Magic class member variable initialization with lists

N

neoone

Hi, I reported a bug to the bugtracker (issue 1443), but it was
rejected with the comment:

"Go ask on c.l.py why this is not a bug"

After decrypting c.l.py to the name of this group, I'll do as I was
told so nicely, because I really think it is a misconcept, and cost me
two days because I couldn't believe it.

So here's the problem:
The Initialization of member variables with lists leads to strange
behavior.

The member variable is common to each instance of a class, if the
datatype is a list-Object (and presumable any other PyObject)

Example:
#-------------------------------------------------------
class Proof:
a=[]
b=[]

def __init__(self):
print self.a, self.b, self
self.a.append("STICKYARRAY")
self.b=["NONSTICKY ASSIGN"]

if __name__ == "__main__":
p1=Proof()
p2=Proof()
#-------------------------------------------------------

The execution of this results in:
[] [] <__main__.Proof instance at 0x00BA7120>
['STICKYARRAY'] [] <__main__.Proof instance at 0x00BA7148>

So the initialized list a is the same in both instances, but they are
completely different objects.

Well, I can think of the coders problem, that when creating the
object, always the same copy of the list object is being taken which
has once been defined, but it doesn't makes sense, because they are
not really static like C++, because as soon as you reassign them, they
are lost.

Bye,
Neo
 
M

marek.rocki

This is the expected behaviour. The reference on classes (http://
docs.python.org/ref/class.html) says:
Variables defined in the class definition are class variables;
they are shared by all instances. To define instance variables,
they must be given a value in the __init__() method or in
another method. Both class and instance variables are
accessible through the notation ``self.name'', and an instance
variable hides a class variable with the same name when
accessed in this way.

In your example, 'a' is a class variable, so it's shared by all
instances. 'b' is also a class variable, but in the __init__ method
you create an instance variable with the same name 'b', which takes
precedence over the class-level variable, so 'b' isn't shared.

I think what you need is:

class Proof:
def __init__(self):
self.a = []
self.b = []
# other things

Regards,
Marek
 
D

Dennis Lee Bieber

So here's the problem:
The Initialization of member variables with lists leads to strange
behavior.

The member variable is common to each instance of a class, if the
datatype is a list-Object (and presumable any other PyObject)

Example:
#-------------------------------------------------------
class Proof:
a=[]
b=[]
These are not instance members, but class-wide (shared) names.
def __init__(self):
print self.a, self.b, self
self.a.append("STICKYARRAY")

Here you MUTATE (ie, you have gone inside the object referenced by
self.a, and changed the insides) the "a" list.
self.b=["NONSTICKY ASSIGN"]

Here you rebind, creating an actual instance member. Unqualified
names (that is, a name that does not have a following ".xxx" or a "[x]")
are rebound in assignments -- the name gets attached to the object on
the RHS, and thereby unhooked from the former object. Qualified names
(a.append(), or a[0]) don't do anything with the name itself, instead
"going inside the object" and changing something at that level. a[0] =
xxx rebinds, not the "a", but the zeroth element inside "a" to "xxx"
object.

If you really want classwide shared members, you must either always
use mutating operations (.append(), say), OR use the class name (Proof.b
= "xxx"). For true instance members, you should initialize them in the
__init__() method: self.instance_member = initial_value
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,991
Messages
2,570,217
Members
46,805
Latest member
ClydeHeld1

Latest Threads

Top