*(双星号/星号)和(星号/星号)在参数中的作用是什么?
*(双星号/星号)和(星号/星号)在参数中的作用是什么?
什么是*args
和**kwargs
?
def foo(x, y, *args): def bar(x, y, **kwargs):
admin 更改状态以发布 2023年5月22日
还值得注意的是,调用函数时也可以使用*
和**
。这是一种快捷方式,允许您直接使用列表/元组或字典将多个参数传递给函数。例如,如果您有以下函数:
def foo(x,y,z): print("x=" + str(x)) print("y=" + str(y)) print("z=" + str(z))
您可以执行以下操作:
>>> mylist = [1,2,3] >>> foo(*mylist) x=1 y=2 z=3 >>> mydict = {'x':1,'y':2,'z':3} >>> foo(**mydict) x=1 y=2 z=3 >>> mytuple = (1, 2, 3) >>> foo(*mytuple) x=1 y=2 z=3
注意: mydict
中的键必须与函数 foo
的参数名称完全相同。否则会引发 TypeError
:
>>> mydict = {'x':1,'y':2,'z':3,'badnews':9} >>> foo(**mydict) Traceback (most recent call last): File "", line 1, in TypeError: foo() got an unexpected keyword argument 'badnews'
*args
和**kwargs
是一种常见的习惯用法,可以允许函数接受任意数量的参数,正如Python文档中的more on defining functions部分所述。
*args
将会把所有的函数参数作为一个元组返回:
def foo(*args): for a in args: print(a) foo(1) # 1 foo(1,2,3) # 1 # 2 # 3
**kwargs
将会把所有关键字参数(除了那些对应于形式参数的)作为一个字典返回。
def bar(**kwargs): for a in kwargs: print(a, kwargs[a]) bar(name='one', age=27) # name one # age 27
这两种习惯用法可以与普通参数混合使用,以允许一组固定参数和一些可变参数:
def foo(kind, *args, **kwargs): pass
也可以反过来使用:
def foo(a, b, c): print(a, b, c) obj = {'b':10, 'c':'lee'} foo(100,**obj) # 100 10 lee
*l
习惯用法的另一个用途是在调用函数时解包参数列表。
def foo(bar, lee): print(bar, lee) l = [1,2] foo(*l) # 1 2
在Python 3中,可以在赋值的左侧使用*l
(扩展可迭代解包),尽管在此上下文中返回的是一个列表而不是一个元组:
first, *rest = [1,2,3,4] first, *l, last = [1,2,3,4]
此外,Python 3添加了新的语义(参见PEP 3102):
def func(arg1, arg2, arg3, *, kwarg1, kwarg2): pass
例如,在Python 3中以下代码可以正常运行,但在Python 2中不行:
>>> x = [1, 2] >>> [*x] [1, 2] >>> [*x, 3, 4] [1, 2, 3, 4] >>> x = {1:1, 2:2} >>> x {1: 1, 2: 2} >>> {**x, 3:3, 4:4} {1: 1, 2: 2, 3: 3, 4: 4}
此函数只接受3个位置参数,*
后面的所有参数只能作为关键字参数传递。
注意:
- Python中的
dict
(用于传递关键字参数)的顺序是任意的。然而,在Python 3.6中,关键字参数保证记住插入顺序。 - "
**kwargs
中的元素顺序现在对应于将关键字参数传递给函数的顺序。" - Python 3.6的新特性 - 事实上,CPython 3.6中的所有字典都会作为实现细节记住插入顺序,这在Python 3.7中成为标准。