Python中变量参数vs列表作为函数参数

Python中变量参数vs列表作为函数参数,python,Python,我想了解在Python2.7的函数参数中何时应该使用varargs而不是列表类型 假设我编写了一个处理URL列表的函数。我可以用两种不同的方式定义函数: 备选案文1: def process_urls(urls): if not isinstance(urls, list) or isinstance(urls, tuple): raise TypeError("urls should be a list or tuple type") 备选案文2: def proces

我想了解在Python2.7的函数参数中何时应该使用varargs而不是列表类型

假设我编写了一个处理URL列表的函数。我可以用两种不同的方式定义函数:

备选案文1:

def process_urls(urls):
  if not isinstance(urls, list) or  isinstance(urls, tuple): 
      raise TypeError("urls should be a list or tuple type")
备选案文2:

 def process_urls(*urls):
      # urls is guaranteed to be a tuple
选项2保证
url
是一个元组,但可以接受随机数量的位置参数,这些位置参数可能是垃圾,例如
process\u url(['url1',url2'],“这不是url”)


从编程的角度来看,首选哪个选项?

第一个选项,但不进行类型检查。类型检查会导致死亡。如果调用方希望传入一个生成器、一个集合或其他iterable,该怎么办?不要将它们仅限于列表和元组。

两者都不是最好的。每种风格在不同的情况下都有好处

在大多数情况下,使用单个iterable参数会更好,尤其是当调用方已经将URL打包到列表中时。如果他们有一个列表并且需要使用varargs样式,他们需要调用
process\u url(*existing\u list\u of\u url)
不必要地解包,然后重新打包参数。正如他在回答中所建议的,您可能不应该使用显式类型检查来强制执行参数的类型,只需假设它是一个iterable并从那里开始工作

如果您的函数主要是通过单独的URL调用的,那么使用变量参数列表可能比需要列表更好。例如,可能URL是这样硬编码的:
process\u URL(“http://example.com", "https://stackoverflow.com)
。或者它们可能在单独的变量中,但要使用的特定变量直接编码在:
process\u url(primary\u url,backup\u url)

最后一个选项:支持两种方法!可以指定函数接受一个或多个参数。如果只得到一个,则需要一个包含URL的iterable。如果它得到多个参数,它希望每个参数都是一个单独的URL。下面是可能的情况:

def process_urls(*args):
    if len(args) == 1:
        args = args[0]

    # do stuff with args, which is an iterable of URLs

这样做的一个缺点是,一个单独传递的URL字符串将被错误地标识为URL序列,每个URL序列由原始字符串中的一个字符组成。这是一个非常尴尬的失败案例,所以您可能需要明确地检查它。您可以选择引发异常,或者只接受单个字符串作为参数,就像它在容器中一样。

似乎有点基于观点。为什么要假设这两种方法中的一种是绝对可取的呢?第一种解决方案的优点是可以向它传递迭代器,这是我看到的唯一区别。我认为在这种特殊情况下,我会倾向于选择1。如果可能的话,我宁愿使用
处理url(url)
并使用标准函数(在本例中为
映射
)来创建批处理。那么为什么不也键入序列和生成器的检查呢?如果一个函数将被如此多的方式使用/滥用,那么进行错误处理和类型检查以使函数尽可能“安全”是有意义的。