在设计Python API时何时应使用可变参数?
在你的API中,什么时候应该使用可变参数函数签名(也就是“varargs”,指的是可以接受不同数量参数的函数,比如*args
)而不是传递一个可迭代对象(像列表或集合)呢?
举个例子,os.path.join
这个函数就使用了可变参数的方式:
os.path.join(first_component, *rest) -> str
而min
函数则可以接受以下两种方式:
min(iterable[, key=func]) -> val
min(a, b, c, ...[, key=func]) -> val
但是any
和all
这两个函数只允许传入一个可迭代对象:
any(iterable) -> bool
4 个回答
这两个接口完全不同。
在一种情况下,你只有一个参数,而在另一种情况下,你有很多参数。
any(1, 2, 3)
TypeError: any() takes exactly one argument (3 given)
os.path.join("1", "2", "3")
'1\\2\\3'
这其实取决于你想强调的内容:any
是针对一个列表的(嗯,算是吧),而 os.path.join
是针对一组字符串的。
所以,在第一种情况下,你需要一个列表;而在第二种情况下,你直接需要这些字符串。
换句话说,接口的表达能力应该是选择参数传递方式的主要依据。
我的经验法则是,当你可能经常在传递一个参数和多个参数之间切换时,就可以使用这种方法。比如说,不用写两个函数(就像一些图形界面的代码):
def enable_tab(tab_name)
def enable_tabs(tabs_list)
或者更糟糕的是,只写一个函数
def enable_tabs(tabs_list)
然后像这样使用它:enable_tabls(['tab1'])
,我更倾向于直接写:def enable_tabs(*tabs)
。虽然像enable_tabs('tab1')
这样看起来有点不对劲(因为用的是复数),但我还是觉得这样比其他方法要好。
当你希望用户在调用代码时能直接指定参数列表,或者只有一个值是常见情况时,可以考虑使用可变参数(varargs)。但如果你预期用户会从其他地方获取参数,就不要使用可变参数。如果不确定,最好还是不要用可变参数。
以你的例子为例,os.path.join 最常见的用法是有一个路径前缀,然后在后面加上文件名或相对路径,所以调用通常看起来像 os.path.join(prefix, some_file)。而 any() 通常用来处理一组数据,当你知道所有元素时,不会用 any([a,b,c]),而是直接用 a or b or c。