Reputation: 475
class myclass(object):
i=0
def increase(self):
self.i+=1
print('increased value:', self.i)
if __name__=='__main__':
m=myclass()
m.increase()
Here is a class variable and self.i
is instance variable , on executing i get o/P as 1.
But if comment class variable i
I get an error
self.i+=1
AttributeError: 'myclass' object has no attribute 'i'
what is the relation between class variable i
and instance variable self.i
here.
Upvotes: 1
Views: 65
Reputation: 3082
A class variable is a variable which can be changed by all instances of your class. You call it by [class_name].[variable_name]
For Example:
class myclass(object):
i=0
def increase(self):
myclass.i+=1
print('incresed value:',self.i)
if __name__=='__main__':
m=myclass()
k = myclass()
k.increase()
m.increase()
m.increase()
m.increase()
m.increase()
k.increase()
results in
incresed value: 1
incresed value: 2
incresed value: 3
incresed value: 4
incresed value: 5
incresed value: 6
An instance variable on the other hand (like you have it) can only be accessed by the instance which created it (with self.[variable_name]). To access a variable, the variable first needs to be instantiated. Like
a+=5
would create an error while
a = 0
a+= 5
would not
In your example the instance variable is not specificly instantiated. But because of the class variable (i=0) python automatically instantiates the instance variable (i) with the value of the class variable. (because class and instance variable have the same name)
In other words:
When in your example the class variable i=0 is removed python does not know what value your instance variable self.i should have in the beginning.
Upvotes: 0
Reputation: 2518
What happens is that you are shadowing the class variable with a member variable.
See what happens when you instanciate another myclass-object and add a few printouts to your code:
class myclass(object):
i=0
def increase(self):
myclass.i+=1
print('incresed value:',self.i)
if __name__=='__main__':
m=myclass()
n=myclass()
print("m.i=", m.i)
print("n.i=", n.i)
m.increase()
print("m.i=", m.i)
print("n.i=", n.i)
The output is now:
m.i= 0
n.i= 0
incresed value: 1
m.i= 1
n.i= 0
You see that you incremented the value of the i-member of m, but not of n. This is because self (like this in c++) always refers to the current object instance. If you update your code to the following, you are actually incrementing the class variable:
def increase(self):
myclass.i+=1
print('incresed value:',self.i)
And the output changes to the following:
m.i= 0
n.i= 0
incresed value: 1
m.i= 1
n.i= 1
Like Guillaume Jacquenot already stated in his answer, if you'd like to use member variables, it is advisable to initialize them in __init__(). In your case, the interpreter ist just using the class variable with the same name when it can't find a member variable, and in the same line initializing a member variable (with identical name i). If you comment out the class variable, you're trying to increment a variable which does not exist yet, hence the interpreter error.
Upvotes: 1
Reputation: 1420
The problem you are facing is the lack of definition of i
object after you remove the class variable.
The i=0
statement is the only definition. It is the same with any other variable, nothing special happens here:
i+=1
yields the same error if you put it in main or anywhere. In order to do the increment +=
you need to have the object declared first.
You can do:
class myclass(object):
def increase(self):
self.i=0
self.i+=1
print('increased value:', self.i)
which makes no sense, but illustrates the issue, i think.
Upvotes: 0
Reputation: 11717
You use the following statements to declare a constant inside your class. i
is not supposed to be modified later.
class myclass(object):
i=0
You can access it with
value = myclass().i
If you want a counter, you declare it in the constructor __init__
, and increase it in a method
class myclass(object):
def __init__(self):
self.counter = 0
def increase(self):
self.counter += 1
Upvotes: 0