user2256235
user2256235

Reputation: 399

some confusion with variables declared by python class

I have the class

>>> class Foo:
...     ls=[]
...
>>> f1=Foo()
>>> f2=Foo()
>>> f1.ls.append(1)
>>> f1.ls.append(2)
>>> print f1.ls
[1, 2]
>>> print f2.ls   
[1, 2]                #I expect its result is empty [], why
>>> f2.ls=[]
>>> print f1.ls       
[1, 2]
>>> print f2.ls
[]
           # If f1.ls and f2.ls refer to the same list, since i modify f2.ls,
           # the f1.ls is empty ,too. Does the statement 'f2.ls=[]' add new attribute
           # to f2. Where do f1.ls and f2.ls refer and how it happens

I want to use one class and declare many variables. If I hope all variables have different lists. Do I do like this

class Foo:
    pass
f1=Foo()
f2=oo()
f1.ls=[]
f2.ls=[]
do others

Are there some more simple and better methods. Forgive my ignorant for python class. Thanks in advance

Upvotes: 1

Views: 115

Answers (4)

Bardia Heydari
Bardia Heydari

Reputation: 774

ls is a static variable as you defined. you self.ls in the init so you can have different ls in the memory.

Upvotes: 0

thefourtheye
thefourtheye

Reputation: 239443

When you say

class Foo:
    ls=[]

ls is defined as a class variable and all the objects which you create will will have a variable with the same name and that variable will point to the current value in the class's ls value.

When you say

f1.ls.append(1)

You are actually mutating the original object. That's why the change is reflected in f2 as well (since they both are referring to the same object). But when you say

f2.ls = []

You are actually creating a variable on the f2 object, which refers to an empty list object. Now, the ls object is different from f1's ls. You can confirm this with this statement

print f1.ls is f2.ls    # Will print False
print f1.ls is Foo.ls   # Will print True

If you actually wanted to get a new object whenever you created an object. You have to create an instance variable, like this

class Foo:
    def __init__(self):
        self.ls = []

f1, f2 = Foo(), Foo()
print f1.ls is f2.ls    # Will print False

Now you are binding ls to the current instance of the class and making it point to an empty list. So, this will be different for each instance.

Upvotes: 2

jayelm
jayelm

Reputation: 7657

Defining a variable directly inside a class gives a class-level variable. Thus, ls isn't unique to all instances, but is instead a property of the class Foo. It can still be accessed, however, through its instances, which is what you did.

class Foo:
    ls = []

So that:

>>> f1 = Foo()
>>> f2 = Foo()
>>> Foo.ls.append(1)
>>> Foo.ls
[1]
>>> f1.ls
[1]
>>> f2.ls
[1]

An instance level variable is unique to each instance, and can be defined in the __init__ function, as such:

class Foo:
    def __init__(self):
        self.ls = []

In this way, class Foo has no attribute ls; rather, each instance constructed with __init__ does:

>>> f1 = Foo()
>>> f2 = Foo()
>>> Foo.ls.append(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class Foo has no attribute 'ls'
>>> f1.ls.append(1)
>>> f1.ls
[1]
>>> f2.ls
[]

Upvotes: 2

user2357112
user2357112

Reputation: 280227

Class-level assignments create class variables. To create instance variables, do so in the constructor:

def __init__(self):
    self.ls = []

Upvotes: 3

Related Questions