Python methods: default parameter values are evaluated ONCE
我发现在新的样式类中,子类化和字典更新有一个奇怪的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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} >>> |
在DEBUG中,在第二个调用(
另外,构造函数调用的顺序是:
1 2 | a, b # for b(2) c, a, b # for c(3) |
如果用
但我真的需要更新这个属性,而不是替换
1 2 3 4 5 | class a(object): def __init__(self, props=None): if props is None: props = {} self.props = props |
这是一个常见的python"gotcha"。
您的问题在这一行:
1 | def __init__(self, props={}): |
是可变类型。在python中,默认参数值只计算一次。这意味着所有实例都共享同一个字典对象!
要修复此问题,请将其更改为:
1 2 3 4 5 | class a(object): def __init__(self, props=None): if is None: props = {} self.props = props |
简短版本:执行此操作:
1 2 3 4 5 6 7 8 9 10 11 12 | class a(object): def __init__(self, props=None): self.props = props if props is not None else {} 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) |
长版本:
函数定义只计算一次,因此每次调用它时都使用相同的默认参数。要使其按预期工作,每次调用函数时都必须计算默认参数。但是,python只生成一次函数对象,并将默认值添加到对象中(如