I'm having a problem understanding how class / instance variables work in Python. I don't understand why when I try this code the list variable seems to be a class variable
class testClass():
list = []
def __init__(self):
self.list.append('thing')
p = testClass()
print p.list
f = testClass()
print f.list
Output:
['thing']
['thing', 'thing']
and when I do this it seems to be an instance variable
class testClass():
def __init__(self):
self.list = []
self.list.append('thing')
p = testClass()
print p.list
f = testClass()
print f.list
Output:
['thing']
['thing']
This is because of the way Python resolves names with the
.
. When you writeself.list
the Python runtime tries to resolve thelist
name first by looking for it in the instance object, and if it is not found there, then in the class instance.Let's look into it step by step
list
name into the objectself
?list
name into the class instance of objectself
?But when you bind a name things are different:
list
name into the objectself
?So, that is always an instance variable.
Your first example creates a
list
into the class instance, as this is the active scope at the time (noself
anywhere). But your second example creates alist
explicitly in the scope ofself
.More interesting would be the example:
That will print:
The moment you delete the instance name the class name is visible through the
self
reference.Python has interesting rules about looking up names. If you really want to bend your mind, try this code:
This will give each instance a variable called
l
that masks the class variablel
. You will still be able to get at the class variable if you doself.__class__.l
.The way I think of it is this... Whenever you do
instance.variable
(even for method names, they're just variables who's values happen to be functions) it looks it up in the instance's dictionary. And if it can't find it there, it tries to look it up in the instance's class' dictionary. This is only if the variable is being 'read'. If it's being assigned to, it always creates a new entry in the instance dictionary.When you instantiate a class,
__init__
method is automatically executed.In the first case your list is a class attribute and is shared by all its instances. You got two 'thing's because you appended one when instantitating
p
and another when instantiatedf
(the first one was already appended at the first call).In your first example,
list
is an attribute of the class, shared by all instances of it. This means that you can even access it without having an object of typetestClass
:But all objects share the
list
attribute with the class and each other: