Understanding the difference between Class Var and Instance Var is fundamental to OOP.
Class Var
Given a class Lang
, as below
class Lang:
name = "Python"
version = "3.8"
def __init__(self, name, version):
name = name
version = version
lang1 = Lang("Java", "8.0")
lang2 = Lang("Javascript", "ES6")
print(lang1.name)
print(lang2.name)
The results will be
Because the vars printed are class variables, Class Var is associated with the Class Lang
Instance Var
Change the code
class Lang:
name = "Python"
version = "3.8"
def __init__(self, name, version):
self.name = name
self.version = version
lang1 = Lang("Java", "8.0")
lang2 = Lang("Javascript", "ES6")
print(lang1.name)
print(lang2.name)
print(Lang.name)
Instance Var is associated with a specific Object. In this example, name
is not a good practice for Class var.
As name
is usually specific with a concrete object.
The lookup order
Go back to the code below
class Lang:
name = "Python"
version = "3.8"
def __init__(self, name, version):
name = name
version = version
lang1 = Lang("Java", "8.0")
lang2 = Lang("Javascript", "ES6")
print(lang1.__dict__)
print(Lang.__dict__)
print out the __dict__
, lang1 is empty now
Let’s add back self
class Lang:
name = "Python"
version = "3.8"
def __init__(self, name, version):
self.name = name
self.version = version
# below will print out instance var
print(name)
print(version)
lang1 = Lang("Java", "8.0")
print(lang1.__dict__)
print(Lang.__dict__)
Now lang1
has proper attributes.
Here’s a Pythonic system to look up variables:
- Python will start look for variables in the object
- If the object doesn’t contain the target variable, it will continue search for the variable on the Class level
- If the target variable is not found on the Class level, it will keep searching from the parent Class level if there’s inheritance
Self
self
is explicitly needed for instance attributes and methods- user don’t need to assign
self
manually, it’s automatically done by python - similar to
this
in Java
class Lang:
name = "Python"
version = "3.8"
def __init__(self, name, version):
self.name = name
self.version = version
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")
lang1.check_version()
self
is the object that invokes the method at the moment, e.g. forlang1.check_version()
,self
islang1
in the case above
Access Instance Var and Class Var within Instance Methods
- instance methods: behavior
- instance vars: attributes
- instance methods usually would perform some operations on vars to change the states/results of vars, hence they need to access vars in classes or instances
__init__
function is a special type of instance method. It defines and initializes the attributes of an instance
Instance methods to access instance vars,
self.varname
Instance methods to access class vars
class Lang:
count = 0
name = "class"
def __init__(self, name, version):
self.name = name
self.version = version
print(self.name)
# below is not instance var, it's the arg defined in __init__
print(name)
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")
The print out results are misleading here, if we change the arg name
to lang
, print(name)
will report error as name
doesn’t exist any more
class Lang:
count = 0
name = "class"
def __init__(self, lang, version):
self.name = lang
self.version = version
print(self.name)
# below is not instance var, it's the arg defined in __init__
print(name)
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")
- How to access the class var
count
?
class Lang:
count = 0
name = "class"
def __init__(self, lang, version):
self.name = lang
self.version = version
print(count)
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")
It will still report name error
- To properly access the class var, the class name is needed
class Lang:
count = 0
name = "class"
def __init__(self, lang, version):
self.name = lang
self.version = version
print(Lang.count)
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")
- Magically
self.count
is also accessible thanks to the order of looking var: instance then class then parent class
class Lang:
count = 0
name = "class"
def __init__(self, lang, version):
self.name = lang
self.version = version
print(self.count)
def check_version(self):
print(self.version)
lang1 = Lang("Java", "8.0")