Class instance problem?

Z

Zhao Huang

Hi,

I'm new to python and I've come across a problem with my objects
corrupting each other.

class aclass:
num = 0
l = [[],[]]

a = aclass()
b = aclass()
a.l.append(1)
print "a.l",a.l
print "b.l",b.l

My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command

a.num = 1

doesn't change b.num's. This is inconsistency is driving me crazy.
What am I doing wrong?

Thanks for any help
 
D

David Eppstein

I'm new to python and I've come across a problem with my objects
corrupting each other.

class aclass:
num = 0
l = [[],[]]

a = aclass()
b = aclass()
a.l.append(1)
print "a.l",a.l
print "b.l",b.l

My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command

a.num = 1

doesn't change b.num's. This is inconsistency is driving me crazy.
What am I doing wrong?

When you set num and l in the class body, you're making them class-wide
variables (like static in Java). If you want a different one per
object, you need to set them in the __init__ method.
 
D

Dennis Lee Bieber

Hi,

I'm new to python and I've come across a problem with my objects
corrupting each other.

class aclass:
num = 0
l = [[],[]]

My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command
ONE: read the documentation about mutable and immutable objects.
TWO: num and l are not INSTANCE variables, they are class-wide
definitions. Therefore, ALL instances (objects) created from the class
are using the SAME num and l
a.num = 1

doesn't change b.num's. This is inconsistency is driving me crazy.

Refer back to point "ONE".

Now, to cut to the chase, what you WANT is

class aclass:
def __init__(self):
self.num = 0
self.l = [ [], [] ]

This results in INSTANCE specific variables being created when
the object itself is created:
a = aclass()
b = aclass()
a.l.append([1, 2, 3])
a.num = 4
print a.num 4
print a.l [[], [], [1, 2, 3]]
print b.num 0
print b.l [[], []]

--
 
S

Shalabh Chaturvedi

Zhao said:
Hi,

I'm new to python and I've come across a problem with my objects
corrupting each other.

class aclass:
num = 0
l = [[],[]]

These create class attributes, not instance attributes. For example,
after this you can try:

print aclass.num
print aclass.l

a = aclass()
b = aclass()
a.l.append(1)

Since the instance a does not have an 'l' attribute, a.l refers to the
class attribute aclass.l. You can verify this at this point by:

print a.l is aclass.l # 'is' checks identity of objects

Also you do a.l.append(1). The .append() (note the '.') tells python to
append to the referred object. You are calling a method on the list
object and you end up appending to aclass.l.
print "a.l",a.l
print "b.l",b.l

Also try, print a.l is b.l. There is only one list object, it is on the
class aclass but can be referenced through a.l and b.l.
My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command

a.num = 1

Aha, here you use the '=' operator. Compare with operation on the list l
earlier, where you used the '.' operator and a method name 'append'. The
'=' creates an instance attribute 'num' on a.
doesn't change b.num's.

Nope, there is no instance attribute 'num' on b as of now. print b.num
merely prints aclass.num.

Now that you know about '=', you can try

a.L = []
b.L = []
a.L.append(1)
print a.L, b.L

And you'll see that you have two distinct lists. Actually three distinct
ones if you count aclass.l. If you only need instance attributes, don't
put them on the class. Use the following:

class aclass:
def __init__(self):
self.L = []
self.num = 0

a = aclass()
b = aclass()
# play with a.L, b.L, a.num, b.num


This is inconsistency is driving me crazy.
What am I doing wrong?


Hope the above helped.
 
M

Miki Tebeka

Hello Zhao,
class aclass:
num = 0
l = [[],[]]

a = aclass()
b = aclass()
a.l.append(1)
print "a.l",a.l
print "b.l",b.l

My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command

a.num = 1

doesn't change b.num's. This is inconsistency is driving me crazy.
What am I doing wrong?
Several things :)
First, "num" and "l" are both *class* properties and not object
properties. The right way to do this is:
class aclass:
def __init__(self):
num = 0
l = [[], []]

Each class method has a `self' parameter which is the object that is
currently called. See the tutorial for more explanation on the subject.

Second "num" and "l" are named bounded to the same objects objects both
in a and b. When you do `a.num =1' you change the binding of a.num to 1.
When you do a.l.append you append to the same objects as in b.l.

HTH.
Miki
 
R

Riccardo Attilio Galli

Hello Zhao,
class aclass:
num = 0
l = [[],[]]

a = aclass()
b = aclass()
a.l.append(1)
print "a.l",a.l
print "b.l",b.l

My expectation is that a,b are separate objects, but appending to
a's l also appends to b's l. Why does this occur? On the other hand,
the command

a.num = 1

doesn't change b.num's. This is inconsistency is driving me crazy.
What am I doing wrong?
Several things :)
First, "num" and "l" are both *class* properties and not object
properties. The right way to do this is:
class aclass:
def __init__(self):
num = 0
l = [[], []]

You surely intended:

class aclass:
def __init__(self):
self.num = 0
self.l = [[], []]

(for Zhao's mental sanity)

Riccardo

--
-=Riccardo Galli=-

_,e.
s~ ``
~@. ideralis Programs
.. ol
`**~ http://www.sideralis.net
 

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

Members online

No members online now.

Forum statistics

Threads
474,197
Messages
2,571,040
Members
47,635
Latest member
SkyePurves

Latest Threads

Top