python Foundation (24): one of the three characteristics of object-oriented (inheritance)

Keywords: Python Attribute Programming Linux

1. inheritance

1.1 what is inheritance

Inheritance is a way to create a new class. In python, a new class can inherit one or more parent classes. The parent class can also be called a base class or a superclass. The new class is called a derived class or a subclass.

The inheritance of classes in python can be divided into single inheritance and multiple inheritance.

class ParentClass1: #Defining parent class
  pass

class ParentClass2: #Defining parent class
  pass

class SubClass1(ParentClass1): #Single inheritance, base class is ParentClass1,Derived classes are SubClass
  pass

class SubClass2(ParentClass1,ParentClass2): #python Support multiple inheritance, separate multiple inherited classes with commas
  pass

View inheritance:

>>> SubClass1.__bases__ #__base__Only the first subclass inherited from left to right is viewed,__bases__View all inherited parent classes
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

Tip: if no base class is specified, python class will inherit the object class by default. Object is the base class of all Python classes. It provides some common methods (such as the implementation of \\\\\\\\.

>>> ParentClass1.__bases__
(<class 'object'>,)
>>> ParentClass2.__bases__
(<class 'object'>,)

1.2 inheritance and abstraction

Abstraction is the extraction of similar or more similar parts.

There are two levels of abstraction:

1. Extract the similar parts of Obama and Messi into categories

2. Extract the similar parts of human, pig and dog into the parent class.

The main function of abstraction is to classify (to isolate concerns and reduce complexity)

Inheritance: it is based on the result of abstraction. To realize it through programming language, we must first go through the process of abstraction before we can express the abstract structure through inheritance.

Abstract is just an action or a skill in the process of analysis and design, through which class can be obtained

 

 

1.3 inheritance and reusability

An example of using inheritance to solve code reuse:

==========================Part I
 for example

Cats can: eat, drink, climb trees

Dogs can: eat, drink and watch the house

If we want to create a class for the cat and the dog, we need to implement all their functions for the cat and the dog. The pseudo code is as follows:


#Cats and dogs have a lot of the same content
 class cat:

    def eat (self):
        # do something

    def drink (self):
        # do something

    def self:
        # do something



class dog:

    def eat (self):
        # do something

    def drink (self):
        # do something

    def self:
        #do something


==========================Part II
 It's not hard to see that eating and drinking are the functions of both cats and dogs, but we have written them twice in our cat and dog classes respectively. If the idea of inheritance is used, it is implemented as follows:

Animals: eating and drinking

Cats: climbing trees (cats inherit the functions of animals)

Dog: watch the house (dog inherits the function of animal)

The pseudo code is as follows:
class animal:

    def eat (self):
        # do something

    def drink (self):
        # do something

#Write another class name in parentheses after the class, indicating that the current class inherits another class
 class cat (animal):

    def self:
        print 'meow'

#Write another class name in parentheses after the class, indicating that the current class inherits another class
 class dog (animal):

    def self:
        print 'bark'


==========================Part III
 #Inherited code implementation
class Animal:

    def eat(self):
        print("%s eat"% self.name) "

    def drink(self):
        print ("%s drink"% self.name) "

class Cat(Animal):

    def __init__(self, name):
        self.name = name
        self.breed = 'cat'

    def climb(self):
        print('tree climbing ')

class Dog(Animal):

    def __init__(self, name):
        self.name = name
        self.breed = 'dog'

    def look_after_house(self):
        print('barking ')


#Execution#########

c1 = Cat('little black cat of little white '
c1.eat()

c2 = Cat('little black little white cat ')
c2.drink()

d1 = Dog('Fat family's little skinny dog ')
d1.eat()

In the process of developing the program, if we define a Class A and then want to create another class B, but most of the content of class B is the same as that of class A.

We can't write a class B from scratch, which uses the concept of class inheritance.

Create A new class B through inheritance, let B inherit A, and B will 'inherit' all attributes (data attributes and function attributes) of A, so as to realize code reuse.

class Animal:
    '''
    //People and dogs are animals, so create an Animal base class
    '''
    def __init__(self, name, aggressivity, life_value):
        self.name = name  # People and dogs have their own nicknames;
        self.aggressivity = aggressivity  # Man and dog have their own attack power;
        self.life_value = life_value  # People and dogs have their own life values;

    def eat(self):
        print('%s is eating'%self.name)

class Dog(Animal):
    pass

class Person(Animal):
    pass

egg = Person('egon',10,1000)
ha2 = Dog('Two Leng Zi',50,1000)
egg.eat()
ha2.eat()

Tip: build a new class with the existing classes, so that you can reuse part of the existing software settings, which greatly generates programming workload. This is often called software reuse, which can not only reuse your own classes, but also inherit others', such as standard library, to customize new data types, which greatly shortens the software development cycle, for large-scale software Software development is of great significance.

1.4 derivation

Of course, a subclass can also add its own new properties or redefine these properties here (which will not affect the parent class). It should be noted that once its own properties are redefined and have the same name as the parent class, when calling the new properties, it will be based on itself.

class Animal:
    '''
    //People and dogs are animals, so create an Animal base class
    '''
    def __init__(self, name, aggressivity, life_value):
        self.name = name  # People and dogs have their own nicknames;
        self.aggressivity = aggressivity  # Man and dog have their own attack power;
        self.life_value = life_value  # People and dogs have their own life values;

    def eat(self):
        print('%s is eating'%self.name)

class Dog(Animal):
    '''
    //Dog class, inherit Animal class
    '''
    def bite(self, people):
        '''
        //Derivation: dogs have the ability to bite people
        :param people:  
        '''
        people.life_value -= self.aggressivity

class Person(Animal):
    '''
    //Human, inherit Animal
    '''
    def attack(self, dog):
        '''
        //Derivation: people have attack skills
        :param dog: 
        '''
        dog.life_value -= self.aggressivity

egg = Person('egon',10,1000)
ha2 = Dog('Two Leng Zi',50,1000)
print(ha2.life_value)
print(egg.attack(ha2))
print(ha2.life_value)

Note: for attribute references such as ha2.life'u value, you will first find life'u value from the instance, then find it in the class, then find it in the parent class... Until the top-level parent class.

In the subclass, when editing the function in the function, the newly created function attribute with duplicate name in the parent class may need to reuse the function function with duplicate name in the parent class. It should be called in the way of ordinary function, i.e. class name. func(), which is the same as calling ordinary function. Therefore, even the self parameter should pass value for it.

In python3, the method of subclass executing parent class can also use super method directly.

class A:
    def hahaha(self):
        print('A')

class B(A):
    def hahaha(self):
        super().hahaha()
        #super(B,self).hahaha()
        #A.hahaha(self)
        print('B')

a = A()
b = B()
b.hahaha()
super(B,b).hahaha()
class Animal:
    '''
    //People and dogs are animals, so create an Animal base class
    '''
    def __init__(self, name, aggressivity, life_value):
        self.name = name  # People and dogs have their own nicknames;
        self.aggressivity = aggressivity  # Man and dog have their own attack power;
        self.life_value = life_value  # People and dogs have their own life values;

    def eat(self):
        print('%s is eating'%self.name)

class Dog(Animal):
    '''
    //Dog class, inherit Animal class
    '''
    def __init__(self,name,breed,aggressivity,life_value):
        super().__init__(name, aggressivity, life_value) #Execute parent class Animal Of init Method
        self.breed = breed  #Derived new properties

    def bite(self, people):
        '''
        //A new skill has been developed: dogs have the ability to bite people
        :param people:  
        '''
        people.life_value -= self.aggressivity

    def eat(self):
        # Animal.eat(self)
        #super().eat()
        print('from Dog')

class Person(Animal):
    '''
    //Human, inherit Animal
    '''
    def __init__(self,name,aggressivity, life_value,money):
        #Animal.__init__(self, name, aggressivity, life_value)
        #super(Person, self).__init__(name, aggressivity, life_value)
        super().__init__(name,aggressivity, life_value)  #Executing the init Method
        self.money = money   #Derived new properties

    def attack(self, dog):
        '''
        //New skills have been derived: people have the ability to attack
        :param dog: 
        '''
        dog.life_value -= self.aggressivity

    def eat(self):
        #super().eat()
        Animal.eat(self)
        print('from Person')

egg = Person('egon',10,1000,600)
ha2 = Dog('Two Leng Zi','Siberian Husky',10,1000)
print(egg.name)
print(ha2.name)
egg.eat()

Through inheritance, the relationship between derived classes and base classes is established. It is a 'yes' relationship, for example, white horse is a horse, human is an animal.

When there are many same functions between classes, it is better to extract these common functions to make a base class and use inheritance, for example, a professor is a teacher

>>> class Teacher:
...     def __init__(self,name,gender):
...         self.name=name
...         self.gender=gender
...     def teach(self):
...         print('teaching')
... 
>>> 
>>> class Professor(Teacher):
...     pass
... 
>>> p1=Professor('egon','male')
>>> p1.teach()
teaching

1.5 abstract class and interface class

1.5.1 interface class

Inheritance has two uses:

One: inherit the methods of the base class and make your own changes or extensions (code reuse).

Second, declare that a subclass is compatible with a base class, and define an Interface class Interface. The Interface class defines some Interface names (function names) and does not implement the functions of the Interface. The subclass inherits the Interface class and implements the functions of the Interface.

class Alipay:
    '''
    //Alipay payment
    '''
    def pay(self,money):
        print('Alipay paid.%s element'%money)

class Applepay:
    '''
    apple pay payment
    '''
    def pay(self,money):
        print('apple pay Paid.%s element'%money)

def pay(payment,money):
    '''
    //Payment function, overall responsible for payment
    //Corresponding payment object and amount to be paid
    '''
    payment.pay(money)

p = Alipay()
pay(p,200)

Problems in development:

class Alipay:
    '''
    //Alipay payment
    '''
    def pay(self,money):
        print('Alipay paid.%s element'%money)

class Applepay:
    '''
    apple pay payment
    '''
    def pay(self,money):
        print('apple pay Paid.%s element'%money)

class Wechatpay:
    def fuqian(self,money):
        '''
        //The function of pay is implemented, but the name is different
        '''
        print('Wechat paid%s element'%money)

def pay(payment,money):
    '''
    //Payment function, overall responsible for payment
    //Corresponding payment object and amount to be paid
    '''
    payment.pay(money)

p = Wechatpay()
pay(p,200)   #Error in execution meeting

Interface initialization: manually report exception: notimplemented error to solve problems encountered in development.

class Payment:
    def pay(self):
        raise NotImplementedError

class Wechatpay(Payment):
    def fuqian(self,money):
        print('Wechat paid%s element'%money)

p = Wechatpay()  #No mistake here
pay(p,200)      #Wrong report here

Use abc module to implement the interface.

from abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass

class Wechatpay(Payment):
    def fuqian(self,money):
        print('Wechat paid%s element'%money)

p = Wechatpay() #If it's not adjusted, it's wrong

In practice, the first meaning of inheritance is not very significant, or even harmful. Because it makes subclass and base class appear strong coupling.

The second meaning of inheritance is very important. It is also called "interface inheritance".
Interface inheritance essentially requires "making a good abstraction, which specifies a compatible interface, so that external callers do not need to care about specific details, and can handle all objects that implement a specific interface equally" - this is called normalization in programming.

Normalization enables high-level external users to process all interface compatible object sets indiscriminately -- just like the concept of linux pan file, everything can be treated as a file, regardless of whether it is memory, disk, network or screen (of course, for the low-level designers, it can also distinguish "character device" and "block device", and then make Targeted design: the level of detail depends on the needs).

Dependency Inversion Principle:

High level modules should not rely on low-level modules, both of which should rely on their abstractions; abstractions should not rely on details; details should rely on abstractions. In other words, program for the interface, not for the implementation.

Why interface:

There is no keyword called interface in python at all. The code above just looks like an interface, but it doesn't play the role of an interface. Subclasses don't need to implement interfaces. If you have to imitate the concept of interfaces, you can use third-party modules.

Interface extracts a group of common functions, which can be regarded as a collection of functions.

Then let the subclass implement the function in the interface.

The significance of doing this is normalization. What is normalization? As long as the classes are implemented based on the same interface, all the objects generated by these classes are the same in use.

Normalization, so that users do not need to care about what the object class is, just need to know that these objects have some functions, which greatly reduces the user's use difficulty.

For example, we define an animal interface, in which there are interface functions such as run, eat, and breath. In this way, the mouse class implements the interface, and the squirrel class also implements the interface. The two generate a mouse and a squirrel respectively and send them to you. Even if you don't know which mouse is which, you must know that they can both run, eat, and breathe .

Another example: we have a car interface, which defines all the functions of the car. Then Honda, Audi and Volkswagen all implement the car interface, which is easy to do. You only need to learn how to drive a car, so we can drive a car no matter Honda, Audi or Volkswagen. When we drive a car, we don't need to turn it off at all Mind what kind of car I drive, the operation method (function call) is the same.

1.5.2 abstract class

What is an abstract class?

Like java, python also has the concept of abstract class, but it also needs to be implemented by modules. Abstract class is a special class, which can only be inherited and cannot be instantiated.

Why abstract classes?

If a class comes from extracting the same content from a pile of objects, the abstract class comes from extracting the same content from a pile of classes, including data attributes and function attributes.

For example, we have banana class, apple class and peach class. The same content extracted from these classes is the abstract class of fruit. When you eat fruit, you either eat a specific banana or a specific peach...... You can never eat something called fruit.

From a design point of view, if a class is abstracted from a real object, then the abstract class is based on the class abstraction.

From the perspective of implementation, the difference between abstract classes and ordinary classes is that there are abstract methods in abstract classes, which can't be instantiated, can only be inherited, and subclasses must implement abstract methods. This is similar to the interface, but it is different. The answer will be revealed soon.

To implement abstract classes in python:

#Everything is a document
import abc #utilize abc Module implementation abstract class

class All_file(metaclass=abc.ABCMeta):
    all_type='file'
    @abc.abstractmethod #Define abstract methods without implementing functions
    def read(self):
        'Subclass must define read function'
        pass

    @abc.abstractmethod #Define abstract methods without implementing functions
    def write(self):
        'Subclass must define write function'
        pass

# class Txt(All_file):
#     pass
#
# t1=Txt() #Error reporting, subclass does not define abstract method

class Txt(All_file): #Subclasses inherit abstract classes, but must define read and write Method
    def read(self):
        print('Reading method of text data')

    def write(self):
        print('Reading method of text data')

class Sata(All_file): #Subclasses inherit abstract classes, but must define read and write Method
    def read(self):
        print('Reading method of hard disk data')

    def write(self):
        print('Reading method of hard disk data')

class Process(All_file): #Subclasses inherit abstract classes, but must define read and write Method
    def read(self):
        print('Reading method of process data')

    def write(self):
        print('Reading method of process data')

wenbenwenjian=Txt()

yingpanwenjian=Sata()

jinchengwenjian=Process()

#So everyone is normalized,That is, the idea that everything is a document
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()

print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)

1.5.3 abstract class and interface class

The essence of an abstract class is still a class. It refers to the similarity of a group of classes, including data attributes (such as all? Type) and function attributes (such as read and write). The interface only emphasizes the similarity of function attributes.

Abstract class is a direct concept between class and interface, which has some characteristics of class and interface, and can be used to realize normalized design.  

In python, there is no such thing as interface class. Even if we don't define interfaces through special modules, we should have some basic concepts.

1. Multiple inheritance

In the process of inheriting abstract classes, we should avoid inheriting as much as possible;
When you inherit interfaces, we encourage you to inherit more interfaces.

Interface isolation principle:

Use multiple specialized interfaces instead of a single total interface. That is, clients should not rely on interfaces that are not needed.

2. Implementation of the method

In abstract classes, we can make basic implementation for some abstract methods;
In the interface class, any method is only a specification, and specific functions need to be implemented by subclasses.

1.6 succession order and principle

1.6.1 succession order

class A(object):
    def test(self):
        print('from A')

class B(A):
    def test(self):
        print('from B')

class C(A):
    def test(self):
        print('from C')

class D(B):
    def test(self):
        print('from D')

class E(C):
    def test(self):
        print('from E')

class F(D,E):
    # def test(self):
    #     print('from F')
    pass
f1=F()
f1.test()
print(F.__mro__) #Only the new class has this attribute to view the linear list. The classic class does not have this attribute

#New class inheritance order:F->D->B->E->C->A
#Classic class inheritance order:F->D->B->A->E->C
#python3 China unification is a new type
#pyhon2 Chinese talents are divided into new type and classic type

1.6.2 inheritance principle

How does Python implement inheritance? For each class you define, python accountant calculates a method resolution order (MRO) list, which is a simple linear order list of all base classes. For example:

>>> F.mro() #Equate to F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

In order to implement inheritance, python will look for the base class from left to right on the MRO list until it finds the first class that matches this property.
The MRO list is constructed by a C3 linearization algorithm. We will not go deep into the mathematical principle of this algorithm. In fact, it is to merge the MRO lists of all parent classes and follow the following three guidelines:
1. The child class will be checked before the parent class.
2. Multiple parent classes are checked according to their order in the list.
3. If there are two legal choices for the next class, select the first parent class.

Posted by BMorganVA on Wed, 13 Nov 2019 06:54:55 -0800