Python methods: default parameter values ​​evaluated by ONCE

I found a strange problem with subclassing and updating the dictionary 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 debugging in the second call ( c(3)), you can see that the aconstructor is self.propsalready equal inside {'arg': 2}, and after that the constructor is called after it b, it becomes {'arg': 3}for both objects!

also the order of the constructor calls:

  a, b    # for b(2)
  c, a, b # for c(3)

If you change self.props.update()to self.props = {'arg': val}in the constructor b, everything will be fine and will act as expected

But I really need to update this property, not replace

+5
source share
3 answers

props . :

class a(object):
    def __init__(self, props=None):
        if props is None:
            props = {}
        self.props = props

gotcha.

+9

:

def __init__(self, props={}):

{} . python . , -!

, :

class a(object):
    def __init__(self, props=None):
        if is None:
            props = {}
        self.props = props
+7

: :

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)

:

A function definition is evaluated exactly once, so each time you call it, the same default argument is used. For this to work as you expect, the default arguments must be evaluated every time the function is called. But instead, Python generates a function object once and adds default values ​​to the object (like func_obj.func_defaults)

+1
source

All Articles