Why does i remain the same even after a new instance of the class is created?
class Test(object):
i = 0
def add(self):
Test.i += 1
Running this code
t = Test()
print t.i
t.add()
t2 = Test()
print t2.i
print t.i
Gives
0
1
1
Why didn't both t.i and t2.i equal 0? Shouldn't they have equaled 0 because the line t2 = Test()
would have reset i to 0?
i
is a class variable, not an instance variable. It is bound to the class itself (which is why you can write Test.i
, even if no instances of Test
exist).
You have to make i
an instance variable:
class Test(object):
def __init__(self):
self.i = 0
def add(self):
self.i += 1
You are modifying a property of the entire class, instead of a property of the instance. Try this:
class Test(object):
i = 0
def add(self):
self.i += 1
Python automatically passes the instance as the argument self
to the method. Within the method, you can therefore refer to a property of the instance as self.i
.
class Test(object):
i = 0
def add(self):
Test.i += 1
print "Test.i == ",Test.i
print "'i' in dir(Test) == ",'i' in dir(Test)
print "'i' in Test.__dict__ == ",'i' in Test.__dict__
t1 = Test()
print '\n# t1 = Test() executed'
print "t1.i == ",t1.i
print "'i' in dir(t1) == ",'i' in dir(t1)
print "'i' in t1.__dict__ == ",'i' in t1.__dict__
result
Test.i == 0
'i' in dir(Test) == True
'i' in Test.__dict__ == True
# t1 = Test() executed
t1.i == 0
'i' in dir(t1) == True
'i' in t1.__dict__ == False
.
The attribute of name __dict__
of an object is the dictionary that represents the namespace of this object, that is to say it contains the attributes of the object.
Also, we have:
dir([object])
If the object has a method named __dir__()
, this method will be called
and must return the list of attributes.
So, how is it possible that dir(t1)
contains the attribute i and t1.__dict__
doesn't ?
While all two dir(Test)
and Test.__dict__
contain the attribute i ?
.
That's for the same reason that answers to your question:
The behavior of returning the attribute of an object is awkward.
And `dir(object)
reflects this awkwardness:
The default dir() mechanism behaves differently with different types
of objects, as it attempts to produce the most relevant, rather than
complete, information:
•If the object is a module object, the list contains the names of the
module’s attributes.
•If the object is a type or class object, the
list contains the names of its attributes, and recursively of the
attributes of its bases.
•Otherwise, the list contains the object’s
attributes’ names , the names of its class’s attributes, and
recursively of the attributes of its class’s base classes.
.
Then, the answer to your question is in two parts:
1) dir(t1)
gives what is considered as the attributes of the object but the REAL NAMESPACE of the object, exposed as t1.__dict__
doesn't contain the attribute i, which is, as it has already been answered, in fact, a class' atribute.
Hence the pseudo-attributes i of two instances t1 and t2 appear equals because the expressions t1.i
and t2.i
are in fact evaluated as Test.i
,
in the same way that dir(t1)
and dir(t2)
include the class's attribute Test.i
.
2) how the expression t1.i
is evaluated as Test.i
??
Because of that (which constitutes the additional info of my answer):
A class instance has a namespace implemented as a dictionary which is
the first place in which attribute references are searched. When an
attribute is not found there, and the instance’s class has an
attribute by that name, the search continues with the class
attributes.
http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy
It means that when an attribute isn't found in the namespace of an object, it is searched in the namespace of the class whose the object is an instance.