# Python: Class Introduction

2022-02-02 14:14:52 Ice sky

# Python class

## One 、 Class construction & initialization

adopt __init__ Initialization with built-in functions ：

class Student:

def __init__(self, name, age):
print('Start initialization...')
self.name = name
self.age = age

alice = Student('Alice', 20)
bob = student('Bob', 20)
print(id(bob))
# show dictionary of each student
print(alice.__dict__)
# {'name': 'alice', 'age': 20}
print(bob.__dict__)
# {'name': 'bob', 'age': 20}


adopt __dict__ Code optimization for multi field initialization ：

class person:
''' def __init__(self, name, age, hobby, address, email): # intialization # self.name = name # ... # self.email = email '''
# using __dict__ to init
def __init__(self, info):
self.__dict__.update(info)

perinfos = open('person_info.txt', 'r')
persons = []
for p in perinfos:
info = p.split(', ')
persons.append(person(info))

print(persons)


## Two 、 Class characteristics

• polymorphic Polymorphism
• encapsulation Capsulation
• Inherit Inheritation

### 2.1 Class inheritance ：Inheritation

#### 2.1.1 The definition of inheritance

###########################################################################################################
###########################################################################################################
### ___ ______ ____ ___ _______ _______ ___ ___
### | |\ | | | | | \ | | /\ | | / \ |\ |
### | | \ | |_____| |____ |____/ | | / \ | | | | | \ |
### | | \ | | | | | \ | | /----\ | | | | | \ |
### _|_ | \| | | |_____ | \ _|_ | / \ | _|_ \___/ | \|
###########################################################################################################
###########################################################################################################

# derived_class - Class this class derived from
class class_name(derived_class):

# some variables
# some override functions such as: __init__, __call__
# some user defined function


#### 2.1.2 multiple inheritance

Python Support for multiple inheritance , Subclasses inherit all variables and methods of the parent class . Variable search method ：

• From bottom to top
• From left to right
class parent1:
x = 'parent1 x'
parent_name = 'parent1'
class parent2:
x = 'parent2 x'
parent_name = 'parent2'
class child(parent1, parent2):
myname = 'myname is child'

child = child()
print(child.myname)
print(child.parent_name) # output: parent1 which is first in parent list


#### 2.1.3 Search method

• Depth-first search （DFS, Depth-First-Search）
##### Python2： The difference between classic and new classes

Classic class ：

class A:

def echo(self):
print('I am A')

class B(A):
# do nothing
pass

class C:

def echo(self):
print('I am C')

class D(B,C):
pass

d = D()
print(d.echo()) # I am A



The new class ：

class A(Object):

def echo(self):
print('I am A')

class B(A):
# do nothing
pass

class C:

def echo(self):
print('I am C')

class D(B,C):
pass

d = D()
print(d.echo()) # I am C


#### 2.1.4 Variables and methods

By explicitly calling the function with the same name in the parent class , Implement code optimization .

##### The inheritance of function is related to

First, we define three classes ：

• person： Base class , Contains a say Methods and a way to increase your salary 
• staff： According to the salary formula of ordinary employees , Override the salary method in the parent class
• manager： ditto , But the salary calculation method is different

We have defined different salary calculation formulas in each class , And set the corresponding formal parameters ：

class person:

def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary

def say(self):
s = 'My name is %s, my age is %s, and my price is %s' %(self.name, self.age, self.price)

def raise_salary(self, percentage):
self.salary = self.salary * (1 + percentage)

class staff(person):

def __init__(self):
pass

def raise_salary(self, percentage, performance):
self.salary = self.salary * (1 + percentage + performance)

class manager(person):

def __init__():
pass

def raise_salary(self, percentage, performance, shareoutbonus):
self.salary = self.salary * (1 + percentage + performance + shareoutbonus)


obviously , At this point, when we want to calculate the salary formula , Or when the parameter is modified , We need to modify every function , However, it is realized by explicitly calling the function function of the parent class in the function function of the child class , You can directly modify the methods in the parent function ：

# staff
def raise_salary(self, percentage, performance):
# self.salary = self.salary * (1 + percentage + performance)
person.raise_salary(percentage = percentage + performance)
# manager
def raise_salary(self, percentage, performance, shareoutbonus):
# self.salary = self.salary * (1 + percentage + performance + shareoutbonus)
person.raise_salary(percentage = percentage + performance + shareoutbonus)

##### The inheritance of constructors is related to

When a new member variable is added to a subclass , And when you want to pass new variables during construction ：

##  Inheritance of constructors

class person:
def __init__(self, name, age, price):
self.name = name
self.age = age
self.price = price

class manager(person):

m2 = manager('m2', 20, 1000, 'Dongguan') # error 'cause __init__ has been overrrided


At this point, if the initialization function of the subclass only contains the new field parameters , When constructing, the parameters in the initialization function of the parent class are passed , Report errors , because __init The method of is completely overridden in subclasses , also Python The initialization function of the parent class is not implicitly called for redundant parameters , Therefore, you need to completely rewrite the initialization function , Give the corresponding assignment statement for each field ：

##  Inheritance of constructors

class person:
def __init__(self, name, age, price):
self.name = name
self.age = age
self.price = price

class manager(person):

def __init__(self, name, age, price, address):
self.name = name
self.age = age
self.price = price

m2 = manager('m2', 20, 1000, 'Dongguan') # error 'cause __init__ has been overrrided


obviously , At this time, there are many duplicate codes in the initialization functions of subclasses and parent classes .

When there are a large number of duplicate assignment statements in the initialization function of the subclass and the parent class , Code optimization can be achieved by explicitly calling the initialization function of the parent class ：

class person:
def __init__(self, name, age, price):
self.name = name
self.age = age
self.price = price

class manager(person):

def __init__(self, name, age, price, address):
''' self.name = name self.age = age self.price = price '''
# instead explicitly called person's initialization method
person.__init__(self, name, age, price)

m2 = manager('m2', 20, 1000, 'Dongguan') # pass


#### 2.1.5 Inherited application scenarios

• synthesis
• polymerization
• Reuse
##### synthesis

The life cycle of part and whole is consistent , The whole has control over its organizational part , And a component only belongs to a synthetic relationship , It can't be shared

for example ：

• house ： Including rooms s, room s Only belong to this house , The house disappeared , The room disappeared , A strong ownership relationship
• room ： Inside the house , The life cycle is less than or equal to the house , The disappearance of the house must be accompanied by the disappearance of the room
class room:
def create_room(self):
print("this is a new room")

class house:
def __init__(self):
self.room = room()

def create_house(self):
self.room.create_room()

h1 = house()
h1.create_house()

##### polymerization

Indicates a relationship of ownership , The relationship between the whole and the parts

for example ：

• Student ： part , The school closed down , But students still exist , Will not disappear because of the disappearance of the whole , That is, the life cycle of a part can exceed that of the whole
• Flight class ： The whole that contains each student part
#  Student , Part of the classroom
class student:
pass

#  classroom , Including the whole of students
class classroom:
def __init__(self, student):
self.student = student

s1 = student()
c1 = classroom(s)


Object relationship ：

• IS-A ： I am a person （？）, Obviously, this is an inheritance relationship
• HAS-A： People have brains （？）, It's obviously a synthetic relationship

Example ：
m a n { i n   c o m p a n y : e m p l o y e e a t   h o m e : h u s b a n d f a t h e r a t   s c h o o l : s t u d e n t man\begin{cases} in\ company:employee\\ at\ home:husband&father\\ at\ school:student \end{cases}

class person:
def show(self):
print('live a happy life')

class staff:
def show(self):
print("try to work hard")

class husband(person):

def show(self):
print("work and earn money")

class student(person):

def show(self):
pritn("good good study day day up")

p = staff()
p.show()
# different person, not able to create a person with different roles
p = husband()
p.show()

class role:
def show(self):
pass

class staff(role):
def show(self):
print("try to work hard")

class husband(role):

def show(self):
print("try best to make family happy")

class student(role):

def show(self):
pritn("good good study day day up")

class person:
def set_role(self, role):
self.role = role

def get_role(self):
self.role.show()

p = person()
p.set_role(staff)
p.get_role() # "try to work hard"

p.set_role(husband)
p.get_role() # "try best to make family happy"

p.set_role(student)
p.get_role() # "good good study day day up"


#### 2.1.6 The Demeter principle ： The principle of least knowledge

Ensure encapsulation , Reduce the internal exposure of classes , Example ：

• A class ： By B rely on , Expose only the methods and properties that must be provided , That is, define the visible range of methods and attributes
• B class ： Depend on A, Rely only on what should be relied on , That is, only want to provide information to the object that needs to provide information , Don't expose content to unrelated classes

for example ：

class A:
def __init__(self, name):
self.name = name
def get_b(self, name):
return B(name)

# A -> B -> C to work
def work(self):
b = self.get_b('b')
c = b.get_c('c')
c.work()

class B:
def __init__(self, name):
self.name = name
def get_c(self, name):
return C(name)

class C:
def __init__(self, name):
self.name = name
def work(self):
print('Done! by' + self.name)

a = A('a')
a.work()


You can find , At this time in A Called in C Related code , But obviously C It should be right A Hidden , in other words , We should make use of B To make the C Complete relevant work , and A Just contact B that will do ：

class A:
def __init__(self, name):
self.name = name
def get_b(self, name):
return B(name)

# A -> B -> C to work
def work(self):
b = self.get_b('b')
# c = b.get_c('c')
# c.work()
b.work()

class B:
def __init__(self, name):
self.name = name
def get_c(self, name):
return C(name)
def work(self):
c = self.get_c('c')
c.work()

class C:
def __init__(self, name):
self.name = name
def work(self):
print('Done! by' + self.name)

a = A('a')
a.work()a.work()


Besides , For the dependent , Dependents should minimize the exposure of internal specific processes and methods , And only provide users with a user-friendly and detail hidden method , It not only improves the encapsulation of classes , It can also improve the user experience ：

class computer:
# private methods
def __stop_service(self):
print('wait for stopping process...done!')

def __poweroff(self):
print('wait for power off...done!')

def __shut_screen(self):
print('screen is going to sleep...done!')

def __save_data(self):
print('writing back data...done!')

# public
def shutdown(self):
self.__stop_service()
self.__save_data()
self.__shut_screen()
self.__poweroff()

if __name__ == '__main__':
c = computer()
c.shutdown()
# c.__save_data() error
# c.__stop_service() error


### 2.2 Class encapsulation ：Capsulation

########################################################################################################
########################################################################################################
### ___ ____ ___ _______ ___ ___ #####
### / \ /\ | \ / \ | | | /\ | | / \ |\ | #####
### | / \ |____/ \___ | | | / \ | | | | | \ | #####
### | /----\ | \ | | | /----\ | | | | | \ | #####
### \___/ / \ | \___/ |_____| |_____ / \ | _|_ \___/ | \| ###
############################################################################################################
############################################################################################################


First , stay Python in , Encapsulation is just a convention , in other words , In fact, the internal variables of any object can be accessed externally in some way . For an ordinary variable , The outside can be accessed at will , such as ：

class temp:

var = 1

# some definitions



This variable var It can be accessed freely from the outside .

Inaccessible type ,Python Two internal variables are agreed ：

• _varname： Variables with variable names starting with underscores
• __varname： A variable whose name begins with a double underscore

for example ：

class temp:

var = 1

def __init__(self):

self._var = 2
self.__var = 3

# other definitions

t = temp()
print(t.var) # 1
print(t._var) # 2, You can still visit , Just an agreement
print(t.__var) # error, Double underscores are not accessible
print(t._temp__var) # 3,  But it can still be accessed through the dictionary , Go further  Python  Private is just an agreement , Access is not completely restricted


### 2.3 Class polymorphism ：Polymophism

class animal:
def run(self):
print('it is running')

class dog(animal):
def run(self):
print('dog is running')

class cat(animal):
def run(self):
print('cat is running')

if __name__ == '__main__':
d = dog()
d.run()

c = cat()
c.run()

print(isinstance(d, dog)) # True
print(isinstance(d, animal)) # True
print(isinstance(c, animal)) # True
print(isinstance(c, dog)) # False


## 3、 ... and 、 abstract class

• Can't instantiate （ When there are abstract methods ）
• Through the function decorator @abstractmethod Set the corresponding function in the abstract class as the abstract function , Subclass must implement
from abc improt ABCMeta, abstractmethod

class animal(metaclass=ABCMeta):

def__init__(self, name, age):
self.name = name
self.age = age
@abstractmethod
def run(self):
pass

class dog(animal):

def __init__(self, name, age):
self.name = name
self.age = age

def run(self):
print('a dog runs with four legs running')

class kangroo(animal):

def __init__(self, name, age):
self.name = name
self.age = age

def run(self):
print('a kangroo runs with two legs jumping')

d = dog('dd', 3)
d.run()

k = kangroo('kk', 5)
k.run()
`

Through abstract classes ：

• Ensure that the subclass contains and implements the corresponding functions
• Ensure the standardization of naming