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

问题描述 投票:3回答:2

我想了解何时应该在Python 2.7中的函数参数中使用varargs vs list类型

假设我编写了一个处理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保证urls是一个元组,但可以接受随机数量的位置参数,这些参数可能是垃圾,例如process_urls(['url1', 'url2'], "this is not a url")

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

python
2个回答
3
投票

第一个,但没有类型检查。类型检查杀死duck typing。如果调用者想要传入生成器,集合或其他可迭代的内容,该怎么办?不要将它们仅限于列表和元组。


0
投票

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

使用单个可迭代参数在大多数情况下会更好,特别是如果调用者已将URL打包到列表中。如果他们有一个列表并需要使用varargs样式,他们需要调用process_urls(*existing_list_of_URLs),不必要地解包,然后重新打包参数。正如John Kugelman在他的回答中建议的那样,你可能不应该使用显式类型检查来强制执行参数的类型,只是假设它是可迭代的并且可以从那里开始工作。

如果您的函数主要使用单独的URL调用,则使用变量参数列表可能比要求列表更好。例如,URL可能是这样的硬编码:process_urls("http://example.com", "https://stackoverflow.com")。或者它们可能在单独的变量中,但要使用的特定变量直接编码为:process_url(primary_url, backup_url)

最后一个选择:支持两种方法!您可以指定您的函数接受一个或多个参数。如果它只有一个,它需要一个包含URL的迭代。如果它有多个参数,它希望每个参数都是一个单独的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由原始字符串中的单个字符组成。这是一个如此尴尬的失败案例,所以你可能想要明确地检查它。您可以选择引发异常,或者只接受单个字符串作为参数,就像它在容器中一样。

© www.soinside.com 2019 - 2024. All rights reserved.