By 8steve8


2009-11-05 13:19:55 8 Comments

What I want is this behavior:

class a:
    list = []

x = a()
y = a()

x.list.append(1)
y.list.append(2)
x.list.append(3)
y.list.append(4)

print(x.list) # prints [1, 3]
print(y.list) # prints [2, 4]

Of course, what really happens when I print is:

print(x.list) # prints [1, 2, 3, 4]
print(y.list) # prints [1, 2, 3, 4]

Clearly they are sharing the data in class a. How do I get separate instances to achieve the behavior I desire?

8 comments

@Swapnil 2017-01-16 19:03:10

Although the accepted anwer is spot on, I would like to add a bit description.

Let's do a small exercise

first of all define a class as follows:

class A:
    temp = 'Skyharbor'

    def __init__(self, x):
        self.x = x

    def change(self, y):
        self.temp = y

So what do we have here?

  • We have a very simple class which has an attribute temp which is a string
  • An __init__ method which sets self.x
  • A change method sets self.temp

Pretty straight forward so far yeah? Now let's start playing around with this class. Let's initialize this class first:

a = A('Tesseract')

Now do the following:

>>> print(a.temp)
Skyharbor
>>> print(A.temp)
Skyharbor

Well, a.temp worked as expected but how the hell did A.temp work? Well it worked because temp is a class attribute. Everything in python is an object. Here A is also an object of class type. Thus the attribute temp is an attribute held by the A class and if you change the value of temp through A (and not through an instance of a), the changed value is going to be reflected in all the instance of A class. Let's go ahead and do that:

>>> A.temp = 'Monuments'
>>> print(A.temp)
Monuments
>>> print(a.temp)
Monuments

Interesting isn't it? And note that id(a.temp) and id(A.temp) are still the same.

Any Python object is automatically given a __dict__ attribute, which contains its list of attributes. Let's investigate what this dictionary contains for our example objects:

>>> print(A.__dict__)
{
    'change': <function change at 0x7f5e26fee6e0>,
    '__module__': '__main__',
    '__init__': <function __init__ at 0x7f5e26fee668>,
    'temp': 'Monuments',
    '__doc__': None
}
>>> print(a.__dict__)
{x: 'Tesseract'}

Note that temp attribute is listed among A class's attributes while x is listed for the instance.

So how come that we get a defined value of a.temp if it is not even listed for the instance a. Well that's the magic of __getattribute__() method. In Python the dotted syntax automatically invokes this method so when we write a.temp, Python executes a.__getattribute__('temp'). That method performs the attribute lookup action, i.e. finds the value of the attribute by looking in different places.

The standard implementation of __getattribute__() searches first the internal dictionary (dict) of an object, then the type of the object itself. In this case a.__getattribute__('temp') executes first a.__dict__['temp'] and then a.__class__.__dict__['temp']

Okay now let's use our change method:

>>> a.change('Intervals')
>>> print(a.temp)
Intervals
>>> print(A.temp)
Monuments

Well now that we have used self, print(a.temp) gives us a different value from print(A.temp).

Now if we compare id(a.temp) and id(A.temp), they will be different.

@Projesh Bhoumik 2018-08-07 14:11:52

To protect your variable shared by other instance you need to create new instance variable each time you create an instance. When you are declaring a variable inside a class it's class variable and shared by all instance. If you want to make it for instance wise need to use the init method to reinitialize the variable as refer to the instance

From Python Objects and Class by Programiz.com:

__init__() function. This special function gets called whenever a new object of that class is instantiated.

This type of function is also called constructors in Object Oriented Programming (OOP). We normally use it to initialize all the variables.

For example:

class example:
    list=[] #This is class variable shared by all instance
    def __init__(self):
        self.list = [] #This is instance variable referred to specific instance

@TheQabalist 2014-01-31 23:52:55

So nearly every response here seems to miss a particular point. Class variables never become instance variables as demonstrated by the code below. By utilizing a metaclass to intercept variable assignment at the class level, we can see that when a.myattr is reassigned, the field assignment magic method on the class is not called. This is because the assignment creates a new instance variable. This behavior has absolutely nothing to do with the class variable as demonstrated by the second class which has no class variables and yet still allows field assignment.

class mymeta(type):
    def __init__(cls, name, bases, d):
        pass

    def __setattr__(cls, attr, value):
        print("setting " + attr)
        super(mymeta, cls).__setattr__(attr, value)

class myclass(object):
    __metaclass__ = mymeta
    myattr = []

a = myclass()
a.myattr = []           #NOTHING IS PRINTED
myclass.myattr = [5]    #change is printed here
b = myclass()
print(b.myattr)         #pass through lookup on the base class

class expando(object):
    pass

a = expando()
a.random = 5            #no class variable required
print(a.random)         #but it still works

IN SHORT Class variables have NOTHING to do with instance variables.

More clearly They just happen to be in the scope for lookups on instances. Class variables are in fact instance variables on the class object itself. You can also have metaclass variables if you want as well because metaclasses themselves are objects too. Everything is an object whether it is used to create other objects or not, so do not get bound up in the semantics of other languages usage of the word class. In python, a class is really just an object that is used to determine how to create other objects and what their behaviors will be. Metaclasses are classes that create classes, just to further illustrate this point.

@jurgenreza 2013-03-23 18:12:40

The accepted answer works but a little more explanation does not hurt.

Class attributes do not become instance attributes when an instance is created. They become instance attributes when a value is assigned to them.

In the original code no value is assigned to list attribute after instantiation; so it remains a class attribute. Defining list inside __init__ works because __init__ is called after instantiation. Alternatively, this code would also produce the desired output:

>>> class a:
    list = []

>>> y = a()
>>> x = a()
>>> x.list = []
>>> y.list = []
>>> x.list.append(1)
>>> y.list.append(2)
>>> x.list.append(3)
>>> y.list.append(4)
>>> print(x.list)
[1, 3]
>>> print(y.list)
[2, 4]

However, the confusing scenario in the question will never happen to immutable objects such as numbers and strings, because their value cannot be changed without assignment. For example a code similar to the original with string attribute type works without any problem:

>>> class a:
    string = ''


>>> x = a()
>>> y = a()
>>> x.string += 'x'
>>> y.string += 'y'
>>> x.string
'x'
>>> y.string
'y'

So to summarize: class attributes become instance attributes if and only if a value is assigned to them after instantiation, being in the __init__ method or not. This is a good thing because this way you can have static attributes if you never assign a value to an attribute after instantiation.

@spelufo 2012-09-07 14:34:46

I think the answers provided are misleading. A property defined inside a class becomes an instance property when the object is instantiated, regardless of how you define it. So copies of a.list are made, and x.list and y.list are different copies. The reason they seem to be the same is that they are both aliases to the same list. But that is a consequence of the way lists work, not of the way classes work. If you were to do the same thing with numbers instead of lists (or just using += instead of append, which would create a new list) you would see that changing x.attr doesn't affect changing y.attr.

Defining self.list inside __init__ works, because the function is called twice, once for each time the object is instantiated, and so, two different lists are created.

@Martijn Pieters 2013-02-23 15:44:22

Nope, that's not how it works.

@user629132 2013-03-11 01:51:29

@MartijnPieters: Do you have any reference for that? The explanation in the answer seems very logical, and completely consistent with Python actually behaves. In which way is it incorrect?

@Martijn Pieters 2013-03-11 10:20:07

@JanHlavacek: This answer is incorrect on several points: 1) We are talking about attributes here, not properties; those are different beasts. 2) See class instances in the data model documentation; class attributes are not copied to instances when instantiating. Instead, x.list and y.list are both looked up on the instance first, then when not found there, refer to the underlying class object. Thus, they are the same reference, the class attribute. They are not multiple references to the same list.

@user629132 2013-03-11 14:31:24

@MartijnPieters: Thanks, that was exactly what I was looking for. The key is that a class attribute will become an instance attribute when you assign to it, not when the class is instantiated.

@abyx 2009-11-05 13:23:13

You want this:

class a:
    def __init__(self):
        self.list = []

Declaring the variables inside the class declaration makes them "class" members and not instance members. Declaring them inside the __init__ method makes sure that a new instance of the members is created alongside every new instance of the object, which is the behavior you're looking for.

@Matt Moriarity 2009-11-05 14:04:23

An added clarification: if you were to reassign the list property in one of the instances, it would not affect the others. So if you did something like x.list = [], you could then change it and not affect any others. The problem you face is that x.list and y.list are the same list, so when you call append on one, it affects the other.

@Amal Ts 2015-05-20 06:03:23

But why does this happens only for list? When i declared an integer or string outside the init, it was not shared among the objects? Can anyone share any doc link to this concept?

@Андрей Беньковский 2016-01-25 18:13:26

@AmalTs It looks like you don't understand how assignment in python works. See this video or this SO post. The behaviour you see is caused by the fact that you are mutating lists but rebinding references to ints and strings.

@Андрей Беньковский 2016-01-25 18:21:47

@AmalTs Note: it's considered a bad practice to use class attributes as "lazy" default values for instance attributes. Even if the attributes are of an immutable type it's better to assign them inside __init__.

@jldupont 2009-11-05 13:22:00

You declared "list" as a "class level property" and not "instance level property". In order to have properties scoped at the instance level, you need to initialize them through referencing with the "self" parameter in the __init__ method (or elsewhere depending on the situation).

You don't strictly have to initialize the instance properties in the __init__ method but it makes for easier understanding.

@osanchezmon 2009-11-05 13:27:04

Yes you must declare in the "constructor" if you want that the list becomes an object property and not a class property.

Related Questions

Sponsored Content

32 Answered Questions

[SOLVED] "Least Astonishment" and the Mutable Default Argument

20 Answered Questions

[SOLVED] How to read a text file into a string variable and strip newlines?

  • 2011-12-03 16:47:54
  • klijo
  • 976490 View
  • 758 Score
  • 20 Answer
  • Tags:   python

17 Answered Questions

[SOLVED] Get list from pandas DataFrame column headers

8 Answered Questions

[SOLVED] Proper way to declare custom exceptions in modern Python?

16 Answered Questions

[SOLVED] Convert bytes to a string?

10 Answered Questions

[SOLVED] How to print the full traceback without halting the program?

14 Answered Questions

[SOLVED] How to return multiple values from a function?

11 Answered Questions

[SOLVED] How to print objects of class using print()?

21 Answered Questions

[SOLVED] How to print a date in a regular format?

  • 2008-11-22 18:37:07
  • NomadAlien
  • 1130922 View
  • 571 Score
  • 21 Answer
  • Tags:   python datetime date

8 Answered Questions

[SOLVED] Getting the class name of an instance?

Sponsored Content