Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > class attribute confusion

Reply
Thread Tools

class attribute confusion

 
 
OAN
Guest
Posts: n/a
 
      12-03-2010
Hi,

i was having a problem with class attributes initiated outside of
__init__. This code is a demonstration of what i mean:

class A():
mylist = []
def __init__(self):
self.mylist.append(1)
pass

class B(A):
def __init__(self):
A.__init__(self)
self.mylist.append(2)

v = A()
print 'v:',v.mylist
x = B()
print 'x:',x.mylist
y = B()
print 'y:',y.mylist
z = A()
print 'z:',z.mylist
print 'v:',v.mylist

I would expect the following result:

v: [1]
x: [1, 2]
y: [1, 2]
z: [1]
v: [1]

Who wouldn't, right? But actually python 2.6(.6) gives me the following
result:

v: [1]
x: [1, 1, 2]
y: [1, 1, 2, 1, 2]
z: [1, 1, 2, 1, 2, 1]
v: [1, 1, 2, 1, 2, 1]

The four variables v,x,y and z now actually share the same 'mylist'!! To
get the correct results, i have to initialize 'mylist' inside of the
__init__ method!

I think this behaviour is totally wrong, since it seems A.__init__(self)
is changing the value inside of A() not inside of the object variable
'self' (that should be x or y)!!


Could someone explain this to me, please?

regards.



 
Reply With Quote
 
 
 
 
Arnaud Delobelle
Guest
Posts: n/a
 
      12-03-2010
OAN <(E-Mail Removed)> writes:

> Hi,
>
> i was having a problem with class attributes initiated outside of
> __init__. This code is a demonstration of what i mean:
>
> class A():
> mylist = []
> def __init__(self):
> self.mylist.append(1)
> pass
>
> class B(A):
> def __init__(self):
> A.__init__(self)
> self.mylist.append(2)
>
> v = A()
> print 'v:',v.mylist
> x = B()
> print 'x:',x.mylist
> y = B()
> print 'y:',y.mylist
> z = A()
> print 'z:',z.mylist
> print 'v:',v.mylist
>
> I would expect the following result:
>
> v: [1]
> x: [1, 2]
> y: [1, 2]
> z: [1]
> v: [1]
>
> Who wouldn't, right? But actually python 2.6(.6) gives me the
> following result:
>
> v: [1]
> x: [1, 1, 2]
> y: [1, 1, 2, 1, 2]
> z: [1, 1, 2, 1, 2, 1]
> v: [1, 1, 2, 1, 2, 1]
>
> The four variables v,x,y and z now actually share the same 'mylist'!!
> To get the correct results, i have to initialize 'mylist' inside of
> the __init__ method!


Yes. See below.

> I think this behaviour is totally wrong, since it seems
> A.__init__(self) is changing the value inside of A() not inside of the
> object variable 'self' (that should be x or y)!!


It's not wrong at all. You expect "mylist" to behave as an instance
attribute, but you defined it as a class attribute. Instance attributes
are naturally initialised in the __init__() method.

--
Arnaud
 
Reply With Quote
 
 
 
 
Steven D'Aprano
Guest
Posts: n/a
 
      12-03-2010
On Fri, 03 Dec 2010 22:54:19 +0100, OAN wrote:

> Hi,
>
> i was having a problem with class attributes initiated outside of
> __init__. This code is a demonstration of what i mean:

[...]
> I would expect the following result:
>
> v: [1]
> x: [1, 2]
> y: [1, 2]
> z: [1]
> v: [1]
>
> Who wouldn't, right?


Everybody who actually understands Python's object model.


> The four variables v,x,y and z now actually share the same 'mylist'!! To
> get the correct results, i have to initialize 'mylist' inside of the
> __init__ method!


Right. If you define a *class* attribute, it lives in the class, not the
instance, and so all instances share the same value.

> I think this behaviour is totally wrong, since it seems A.__init__(self)
> is changing the value inside of A() not inside of the object variable
> 'self' (that should be x or y)!!


A.__init__(self) calls A's init method with self (either x or y) as the
self parameter, but A's init method merely modifies the class attribute
mylist in place. It doesn't create a new list.

The behaviour you're seeing is no different from this:

shared = []
a = {"spam": shared, "ham": 23}
b = {"spam": shared, "ham": 42}
a["spam"].append("parrot")

What would you expect the value of b["spam"] to be?


--
Steven
 
Reply With Quote
 
Omar Abo-Namous
Guest
Posts: n/a
 
      12-04-2010
Am 03.12.2010 23:11, schrieb Arnaud Delobelle:
> OAN<(E-Mail Removed)> writes:
>
>> Hi,
>>
>> i was having a problem with class attributes initiated outside of
>> __init__. This code is a demonstration of what i mean:
>>
>> class A():
>> mylist = []
>> def __init__(self):
>> self.mylist.append(1)
>> pass
>>
>> class B(A):
>> def __init__(self):
>> A.__init__(self)
>> self.mylist.append(2)
>>
>> v = A()
>> print 'v:',v.mylist
>> x = B()
>> print 'x:',x.mylist
>> y = B()
>> print 'y:',y.mylist
>> z = A()
>> print 'z:',z.mylist
>> print 'v:',v.mylist
>>
>> I would expect the following result:
>>
>> v: [1]
>> x: [1, 2]
>> y: [1, 2]
>> z: [1]
>> v: [1]
>>
>> Who wouldn't, right? But actually python 2.6(.6) gives me the
>> following result:
>>
>> v: [1]
>> x: [1, 1, 2]
>> y: [1, 1, 2, 1, 2]
>> z: [1, 1, 2, 1, 2, 1]
>> v: [1, 1, 2, 1, 2, 1]
>>
>> The four variables v,x,y and z now actually share the same 'mylist'!!
>> To get the correct results, i have to initialize 'mylist' inside of
>> the __init__ method!

> Yes. See below.
>
>> I think this behaviour is totally wrong, since it seems
>> A.__init__(self) is changing the value inside of A() not inside of the
>> object variable 'self' (that should be x or y)!!

> It's not wrong at all. You expect "mylist" to behave as an instance
> attribute, but you defined it as a class attribute. Instance attributes
> are naturally initialised in the __init__() method.
>

Could you please point me to a reference in the doc??

Thanks in advance.


 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      12-04-2010
On Sat, 04 Dec 2010 15:00:43 +0100, Omar Abo-Namous wrote:

>>> I think this behaviour is totally wrong, since it seems
>>> A.__init__(self) is changing the value inside of A() not inside of the
>>> object variable 'self' (that should be x or y)!!

>> It's not wrong at all. You expect "mylist" to behave as an instance
>> attribute, but you defined it as a class attribute. Instance
>> attributes are naturally initialised in the __init__() method.
>>

> Could you please point me to a reference in the doc??


http://docs.python.org/reference/datamodel.html

In the section about classes:

"Class attribute assignments update the class’s dictionary ..."

and in the section about class instances:

"Attribute assignments and deletions update the instance’s dictionary,
never a class’s dictionary."

In this specific example, you also have to realise that mylist.append()
mutates the list in place, and doesn't create a new list. It doesn't
matter whether the list comes from a global variable, a local variable,
an instance attribute or a class attribute, append is always an inplace
operation.


--
Steven
 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      12-06-2010
On 12/3/2010 11:58 PM, Steven D'Aprano wrote:
> Right. If you define a *class* attribute, it lives in the class, not the
> instance, and so all instances share the same value.


Unless, of course, an instance binds the same name in its namespace, in
which case it will (usually) mask the class attribute for that instance.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon 2011 Atlanta March 9-17 http://us.pycon.org/
See Python Video! http://python.mirocommunity.org/
Holden Web LLC http://www.holdenweb.com/

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
class object's attribute is also the instance's attribute? 陈伟 Python 9 08-30-2012 03:20 PM
Implied instance attribute creation when referencing a class attribute Russell Warren Python 5 01-17-2006 05:07 AM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
class attribute to instance attribute Donnal Walter Python 4 07-06-2005 04:35 AM
XSLT: Confusion over adding attributes with xml:element and xml:attribute Jordan Willms XML 2 11-09-2004 12:25 AM



Advertisments