在编写Python 3.x函数时,我经常偶然发现编写接受单个值和多个值的代码的问题。 采取这个微不足道的功能:
def capitalize(word):
return word.capitalize()
此函数适用于单个字符串作为输入,但如果提供多个字符串或字符串列表,则会失败。
我们可以将函数转换为接受字符串列表,如果同时提供一个值或多个值,它将起作用。但是,即使我传递了一个值,它也需要包含在一个列表中,并且返回值也是一个列表,即使包含一个元素也是如此。
def capitalize(words):
return [word.capitalize() for word in words]
我最近阅读了* args,并且认为我可以通过将其重写为以下函数来传递包含在列表中的单个字符串作为参数的尴尬:
def capitalize(*words):
return [word.capitalize() for word in words]
在我看来,这是对*args
的合理使用。然而,我发现了一个pyCon 2015谈话,其中发言者声称“可变位置参数有助于消除噪声并使您的代码可读,而不是将单个调用api转换为N api”
https://www.youtube.com/watch?v=WjJUPxKB164在5:30标记。
这是否合理使用* args?如果不是*args
应该如何使用,是否有一种既定的方法来处理单参数和多参数函数?
答案 0 :(得分:2)
是的,可以在这里使用*args
。
当它比参数列表(*args
)更容易阅读时,你应该使用def foo(a,b,c,d,e...)
,并且不会更难知道哪个参数用于什么。
您的示例是良好使用*args
的完美示例,args
中的所有元素都将以相同的方式处理。
当您需要为每个参数执行不同的计算时,应该避免使用它,例如:
def foo(*args):
do_one_stuff(args[1], args[2])
if args[3]:
do_another_stuff(args[3], args[4])
if args[6] != args[7]:
return args[0]
else:
return None
如果您对*args
的使用不当,此示例应该让您感受到函数的功能。
答案 1 :(得分:2)
除了接受的答案(提出一些好处)之外,您还必须考虑如何使用您的功能。使用os.path.join
作为示例,此函数接受*args
是有意义的,因为一个人经常会处理一定数量的路径元素,其中每个路径元素都有自己的名称。例如:
dir_name = os.getcwd()
temp_folder = 'temp'
base_name = 'base_file.txt'
full_path = os.path.join(dir_name, temp_folder, base_name)
另一方面,当您使用无法区分的元素时,这些元素自然会被分组到容器对象中,使用args
更有意义。请考虑str.join
的以下用法。
sentence = 'this is an example sentence'
words = sentence.split()
dash_separated = '-'.join(words)
答案 2 :(得分:0)
* args将额外的位置参数组合成一个元组,以便您可以在函数内处理它们。这是可选。函数内部所需的参数最好是位置参数,在这种情况下,在没有这些参数的情况下调用IDE时会出现错误。
* args可以用作扩展,并且可以在不破坏旧实现的情况下用于将来的开发。
# required args
def test_req(arg1, arg2, arg3):
print arg1, arg2, arg3
# not required
def test_args(*args):
if args:
print args, type(args)
for arg in args:
print arg
test_req(1, 2, 3)
test_args(1, 2, 3)
输出
1 2 3
(1, 2, 3) <type 'tuple'>
1
2
3
答案 3 :(得分:0)
简短的回答是:这取决于。
在python中*args
用于将未知个参数传递给函数。非常类似于在C中调用printf()
接受未知数量的参数。
因此,如果您事先不知道用户希望使用*args
处理多少个参数是一个解决方案。我认为发言者的意图是不使用此功能,除非我们不知道参数的数量。所以如果你想比较你使用的两个参数:
def names_are_equal(name1, name2):
return name1 == name2
而不是
def names_are_equal(*names):
return names[0] == names[1]
另一方面,如果您想要使用未知数量的名称来大写:
def capitalize_names(*names):
return [name.upper() for name in names]
请注意,在解包参数等其他情况下使用*
可能很方便:
>>> l = [1, 2, 3, 4, 5]
>>> a, *b, c = l
>>> a
1
>>> b
[2, 3, 4]
>>> c
5