*args和**kwargs是什么意思?
def foo(x, y, *args):
def bar(x, y, **kwargs):
*args和**kwargs是什么意思?
def foo(x, y, *args):
def bar(x, y, **kwargs):
当前回答
在函数中同时使用两者的一个好例子是:
>>> def foo(*arg,**kwargs):
... print arg
... print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b)
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b)
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
其他回答
*和**在函数参数列表中有特殊用法*表示参数是列表,**表示参数是一本字典。这允许函数接受任意数量的论据
TL;博士
以下是python编程中*和**的6种不同用例:
要使用*args:def foo(*args):pass接受任意数量的位置参数,这里foo接受任意数目的位置参数,即,以下调用是有效的foo(1)、foo(2,'bar')若要使用**kwargs:def foo(**kwargs):pass接受任意数量的关键字参数,此处“foo”接受任意数量关键字参数,即,以下调用是有效的foo(name='Tom')、foo(name='Tom',age=33)要使用*args,**kwargs:def foo(*args、**kwargs):pass接受任意数量的位置和关键字参数,这里foo接受任意数目的位置和关键词参数,即,以下调用是有效的foo(1,name='Tom')、foo(2,'bar',name='Tom',age=33)要使用*:def foo(pos1,pos2,*,kwarg1):pass强制只接受关键字参数,这里*表示foo只接受pos2之后的关键字参数,因此foo(1,2,3)引发TypeError,但foo(1,2,kwarg1=3)正常。为了表示对更多位置参数不再感兴趣,请使用*_(注意:这只是一个约定):def foo(bar,baz,*_):pass表示(按照约定)foo在工作中只使用bar和baz参数,而忽略其他参数。为了表示对更多关键字参数不再感兴趣,请使用**_(注意:这只是一个约定):def foo(bar,baz,**_):pass意味着(按照约定)foo在工作中只使用bar和baz参数,而忽略其他参数。
好处:从python 3.8开始,可以在函数定义中使用/来强制执行仅限位置的参数。在以下示例中,参数a和b仅是位置性的,而c或d可以是位置性或关键字,e或f必须是关键字:
def f(a, b, /, c, d, *, e, f):
pass
好处2:对同一个问题的回答也带来了一个新的视角,它分享了*和**在函数调用、函数签名、for循环等方面的含义。
*args是一个特殊的参数,可以将0个或多个(位置)参数作为元组。**kwargs是一个特殊的参数,可以将0个或多个(关键字)参数作为字典。
*在Python中,有两种参数位置参数和关键字参数:
*参数:
例如,*args可以采用0个或多个参数作为元组,如下所示:
↓
def test(*args):
print(args)
test() # Here
test(1, 2, 3, 4) # Here
test((1, 2, 3, 4)) # Here
test(*(1, 2, 3, 4)) # Here
输出:
()
(1, 2, 3, 4)
((1, 2, 3, 4),)
(1, 2, 3, 4)
并且,当打印*参数时,将打印4个数字,不带括号和逗号:
def test(*args):
print(*args) # Here
test(1, 2, 3, 4)
输出:
1 2 3 4
并且,args具有元组类型:
def test(*args):
print(type(args)) # Here
test(1, 2, 3, 4)
输出:
<class 'tuple'>
但是,*参数没有类型:
def test(*args):
print(type(*args)) # Here
test(1, 2, 3, 4)
输出(错误):
TypeError:type()需要1或3个参数
并且,正常参数可以放在*args之前,如下所示:
↓ ↓
def test(num1, num2, *args):
print(num1, num2, args)
test(1, 2, 3, 4)
输出:
1 2 (3, 4)
但是,**kwargs不能放在*args之前,如下所示:
↓
def test(**kwargs, *args):
print(kwargs, args)
test(num1=1, num2=2, 3, 4)
输出(错误):
语法错误:无效语法
而且,正常参数不能放在*args之后,如下所示:
↓ ↓
def test(*args, num1, num2):
print(args, num1, num2)
test(1, 2, 3, 4)
输出(错误):
TypeError:test()缺少2个必需的仅关键字参数:“num1”和“num2”
但是,如果正常参数具有默认值,则可以将它们放在*args之后,如下所示:
↓ ↓
def test(*args, num1=100, num2=None):
print(args, num1, num2)
test(1, 2, num1=3, num2=4)
输出:
(1, 2) 3 4
此外,**kwargs可以放在*args之后,如下所示:
↓
def test(*args, **kwargs):
print(args, kwargs)
test(1, 2, num1=3, num2=4)
输出:
(1, 2) {'num1': 3, 'num2': 4}
**克瓦格斯:
例如,**kwargs可以使用0个或多个参数作为字典,如下所示:
↓
def test(**kwargs):
print(kwargs)
test() # Here
test(name="John", age=27) # Here
test(**{"name": "John", "age": 27}) # Here
输出:
{}
{'name': 'John', 'age': 27}
{'name': 'John', 'age': 27}
并且,当打印*kwargs时,将打印两个键:
def test(**kwargs):
print(*kwargs) # Here
test(name="John", age=27)
输出:
name age
并且,kwargs具有dict类型:
def test(**kwargs):
print(type(kwargs)) # Here
test(name="John", age=27)
输出:
<class 'dict'>
但是,*kwargs和**kwargs没有类型:
def test(**kwargs):
print(type(*kwargs)) # Here
test(name="John", age=27)
def test(**kwargs):
print(type(**kwargs)) # Here
test(name="John", age=27)
输出(错误):
TypeError:type()需要1或3个参数
并且,正常参数可以放在**kwargs之前,如下所示:
↓ ↓
def test(num1, num2, **kwargs):
print(num1, num2, kwargs)
test(1, 2, name="John", age=27)
输出:
1 2 {'name': 'John', 'age': 27}
此外,*args可以放在**kwargs之前,如下所示:
↓
def test(*args, **kwargs):
print(args, kwargs)
test(1, 2, name="John", age=27)
输出:
(1, 2) {'name': 'John', 'age': 27}
并且,正常参数和*args不能放在**kwargs之后,如下所示:
↓ ↓
def test(**kwargs, num1, num2):
print(kwargs, num1, num2)
test(name="John", age=27, 1, 2)
↓
def test(**kwargs, *args):
print(kwargs, args)
test(name="John", age=27, 1, 2)
输出(错误):
语法错误:无效语法
对于*args和**kwargs:
实际上,您可以为*args和**kwargs使用其他名称,如下所示*args和**kwargs通常使用:
↓ ↓
def test(*banana, **orange):
print(banana, orange)
test(1, 2, num1=3, num2=4)
输出:
(1, 2) {'num1': 3, 'num2': 4}
*args和**kwargs:允许您向函数传递可变数量的参数。
*args:用于向函数发送非关键字可变长度参数列表:
def args(normal_arg, *argv):
print("normal argument:", normal_arg)
for arg in argv:
print("Argument in list of arguments from *argv:", arg)
args('animals', 'fish', 'duck', 'bird')
将产生:
normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird
**夸尔斯*
**kwargs允许您向函数传递关键字可变长度的参数。如果要处理函数中的命名参数,应使用**kwargs。
def who(**kwargs):
if kwargs is not None:
for key, value in kwargs.items():
print("Your %s is %s." % (key, value))
who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")
将产生:
Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
上下文
python 3.x使用打开包装**与字符串格式一起使用
与字符串格式一起使用
除了本主题中的答案之外,还有一个其他地方没有提到的细节。这扩展了Brad Solomon的答案
使用python str.format时,使用**解包也很有用。
这有点类似于使用python f-string f-string所做的操作,但增加了声明dict以保存变量的开销(f-string不需要dict)。
快速示例
## init vars
ddvars = dict()
ddcalc = dict()
pass
ddvars['fname'] = 'Huomer'
ddvars['lname'] = 'Huimpson'
ddvars['motto'] = 'I love donuts!'
ddvars['age'] = 33
pass
ddcalc['ydiff'] = 5
ddcalc['ycalc'] = ddvars['age'] + ddcalc['ydiff']
pass
vdemo = []
## ********************
## single unpack supported in py 2.7
vdemo.append('''
Hello {fname} {lname}!
Today you are {age} years old!
We love your motto "{motto}" and we agree with you!
'''.format(**ddvars))
pass
## ********************
## multiple unpack supported in py 3.x
vdemo.append('''
Hello {fname} {lname}!
In {ydiff} years you will be {ycalc} years old!
'''.format(**ddvars,**ddcalc))
pass
## ********************
print(vdemo[-1])