**(双星号/星号)和*(星号/星号)对参数有什么作用?

这是什么意思?*args**kwargs

def foo(x, y, *args):
def bar(x, y, **kwargs):

答案 1

and 是一个常见的习语,它允许任意数量的参数用于函数,如 Python 文档中有关定义函数的更多部分所述。*args**kwargs

将为您提供所有函数参数作为元组*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,语义上用于关键字参数传递,是任意排序的。但是,在Python 3.6中,关键字参数保证记住插入顺序。dict
  • “现在,元素的顺序对应于将关键字参数传递给函数的顺序。 **kwargs
  • 事实上,CPython 3.6中的所有字典都会记住插入顺序作为实现细节,这成为Python 3.7的标准。

答案 2

还值得注意的是,您也可以在调用函数时使用。这是一个快捷方式,允许您使用列表/元组或字典直接将多个参数传递给函数。例如,如果您有以下函数:***

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

注意:中的键必须与函数的参数完全相同命名。否则,它将抛出一个:mydictfooTypeError

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'