多个方法好还是很多可选参数好?
我有一个类,它会向一个远程的API发送请求。我想减少我发送请求的次数。这个类中的一些方法会发送相同的API请求(但原因不同),所以我希望它们能够“共享”一个缓存的API响应。
我不太确定使用可选参数还是多个方法更符合Python的风格,因为这些方法在发送API请求时有一些必需的参数。
以下是我认为的几种方法,你觉得哪种最好呢?
class A:
def a_method( item_id, cached_item_api_response = None):
""" Seems awkward having to supplied item_id even
if cached_item_api_response is given
"""
api_response = None
if cached_item_api_response:
api_response = cached_item_api_response
else:
api_response = ... # make api call using item_id
... #do stuff
或者这样:
class B:
def a_method(item_id = None, cached_api_response = None):
""" Seems awkward as it makes no sense NOT to supply EITHER
item_id or cached_api_response
"""
api_response = None
if cached_item_api_response:
api_response = cached_item_api_response
elif item_id:
api_response = ... # make api call using item_id
else:
#ERROR
... #do stuff
或者这样更合适吗?
class C:
"""Seems even more awkward to have different method calls"""
def a_method(item_id):
api_response = ... # make api call using item_id
api_response_logic(api_response)
def b_method(cached_api_response):
api_response_logic(cached_api_response)
def api_response_logic(api_response):
... # do stuff
5 个回答
1
最终,这个判断需要根据具体情况来决定。我会问自己,下面这两种情况哪个更贴切:
- 两种完全不同的算法或操作,虽然它们可能接收相似的信息,但语义完全不同
- 一个单一的概念,语义一致,但根据输入的不同有细微差别
如果第一种情况更符合,那就用不同的方法。如果第二种情况更符合,那就使用可选参数。你甚至可以通过检查参数的类型来实现一个方法,这样就可以避免传递额外的参数。
2
你在 class B
中使用的方法没有问题。为了让人一眼就能看出你需要包含 item_id
或者 cached_api_response
,我建议把错误检查放在前面:
class B:
def a_method(item_id = None, cached_api_response = None):
"""Requires either item_id or cached_api_response"""
if not ((item_id == None) ^ (cached_api_response == None)):
#error
# or, if you want to allow both,
if (item_id == None) and (cached_api_response == None):
# error
# you don't actually have to do this on one line
# also don't use it if cached_item_api_response can evaluate to 'False'
api_response = cached_item_api_response or # make api call using item_id
... #do stuff
5
通常在写方法的时候,有人会说一个方法或者对象应该只做一件事,而且要把这件事做好。如果你的方法参数越来越多,代码里需要写越来越多的判断(if语句),那很可能说明你的代码在做不止一件事。尤其是当这些参数导致完全不同的行为时,更是如此。其实,可能通过创建不同的类,重载方法,来实现相同的行为会更好。
你可以考虑使用类似这样的方式:
class BaseClass(object):
def a_method(self, item_id):
response = lookup_response(item_id)
return response
class CachingClass(BaseClass):
def a_method(self, item_id):
if item_id in cache:
return item_from_cache
return super(CachingClass, self).a_method(item_id)
def uncached_method(self, item_id)
return super(CachingClass, self).a_method(item_id)
这样一来,你就可以把查找响应的逻辑和缓存的逻辑分开,同时也让API的使用者可以灵活选择是否需要缓存的功能。