**
(双星号)和*
(星号)对参数有什么作用?
它们允许将函数定义为接受并允许用户传递任意数量的参数、位置 和关键字
定义函数
*args
允许任意数量的可选位置参数,它们将被分配给一个名为args
的参数.
**kwargs
允许任意数量的可选关键字参数,它们将位于名为kwargs的参数里.
传递任意数量的参数
还可以分别使用*args
和**kwargs
传递来自列表(或任何可遍历对象)和字典(或任何可映射对象)的参数。
接收参数的函数不必知道它们正在被扩展。
例如,Python 2 的 xrange 没有明确地 要求 *args
,但是因为它需要 3 个整数作为参数:
>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x) # expand here
xrange(0, 2, 2)
Code language: PHP (php)
另一个例子,可以使用 dict 扩展str.format:
>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'
Code language: JavaScript (javascript)
Python 3 中的新功能:使用关键字参数定义函数
def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs):
return arg, kwarg, args, kwarg2, kwargs
Code language: JavaScript (javascript)
用法:
>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2,(3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})
Code language: JavaScript (javascript)
此外,*
可以单独使用来表示后面只有关键字参数,而不允许无限的位置参数。
def foo(arg, kwarg=None, *, kwarg2=None, **kwargs):
return arg, kwarg, kwarg2, kwargs
Code language: JavaScript (javascript)
在这里,kwarg2必须是再次显式命名的关键字参数:
>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})
Code language: JavaScript (javascript)
而且我们不能再接受无限制的位置参数,因为我们没有*args
:
>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback(most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments
but 5 positional arguments(and 1 keyword-only argument) were given
Code language: JavaScript (javascript)
同样,这里我们需要kwarg
按名称给出,而不是按位置给出:
def bar(*, kwarg=None):
return kwarg
Code language: JavaScript (javascript)
在这个例子中,如果试图按kwarg位置传递,会出现错误:
>>> bar('kwarg')
Traceback(most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given
Code language: JavaScript (javascript)
必须显式地将kwarg参数作为关键字参数传递。
>>> bar(kwarg='kwarg')
'kwarg'
Code language: JavaScript (javascript)