多个方法好还是很多可选参数好?

9 投票
5 回答
817 浏览
提问于 2025-04-17 00:07

我有一个类,它会向一个远程的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

最终,这个判断需要根据具体情况来决定。我会问自己,下面这两种情况哪个更贴切:

  1. 两种完全不同的算法或操作,虽然它们可能接收相似的信息,但语义完全不同
  2. 一个单一的概念,语义一致,但根据输入的不同有细微差别

如果第一种情况更符合,那就用不同的方法。如果第二种情况更符合,那就使用可选参数。你甚至可以通过检查参数的类型来实现一个方法,这样就可以避免传递额外的参数。

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的使用者可以灵活选择是否需要缓存的功能。

撰写回答