[英]__init__() got multiple values for keyword argument 'bar'
What seems like a simple pattern for allowing a variable number of positional arguments along with a defaulted named arg doesn't work. 看起来像一个简单的模式,它不允许可变数量的位置参数以及默认名称的arg起作用。 I think I can overcome this by using
**kwargs
, but is there something more straightforward I am doing wrong? 我想我可以通过使用
**kwargs
来克服这个问题,但是我做错了什么更直接的方法吗?
Why doesn't this work? 为什么不起作用?
class Foo(obect):
"""Baffling"""
def __init__(self, bar=None, *args):
pass
foo = Foo(1) #works
foo = Foo(1, bar=2) # explodes
----> 1 foo = Foo(1, bar='baz')
TypeError: __init__() got multiple values for keyword argument 'bar'
How is the above code passing a duplicate bar
keyword argument? 上面的代码如何传递重复的
bar
关键字参数?
In Python, named attributes are used after non-named (like *args
). 在Python中,已命名属性在未命名之后使用(例如
*args
)。 So you should change your __init__
as: 因此,您应将
__init__
更改为:
def __init__(self, *args, bar=None):
Here is the example: 这是示例:
class Foo(object):
"""Baffling"""
def __init__(self, *args, bar=None):
self.bar = bar
foo = Foo(1, bar=2) # explodes
foo.bar
Will return: 将返回:
Out[...]: 2
PS Anyway it is not a good idea to mix *args
, **kwargs
and named attributes. PS无论如何,混合
*args
, **kwargs
和命名属性不是一个好主意。 I recommend you to avoid it. 我建议您避免这种情况。
Named arguments can be passed both by position and by name: 命名参数既可以按位置也可以按名称传递:
>>> def foo(a):
... print(a)
...
>>> foo(1)
1
>>> foo(a=2)
2
If you pass positional and keyword arguments, they get assigned in order. 如果您传递位置和关键字参数,则会按顺序分配它们。 In your case, 1 gets assigned to the first positional argument (
bar
), then bar=2
assigns the the argument named bar
. 在您的情况下,将1分配给第一个位置参数(
bar
),然后bar=2
分配名为bar
的参数。 Thus, both assign to the name bar
, creating a conflict. 因此,两者都分配给名称
bar
,从而产生冲突。
You can pass additional arguments after your named one: 您可以在命名的参数之后传递其他参数:
>>> def foo(bar=None, *args):
... print('args=%r, bar=%r' % (args, bar))
...
... foo(2, 1) # bar=2, *args=(1,)
args=(1,), bar=2
In Python3, you can also make your parameter keyword only: 在Python3中,您还可以仅将parameter关键字设置为:
>>> def foo(*args, bar=None):
... print('args=%r, bar=%r' % (args, bar))
...
... foo(1, bar=2)
args=(1,), bar=2
This also works when you do not take any variadic arguments: 当您不接受任何可变参数时,这也适用:
>>> def foo(*, bar=None):
... print('args=%r, bar=%r' % ('undefined', bar))
...
... foo(bar=2)
args='undefined', bar=2
>>> foo(1, bar=2)
TypeError: foo() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
In Python2, only **kwargs
is allowed after *args
. 在Python2中,在
*args
之后仅允许**kwargs
。 You can emulate named parameters by popping them from kwargs
: 您可以通过从
kwargs
弹出命名参数来模拟它们:
>>> def foo(*args, **kwargs):
... bar = kwargs.pop("bar")
... print('args=%r, bar=%r' % (args, bar))
...
... foo(1, bar=2)
args=(1,), bar=2
If you want named-only parameters without variadic positional and named parameters, you must raise errors yourself: 如果您想要不带可变参数位置和命名参数的仅命名参数,则必须自己引发错误:
>>> def foo(*args, **kwargs):
... bar = kwargs.pop('bar')
... if args or kwargs:
... raise TypeError
... print('args=%r, bar=%r' % ('undefined', bar))
...
... foo(bar=2)
args='undefined', bar=2
>>> foo(1, bar=2)
TypeError
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.