Under very simple circumstances, two objects can unintentionally share an attribute such as a list. Is there a reasoning behind this design choice of the language?
I define a class A
with a list attribute children
set by __init__
and empty by default. When I create two instances of A
, they share the same empty list instead of two separate lists being created. Adding a child to one automatically adds it to the other as well.
class A:
def __init__(self, children=[]):
self.children = children
a1, a2 = A(), A()
print(a1, a1.children, id(a1.children))
print(a2, a2.children, id(a2.children))
Output:
<__main__.A object at 0x1023d9f28> [] 4331130696
<__main__.A object at 0x1023f6080> [] 4331130696
Both objects have the same empty list as children
, instead of two separate empty lists, which is what I would expect. This can be realized e. g. like this:
class A:
def __init__(self, children=None):
if children is not None:
self.children = children
else:
self.children = [] # creates a fresh new empty list each time
But having to write this boilerplate if
-block defeats IMO the benefit of default argument values. Why does Python behave in this way and what is the most pythonic way to handle the situation?