beza1e1 said:
Coming back from a bug hunt, i am not sure what to think of this python
behaviour. Here is a demo program:
class A:
def __init__(self, lst=[]):
self.lst = lst
a = A()
b = A()
b.lst.append("hallo")
print a.lst # output: ["hallo"]
The point seems to be, that lst=[] creates a class attribute (correct
name?), which is shared by all instances of A. So a.lst ist the same
object as b.lst, despite the fact, that object a is different to object
b.
It is an *instance attribute* by nature, since it does not reside in the
class object, but only in its instances. The truth is, that a.lst and
b.lst point to the same memory object, so it seems to behave much like
the class attribute
It is no more different from the simple fact, that two variables
(attributes) may point to the same memory object, like you see below:
a = b = []
a.append("hallo")
print b #output: ["hallo"]
In fact, it is usually a bad practice to assign instance attributes a
reference to the compound variable, existing in an external scope. Example:
aList = []
class A:
def __init__(self, lst): #no default attribute!
self.lst = lst
a = A(aList)
aList.append("hallo")
print a.lst #output: ["hallo"]
and your default value (, lst=[]) IS such an variable! The bad thing is,
that the value of the instance attribute 'lst' (example above) depends
on the external variable, which may be independently modified, thus
modifying unexpectedly the instance attribute. The safer approach, of
course is to write:
class A:
def __init__(self, lst): #no default attribute!
self.lst = lst[:] #take a copy
Summing up, is it an error, or a feature? I would say - a feature.
Everyone should be aware, that the argument default values are evaluated
once, and the same value (memory object) is reused at each instance
creation.
Best regards,
Tomasz Lisowski