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

发布时间 2023-10-29 15:28:37作者: 小满独家

内容来自 DOC https://q.houxu6.top/?s=**(双星号/星号)和 *(星号/星号)对参数有什么作用?

在以下函数定义中,*args**kwargs 分别表示什么意思?

def foo(x, y, *args):
    pass

def bar(x, y, **kwargs):
    pass

关于参数的补充问题,可以参考 What do ** (double star/asterisk) and * (star/asterisk) mean in a function call?


*args**kwargs 是常见的用法,允许在函数中接受任意数量的参数,正如 Python 教程中的 关于定义函数的更多内容 一节所描述。

*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, bar=None, \*\*kwargs):
    print(kind, args, bar, kwargs)

foo(123, 'a', 'b', apple='red')
# 123 ('a', 'b') None {'apple': 'red'}

反过来也是可行的:

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)

baz = [1, 2]

foo(*baz)
# 1 2

在 Python 3 中,可以在左侧使用 *l(扩展迭代器解包),但在这种情况下会给出列表而不是元组:

first, *rest = [1, 2, 3, 4]
# first = 1
# rest = [2, 3, 4]

另外,Python 3 添加了一个新的语义(参见 PEP 3102):

def func(arg1, arg2, arg3, \*, kwarg1, kwarg2):
    pass

这样的函数只接受前三个位置参数,* 之后的所有内容只能作为关键字参数传递。

注意:

Python 的 dict 语义上用于关键字参数传递,但是它们的顺序是任意的。然而,在 Python 3.6+ 中,关键字参数保证记住插入顺序。实际上,CPython 3.6 中的所有 dict 都会以实现细节的形式记住插入顺序,这在 Python 3.7 中成为标准。