Let's explore a bit. This is your class:
class Class:
var1 = 'in class'
def __init__(self, var1):
self.var1 = var1
c = Class('in inst')
Accessing c.var1 shows the var1 from the instance:
>>> c.var1
'in inst'
It is located inside __dict__ of c:
>>> c.__dict__
{'var1': 'in inst'}
The class variable var1 is in __dict__ of Class:
>>> Class.__dict__['var1']
'in class'
Now make a class with only a class variable:
class Class2:
var1 = 'in class'
c2 = Class2()
Since there is nothing in the instance, var1 from the class will be used:
>>> c2.var1
'in class'
The __dict__ of c2 is empty:
>>> c2.__dict__
{}
Python always looks for var1 first in the instance and than falls back to the class.
Two ways to declare instance variables in Python? - Stack Overflow
Can someone explain how object/instance variables vs class/static variables work in Python?
python class instance variables and class variables - Stack Overflow
Declaring an instance variable at the class level
Let's explore a bit. This is your class:
class Class:
var1 = 'in class'
def __init__(self, var1):
self.var1 = var1
c = Class('in inst')
Accessing c.var1 shows the var1 from the instance:
>>> c.var1
'in inst'
It is located inside __dict__ of c:
>>> c.__dict__
{'var1': 'in inst'}
The class variable var1 is in __dict__ of Class:
>>> Class.__dict__['var1']
'in class'
Now make a class with only a class variable:
class Class2:
var1 = 'in class'
c2 = Class2()
Since there is nothing in the instance, var1 from the class will be used:
>>> c2.var1
'in class'
The __dict__ of c2 is empty:
>>> c2.__dict__
{}
Python always looks for var1 first in the instance and than falls back to the class.
As I pointed out in comment, the Class.var1 is a shared variable. It could be accessed for each instance as self.var1 if you don't erase it with a non-shared variable in __init__. Here is a sample of what happens :
class Test(object):
shared = 0
def __init__(self, i):
self.notshared = i
def intro(self):
print("Shared is " + str(self.shared))
print("NotShared is " + str(self.notshared))
test1 = Test(4)
test1.intro()
# Shared is 0
# NotShared is 4
Test.shared = 5
test1.intro()
# Shared is 5
# NotShared is 4
test2 = Test(3)
test2.intro()
# Shared is 5
# NotShared is 3
Be aware however that if you write the self.shared variable afterwards, you do not access the shared variable with self.shared anymore:
test1.shared = 12
test1.intro()
# Shared is 12
# NotShared is 4
test2.intro()
# Shared is 5
# NotShared is 3
So I come from a Java background where defining, declaring and accessing static and instance level variables are pretty much a straightforward process. I want to be able to understand OOP concepts of Python properly so I have been doing some practice.
I have a class:
class A:
def init(self): pass
def someFunc(self): self.var1 += 1
I create an object of this class and call the someFunc() method:
a = A() a.someFunc()
It gives me an error. Ok, fair enough since I haven't declared a self.var1 variable yet.
Consider another example.
class A:
var1 = 10
def init(self): pass
def someFunc(self): self.var1 += 1
Now when I do this:
a = A() a.someFunc() Output: 11
I know that variables defined just below the class definition are class/static variables. And to access them you have to do A.var1
But why does it not give me an error now? I haven't created a object/instance level self.var1 variable yet, just a class level variable var1.
And when I call A.var1 the output is 10. Why is the output not the same as a.var1?
Does python automatically use the class level variable with the same name since there is no instance level variable defined with the same name? And does that in turn become a different variable from the class level variable?
Can someone please elaborate?
This is because of the way Python resolves names with the .. When you write self.list the Python runtime tries to resolve the list 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
self.list.append(1)
- Is there a
listname into the objectself?- Yes: Use it! Finish.
- No: Go to 2.
- Is there a
listname into the class instance of objectself?- Yes: Use it! Finish
- No: Error!
But when you bind a name things are different:
self.list = []
- Is there a
listname into the objectself?- Yes: Overwrite it!
- No: Bind it!
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 (no self anywhere). But your second example creates a list explicitly in the scope of self.
More interesting would be the example:
class testClass():
list = ['foo']
def __init__(self):
self.list = []
self.list.append('thing')
x = testClass()
print x.list
print testClass.list
del x.list
print x.list
That will print:
['thing']
['foo']
['foo']
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:
class testClass():
l = []
def __init__(self):
self.l = ['fred']
This will give each instance a variable called l that masks the class variable l. You will still be able to get at the class variable if you do self.__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.