Bug in __init__?

Bart Ogryczak B.Ogryczak at addr.in.reply-to.invalid
Sun Jan 20 10:34:11 EST 2008


On 2008-01-18, citizen Zbigniew Braniecki testified:
> I found a bug in my code today, and spent an hour trying to locate it 
> and then minimize the testcase.
>
> Once I did it, I'm still confused about the behavior and I could not 
> find any reference to this behavior in docs.
>
> testcase:
>
> class A():
>
>    def add (self, el):
>      self.lst.extend(el)
>
>    def __init__ (self, val=[]):
>      print val
>      self.lst = val

What you want probably is:
	def __init__ (self, val=None):
		if(val == None):
			self.lst = []
		else:
			from copy import copy
			### see also deepcopy
			self.lst = copy(val)

> def test ():
>    x = A()
>    x.add(["foo1","foo2"])
>    b = A()
>
>
> So, what I would expect here is that I will create two instances of 
> class A with empty self.lst property. Right?

Wrong. default value for val gets evaluated only once, creating a list 
(initialy empty). The same list for all of A's instances. 

>>> a = A()
>>> id(a.lst)
13188912

>>> b = A()
>>> id(b.lst)
13188912

Moreover, self.lst = val, does not copy val, rather it creates binding 
between self.list and val. So whatever you do to self.list, it affects 
val (and vice-versa).

>>> x = []
>>> c = A(x)
>>> id(x)
10508368
>>> id(c.lst)
10508368
>>> c.lst.append('wrong')
>>> x
['wrong']

bart
-- 
"We're coming in low out of raising sun and about mile up we'll put on music"
http://candajon.azorragarse.info/ http://azorragarse.candajon.info/



More information about the Python-list mailing list