python中函数的动态输入数量

时间:2019-05-30 12:24:09

标签: python

使用*args和获取列表作为输入以使函数具有动态输入数量有什么区别。

与其他方法相比,这两种方法有什么优势吗?

1 个答案:

答案 0 :(得分:4)

函数期望的参数类型不同。它们是可以互换的。您选择的内容主要是偏好设置(尽管请参阅答案末尾的例外)。

给出以下定义:

# Separate arguments
def foo(*args):
    pass

# Single sequence of arguments
def bar(list_of_args):
    pass

x = [1, 2, 3]

这两个调用是等效的:

foo(1, 2, 3)
foo(*x)      # Unpack a list before calling

这两个调用是等效的:

bar(x)
bar([1, 2, 3])  # Explicitly pack individual arguments

您在问题中提到了**args。参数的名称不是很重要;特殊行为由一个或两个*开头的参数名称表示。一个*表示任意位置参数,如上所示。两个*表示任意关键字参数。按照惯例,两个最常用的名称是*args**kwargs

与上面类似的简短示例:

# Arbitrary keyword arguments
def foo(**kwargs):
    pass

# Single dict d
def bar(d):
    pass

d = {'a': 1, 'b': 2}

# Equivalent
foo(*d)
foo(a=1, b=2)

# Equivalent
bar(d)
bar(dict(a=1, b=2))

例外:如果函数实际上希望对值进行变异,则不能使用* / **参数有效地替换该值。示例:

def foo(**kwargs):
    kwargs['foo'] = 3

这会将'foo'到3的映射添加到字典,但这是为调用foo而创建的临时字典。函数外没有任何东西可以引用该字典,因此,foo返回后,更新不会产生任何作用。

类似的逻辑适用于*args,但是由于args是一个元组,并且元组是不可变的,因此无论如何您都无法使用该参数。就是说,如果该函数确实需要一个列表,而不仅仅是一个任意的参数序列,则必须定义函数来处理该列表。

def foo(some_list):    # can't use *args here
    some_list.append(3)

您不能有效地将其定义为

def foo(*args):
    args.append(3)

因为foo收到一个临时元组,而不是一个列表对象