I have created a class:
class PolicyJSON:
def __init__(this, path:str="", values:dict={}, children:list=[], parent=None):
this.path = path
this.values = values
this.children = children
this.parent = parent
this.path = this.getfullpath()
This class is hierarchical – it can have many children of it’s type, and it can have a parent (of it’s type). I have wrote several hundreds of lines of code already, basically creating whole hierarchy, my codes are working just okay so I was happy, until now.
I have started spawning multiple instances of these hierarchies (see mymethod below), only to find out that for some reason python simply ignores parameter default values defined in __init__(), and, for some weird reason, it’s putting existing variables in these places!
Can someone please explain to me, what is going on here, and how to make class behave like a class?
Basically, I have lots of code that generates PolicyJSON instances with hierarchical data, and then, I do this:
# here is lots of code that also creates PolicyJSON
# instances, then I have something like below:
def mymethod(someparams):
result = PolicyJSON()
return result
myinstance = mymethod(...)
At this point, result, instead of being empty, already has data filled in – I can do result.children and it will return actual data! When I paused debugger at that result = PolicyJSON() line, and then Jumped in (F11), the __init__() constructor had its parameters filled in with data (i.e. children:list=[] was not [], but an actual array with data. How? Why? How can I make it behave "the normal" way?
>Solution :
Let’s consider a minimal example:
... def __init__(self, a=[]):
... self.a = a
...
>>> a = A()
>>> a.a
[]
>>> a.a.append(4)
>>> a.a
[4]
>>> b = A()
>>> b
<__main__.A object at 0x105bb8260>
>>> b.a
[4]
>>>
Your defaults are evaluated at the time the method is created, not each time it’s called. This affects any mutable object you provide as a default. Values like integers, floating point numbers, and strings are not affected.
Rather you can specify a default is None and then set it appropriately within the __init__ method.
>>> class B(object):
... def __init__(self, b=None):
... self.b = (b if b is not None else [])
...
>>> b = B()
>>> b.b.append(9)
>>> b.b
[9]
>>> c = B()
>>> c.b
[]
>>>