Section 8 object oriented advanced


Python is an object-oriented language. It also supports three major features of object-oriented programming: inheritance, encapsulation (hiding) and polymorphism.

·Encapsulation (hidden)
Hide the properties and implementation details of the object, and only provide necessary methods. It is equivalent to "encapsulating details" and only exposing "relevant calling methods".

Realize "encapsulation" through the way of "private attributes and private methods" learned earlier. Python pursues concise syntax. There is no strict syntax level "access control symbol", which is more realized by programmers.

·Inherit
The reusability of the parent class and the inheritance of the child class can be improved.

It is an incremental evolution in design. When the original parent class design remains unchanged, new functions can be added or existing algorithms can be improved.

·Polymorphism
Polymorphism means that the same method call will produce different behaviors due to different objects. In life, such examples abound: the same method of rest, different people have different methods of rest. Zhang San's rest is sleeping, Li Si's rest is playing games, and programmers' rest is "typing a few lines of code".

inherit

Syntax format

Python supports multiple inheritance. A subclass can inherit multiple parent classes. The inherited syntax format is as follows:
   class subclass class name (parent class 1 [, parent class 2,...]):
    class body

If no parent class is specified in the class definition, the default parent class is object Class. in other words, object It is the parent class of all classes, which defines some default implementations common to all classes, such as:__new__(). 

When you define a subclass, you must call the constructor of the parent class in its constructor. The call format is as follows: Parent class name.__init__(self, parameter list)

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    def say_age(self):
        print(self.name, "Your age is:", self.__age)

class Student(Person):
    def __init__(self,name,age,score):
        self.score = score
        Person.__init__(self,name,age) #The constructor contains the constructor that calls the parent class. As needed, not necessary. Subclasses do not automatically call the parent class__ init__ (), we must explicitly call it.

s1 = Student("Zhang San",15,85)
s1.say_age()
print(dir(s1))

result:
Zhang San's age is 15
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'say_age', 'score']

Inheritance and override of class members

  1. Member inheritance: the subclass inherits all members of the parent class except the constructor.
  2. Method override: subclasses can redefine the methods in the parent class, which will override the methods of the parent class, also known as "override"
class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    def say_age(self):
        print(self.name, "Your age is:", self.__age)
    def say_name(self):
        print("I am",self.name)


class Student(Person):
    def __init__(self,name,age,score):
        self.score = score
        Person.__init__(self,name,age) #The constructor contains the constructor that calls the parent class. As needed, not necessary. Subclasses do not automatically call the parent class__ init__ (), we must explicitly call it.

    def say_score(self):
        print(self.name, "Your score is:", self.score)

    def say_name(self):  # Override the method of the parent class
        print("Report to the teacher, I am",self.name)


s1 = Student("Zhang San",15,85)
s1.say_score()
s1.say_name()
s1.say_age()

result:
What's Zhang San's score: 85
 Report to the teacher, I'm Zhang San
 Zhang San's age is 15

View the inheritance hierarchy of a class

Through class method mro() or class attribute__ mro__ You can output the inheritance hierarchy of this class.

class A:pass
class B(A):pass
class C(B):pass
print(C.mro())

result:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

Rewrite__ str__ () method

Object has a__ str__ () method, which is used to return a "description of the object", corresponding to the built-in function str(), which is often used in the print() method to help us view the information of the object. str() can be overridden.

class Person:
    def __init__(self,name,age):
         self.name = name
         self.__age = age


    def __str__(self):
        '''Converts an object into a string, typically used for print method'''

        return "The name is:{0},Age is{1}".format(self.name,self.__age)

p = Person("Gao Qi",18)
print(p)

result:
The name is:Gao Qi,The age is 18

multiple inheritance

Python supports multiple inheritance. A subclass can have multiple "direct parent classes". In this way, it has the characteristics of "multiple parent classes". However, because this will be extremely complicated by the "overall level of class", try to avoid using it.

MRO()

Python supports multiple inheritance. If there are methods with the same name in the parent class, the interpreter will search in order "from left to right" when the child class does not specify the parent class name.

MRO(Method Resolution Order): method resolution order. We can obtain the "class hierarchy" through the mro() method, and the method parsing order is also found according to the "class hierarchy".

class A:
    def aa(self):
        print("aa")
    def say(self):
        print("say AAA!")
class B:
    def bb(self):
        print("bb")
    def say(self):
            print("say BBB!")
class C(B,A):
    def cc(self):
        print("cc")

c = C() 
print(C.mro())  #Print class hierarchy
c.say() #The search method of the interpreter is "from left to right". At this time, say() in class B will be executed

result:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
say BBB!

super() gets the parent class definition

In the subclass, if we want to get the method of the parent class, we can do it through super().

super() is not the parent class of the object definition.

class A:
    def say(self):
        print("A:",self)
        print("sayAAA")
class B(A):
    def say(self):
        # A.say(self) calls the say method of the parent class
        super().say() #Call the method of the parent class through super()
        print("sayBBB")

b = B()
b.say()

result:
A: <__main__.B object at 0x7fe147a8fa90>
sayAAA
sayBBB

polymorphic

Note the following two points about polymorphism:

  1. Polymorphism is the polymorphism of methods, and there is no polymorphism of attributes.
  2. There are two necessary conditions for polymorphism: Inheritance and method rewriting.
class Animal:

    def shout(self):
        print("The animal gave a cry")

class Dog(Animal):
    def shout(self):
        print("Puppy, woof, woof")

class Cat(Animal):
    def shout(self):
        print("Kitten, meow, meow")

def animalShout(a):
    if isinstance(a,Animal):
        a.shout() #The actual behavior of the shot method is different depending on the incoming object.


animalShout(Dog())
animalShout(Cat())

result:
Puppy, woof, woof
 Kitten, meow, meow

Overloading of special methods and operators

Special properties

Shallow and deep copies of objects

·Assignment of variables
Only two variables are formed, which actually point to the same object.
·Shallow copy
Python copies are generally shallow copies. When copying, the sub object content contained in the object is not copied. Therefore, the source object and the copy object will reference the same child object.
·Deep copy
Use the deepcopy function of the copy module to recursively copy the sub objects contained in the object. All child objects of the source object and the copy object are also different.

combination

For the "is-a" relationship, we can use "inheritance". So as to realize the methods and properties of the parent class owned by the child class. "Is-a" relationship refers to a relationship similar to this: dog is animal and dog is animal. Dogs should inherit animals.

"Has-a" relationship, we can use "composition", and we can also realize that one class has the methods and properties of another class. " The "has-a" relationship refers to the relationship that the mobile phone has a CPU. MobilePhone has a CPU.

Design mode_ Factory mode implementation

The factory mode realizes the separation of creator and caller. Special factory classes are used to uniformly manage and control the selected implementation classes and creation objects.

class CarFactory:
    def createCar(self,brand):
        if brand == "Benz":
            return Benz()
        elif brand == "bmw":
            return BMW()
        elif brand == 'BYD':
            return BYD()
        else:
            return "Unknown brand, unable to create"

class Benz:
    pass
class BMW:
    pass
class BYD:
    pass

factory = CarFactory()
c1 = factory.createCar("Benz")
c2 = factory.createCar("bmw")
print(c1)
print(c2)

result:
<__main__.Benz object at 0x7f8fbb17f9e8>
<__main__.BMW object at 0x7f8fbb1bab70>

Design mode_ Singleton mode implementation

The core function of singleton pattern is to ensure that there is only one instance of a class and provide a global access point to access the instance.
Singleton mode only generates one instance object, which reduces the overhead of system resources. When the generation of an object requires more resources, such as reading configuration files and generating other dependent objects, a "singleton object" can be generated and then permanently stored in memory, which greatly reduces the overhead.
Singleton mode can be implemented in many ways. We recommend rewriting it here__ new__ () method.

class MySingleton:
    __obj = None
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)

        return cls.__obj

    def __init__(self, name):
        if MySingleton.__init_flag:
            print("init....")

            self.name = name
            MySingleton.__init_flag = False


a = MySingleton("aa")
print(a)
b = MySingleton("bb")
print(b)

result:
init....
<__main__.MySingleton object at 0x7ff1ea17fac8>
<__main__.MySingleton object at 0x7ff1ea17fac8>

Keywords: Python

Added by [ArcanE] on Tue, 08 Feb 2022 20:44:03 +0200