如何更新基类创建的属性?可变的默认参数,而不修改该参数?
我在新式类中发现了子类化和字典更新的一个奇怪问题:
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on
win32
>>> class a(object):
... def __init__(self, props={}):
... self.props = props
...
>>> class b(a):
... def __init__(self, val = None):
... super(b, self).__init__()
... self.props.update({'arg': val})
...
>>> class c(b):
... def __init__(self, val):
... super(c, self).__init__(val)
...
>>> b_inst = b(2)
>>> b_inst.props
{'arg': 2}
>>> c_inst = c(3)
>>> c_inst.props
{'arg': 3}
>>> b_inst.props
{'arg': 3}
>>>
在调试中,在第二次调用 (c(3)
) 中,您可以在 a
中看到这一点构造函数 self.props
已经等于 {'arg': 2}
,之后调用 b
构造函数时,它就变成 {'arg': 3}
对于两个对象!
另外,构造函数调用的顺序是:
a, b # for b(2)
c, a, b # for c(3)
如果将 b 中的
self.props.update()
替换为 self.props = {'arg': val}</code>
构造函数,一切都会好的,并且会按预期运行,
但我确实需要更新这个属性,而不是替换它。
I've found a strange issue with subclassing and dictionary updates in new-style classes:
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on
win32
>>> class a(object):
... def __init__(self, props={}):
... self.props = props
...
>>> class b(a):
... def __init__(self, val = None):
... super(b, self).__init__()
... self.props.update({'arg': val})
...
>>> class c(b):
... def __init__(self, val):
... super(c, self).__init__(val)
...
>>> b_inst = b(2)
>>> b_inst.props
{'arg': 2}
>>> c_inst = c(3)
>>> c_inst.props
{'arg': 3}
>>> b_inst.props
{'arg': 3}
>>>
In debug, in second call (c(3)
) you can see that within a
constructor self.props
is already equal to {'arg': 2}
, and when b
constructor is called after that, it becomes {'arg': 3}
for both objects!
also, the order of constructors calling is:
a, b # for b(2)
c, a, b # for c(3)
If you replace self.props.update()
with self.props = {'arg': val}
in b
constructor, everything will be OK, and will act as expected
But I really need to update this property, not to replace it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
props
不应该有这样的默认值。这样做:这是一个常见的 python "gotcha"。
props
should not have a default value like that. Do this instead:This is a common python "gotcha".
您的问题出在这一行:
{} 是可变类型。在 python 中,默认参数值仅计算一次。这意味着您的所有实例都共享同一个字典对象!
要解决此问题,请将其更改为:
Your problem is in this line:
{} is an mutable type. And in python default argument values are only evaluated once. That means all your instances are sharing the same dictionary object!
To fix this change it to:
简短版本:执行此操作:
长版本:
函数定义仅计算一次,因此每次调用它时都会使用相同的默认参数。为了使其按照您的预期工作,每次调用函数时都必须评估默认参数。相反,Python 会生成一个函数对象一次,并将默认值添加到该对象中(如
func_obj.func_defaults
)The short version: Do this:
The long version:
The function definition is evaluated exactly once, so every time you call it the same default argument is used. For this to work like you expected, the default arguments would have to be evaluated every time a function is called. But instead Python generates a function object once and adds the defaults to the object ( as
func_obj.func_defaults
)