Python: Advanced Syntax of Class

楊捷成
NTUST-AIVC
Published in
7 min readJun 21, 2022

Co-Author: Y. S. Huang, a master’s student studying NTUST-AIVC, likes open-source.
If you are interested, go to check my Github!

Last time we introduced some basic elements of class in python. This time we will focus on the class method and the different usage of the class.

In this article, first, we introduce the Class Method and the Static Method. Then we talk about the different usage of class like Inheritance, Encapsulation and Polymorphism.

Class Method

In comparison, class method uses cls as its parameter, the instance method uses self instead. As a result, you can simply differentiate by checking its parameter. Besides, the class method needs a decorator @classmethod upon the class.

The class method uses cls as its parameter, which directs to the class. In consequence, it can only alter the class’s status but not the object’s because it doesn’t have the self parameter which directs to the object.

class People():
@classmethod
def walk(cls):
print("people walks")
Kevin = People()
Kevin.walk() #call by object
People.walk() #call by class
---output---
people walks
people walks

You can see in the code that both object and class can call the method.

Class method is often used to generate an object. You can subdivide a class of various types to create an object with some specific attributes. Besides, when it is complicated to generate an object, the class method helps you simplify the process. Making good use of class method makes your code more concise.

class Dog():
def __init__(self, color, age):
self.color = color
self.age = age
@classmethod
def border_collie(cls):
return cls('black', 2)
@classmethod
def poodle(cls):
return cls('white', 3)
dog_1 = Dog.border_collie() #construct with classmethod
dog_2 = Dog.poodle() #construct with classmethod
print(dog_1.__dict__)
print(dog_2.__dict__)
---output---
{'color': 'black', 'age': 2}
{'color': 'white', 'age': 3}

Static Method

Compared to instance method and class method, the static method represent by the decorator of @statidmethod, and it doesn’t have the parameter of self or cls. Therefore it can neither change class nor object's status. However, it can accept any other parameter.

Static method is an independent method in the class, normally used on the condition that the method doesn’t need to access the object’s attributes of the method, e.g. calculation.

class Human():
@staticmethod
def BMI(height, weight):
return float(weight / height / height * 10000)
David = Human()
David_BMI = David.BMI(175, 70) #called by object
someone_BMI = Human.BMI(180, 75) #called by class
print("David's BMI is ", David_BMI)
print("someone's BMI is ", someone_BMI)
---output---
David's BMI is 22.857142857142858
Someone's BMI is 23.148148148148152

Static method can be called by either an object or a class. The greatest advantage of the static method is that it can prevent accidental alteration because it doesn’t have self or cls parameter to affect the object or class. Moreover, due to its independence, it is helpful for unit tests.

Inheritance

As its name, it means the Sub class will inherit its Base class’s attributes and methods. Making good use of Inheritance can greatly improve code redundancy.

Let’s see an example to see how to use inheritance.

class Marine():
def __init__(self, eat):
self.behavior = 'swim'
self.feeding_habit = eat
def get_behavior(self):
print("it can swim")
class Fish(Marine):
def __init__(self, eat, speed, color):
super().__init__(eat)
self.speed = speed
self.color = color
def details(self):
print("speed:'{}'".format(self.speed))
print("color:'{}'".format(self.color))
print("eat:'{}'".format(self.feeding_habit) )
fish_1 = Fish('meat', 20, 'red')
print(fish_1.color)
print(fish_1.behavior)
fish_1.details()
fish_1.get_behavior()
---output---
red
swim
speed:'20'
color:'red'
eat:'meat'
it can swim

First, we have created the class “marine”. Then we created the other class “fish” and use the class marine as its parameter. Then in the __init__ method, we have two more parameters “speed” and “color”, and one parameter “eat” which belongs to the base class. Don’t forget to add the parameter of the base class into the method __init__. Otherwise, the required number of arguments won’t be matched and thus cause an error.

Now let’s talk about the method super().__init__. Super() represents the base class. Super directs to the base class and can execute a specific method of it. Consequently, super().__init__ executes the __init__ method of the base class, which greatly concise the code.

Sub class may have the same method name as the base class with different contents. In this case, sub class’s method will overwrite the base class’s method.

class Human():
def __init__(self)->None:
self.feed_habit = 'meat'

def eat(self):
print("they eat", self.feed_habit)
class Baby(Human):
def __init__(self) -> None:
super().__init__()
self.eat()
self.feed_habit = 'milk'

bawan = Baby()
bawan.eat()
---output---
they eat meat
they eat milk

Here you can see self.feed_habit is different because the class “Baby” rewrites the self.feed_habit .

Multi-Level Inheritance

The concept of Multi-level Inheritance can be simply understood by watching this picture.

This picture tells you that Multi-level Inheritance is vertical inheritance. The Intermediatory class inherits the Base class. Then the Derived class inherits the Intermediatory class. It is, the derived class will not only have the attributes and methods of the Intermediatory class but also the Base class.

class Creature():
def __init__(self, age):
self.age = age
def live(self):
print(self.age, "years of life")
print("it needs energy to survive")

class Animal(Creature):
def __init__(self, age):
super().__init__(age)
def eat(self):
print("animal needs to eat food to produce energy")

class Dog(Animal):
def eat_habbit(self):
print("dog eats meat")

dog_1 = Dog(10)
dog_1.live()
dog_1.eat()
dog_1.eat_habbit()
---output---
10 years of life
it needs energy to survive
animal needs to eat food to produce energy
dog eats meat

You can see that the data type of dog_1 is Dog(Animal) . Thus it has the attribute and the method of Animal and the base class of Animal.

Multiple Inheritance

Multiple Inheritance is like a horizontal inheritance. By watching the following picture, you get to know that both classes “Base1” and “base2” will pass their contents to the derived class. It is, the derived class can inherit many classes simultaneously. In comparison, Multi-level inheritance can only inherit one class, but it may include several levels of class.

Now let’s watch an example to better understand!

class Doctor():
def help(self):
print("doctor helps patient.")

def place(self):
print("work in hospital")

class Professor():
def teach(self):
print("professor teaches student.")
def place(self):
print("work in college")

class Father(Professor, Doctor):
def take_care(self):
print("my father takes care of the kids.")

peter = Father()
peter.help()
peter.teach()
peter.take_care()
peter.place()
---output---
doctor helps patient.
professor teaches student.
my father takes care of the kids.
work in college

You can see that Father inherit both Doctor and Teacher. One important thing is that in multiple inheritances, the leftmost parameter has the top priority. You can see that both Professor and Doctor have the same method place(). As the place() is called, only the one in Professor was executed.

You can also use super to initialize some attributes as well.

class Child():
def __init__(self):
self.year = 10
class Student():
def __init__(self):
self.id = 'K12345'

def do(self):
self.behavior = 'study'
class Adult(Child, Student):
def __init__(self):
super(Adult, self).__init__()
super(Child, self).__init__()
super(Student, self).__init__()
kevin = Adult()
print(kevin.id)
print(kevin.year)
kevin.do()
print(kevin.behavior)
---output---
K12345
10
study

You can see that in class Adult, super(Child, self).__init__() and super(Student, self).__init__() are called to generate an object with some attributes of the base class, the reason we use super(<object>, self).__init__() to achieve inheritance, this is because MRO Algorithm.

Encapsulation

The usage of encapsulation is to hide the details of the code while the code remains the normal function. If there’s any method or attribute you don’t want to be accessed, you can add “__” in front of them. Then they can only be accessed by the method inside the class.

class Person():
def __init__(self):
self.__organ = 'lung'
def __life(self):
print("100 years")
def behavior(self):
print("walk")
def get_detail(self):
print(self.__organ)
self.__life()
Jason = Person()
Jason.behavior()
Jason.get_detail()
#print(Jason.__organ)
---output---
walk
lung
100 years
#AttributeError: 'person' object has no attribute '__organ'

You can see that the method get_detail can access self.__organ . However, when Jason.__organ() tried to access it, an error in the attribute occurred.

Polymorphism

Before we start to introduce polymorphism, Let’s talk about the “Abstract method” first.

An abstract method is a method that has a declaration but does not have an implementation. Any class that inherits the class with an abstract method must have a method with the same name as the abstract method. Besides, any class that inherits the abstract class cannot instantiate.

from abc import ABC, abstractmethodclass Say(ABC):
@abstractmethod
def say(self):
pass
test = Say()--output--
TypeError: Can't instantiate abstract class Say with abstract methods say

You can see there’s a type error that says it cannot instantiate abstract class.

With the knowledge of the abstract method, now we can move on to polymorphism. In inheritance, method overriding is a performance of polymorphism. The sub class method rewrites the base class method. When an object calls the method, it functions differently depending on the object.

from abc import ABC, abstractmethodclass PersonSay(ABC):
@abstractmethod
def say(self):
pass

class JasonSay(PersonSay):
def say(self):
print("Jason says")

class MattSay(PersonSay):
def say(self):
print("Matt says")
jason = JasonSay()
matt = MattSay()
jason.say()
matt.say()
--output--
Jason says
Matt says

In this code, class PersonSay has the abstract method say, As a result, the class that inherits the class PersonSay must have a method named say .

Both JasonSay and MattSay inherit PersonSay , when method say is called, it functions depending on the object.

--

--