Python Training Camp 45 days - Day07 (Advanced Object-Oriented Programming)

Keywords: Python Attribute Programming

Catalog

Preface: In the last chapter, we learned the basic knowledge of object-oriented. In this chapter, we will further explore the object-oriented knowledge system.

1. @property decorator

In the previous chapter, when we talked about access rights of attributes, although we do not recommend setting attributes to private, it is also problematic to expose attributes directly to the outside world, for example, we can not check whether the value assigned to attributes is valid. Our previous suggestion was to start the attribute naming with a single underline, which implies that the attribute is protected, but the logic of checking the attribute is in the method, and we can't let it go through the example. When assigning the attribute, we also go through the set of logic of checking the attribute. If we want to do this, we need to wrap getter and setter methods with the @property decorator

# -*- coding:utf-8 -*-
"""
@Property Decorator
version:0.1
author:coke
"""
class Person(object):

    def __init__(self,name,age):
        self.__name = name
        self.__age = age
    
    #Accessor
    @property
    def name(self):
        return self.__name 
    
    #Accessor - getter method
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self,age):
        if age < 0 or age > 150:
            print("Age parameter incorrect")
            return
        self.__age = age
    
    def play(self):
        if self.__age <= 16:
            print("%s Playing flying chess."%self.__name)
        else:
            print("%s Playing with the landlord."%self.__name)

def main():
    person = Person("Jack",12)
    person.age = -1
    person.play()

if __name__ == "__main__":
    main()

Output result

 

Summary: @property is widely used in the definition of classes, allowing callers to write short code while ensuring that the parameters are checked as necessary, thus reducing the possibility of errors at run time.

 

2. Magic Method

Python is a door Dynamic language . In general, dynamic languages allow us to bind new attributes or methods to objects while the program is running. Of course, we can also unbind the bound attributes and methods. But if we need to qualify objects of custom types that can only bind certain properties, we can qualify them by defining _slots_ variables in the class. It should be noted that the _slots_ restriction only works on the object of the current class and does not work on subclasses.

# -*- coding:utf-8
"""
slots
version:0.1
author:coke
"""


class Person(object):
   # Restricting Person objects can only bind _name,_age and _gender attributes
   __slots__ = ('_name', '_age', '_gender')

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

   @property
   def name(self):
       return self._name

   @property
   def age(self):
       return self._age

   @age.setter
   def age(self, age):
       self._age = age

   def play(self):
       if self._age <= 16:
           print("%s Playing flying chess, age%d" % (self._name, self._age))
       else:
           print("%s Playing with the landlord, age%d" % (self._name, self._age))

def main():
   person = Person("Jack",18)
   person.play()

if __name__ == "__main__":
   main()

Summary: The _slots_ variable can be used to restrict the attributes that the class instance can add.

 

3. Class and instance attributes

In the previous example, we came across instance attributes (object attributes). As the name implies, class attributes are attributes owned by class objects. They are shared by all instance objects of class objects. There is only one copy in memory. For public class attributes, class objects and instances can be used outside the class. Object access
 
Class attribute

class People(object):
    address = "Shandong"
    def __init__(self):
        self.name = "xiaowang" #Instance attribute
        self.age = 20

p = People()
p.age = 12
print(p.address) #Correct
print(People.address) #Correct
print(p.name) #Correct
print(p.age) #Correct

print(People.address)#Correct
#print(People.age) #error
#print(People.name) #error

Summary: Instance attributes can not be obtained by class objects. Instance attributes can be obtained either by class objects. class attributes or by instance objects. class attributes.

 

Modifying class attributes through instances (objects)

class People(object):
    country = 'china' #Class attribute

print(People.country) #china
p = People()
print(p.country)  #china
p.country = "japan"
print(p.country) #japan
print(People.country) #china
del p.country
print(p.country) #china

Summary: Although class attributes can be accessed through instance objects. class attributes, instance objects can not modify and delete class attributes. If instance objects declare the same name attributes, the attributes belong to instance attributes.

 

4. Static methods and class methods

Previously, the methods we defined in classes were all object methods, that is to say, they were all messages sent to objects. In fact, the methods we write in classes do not need to be all object methods. We can also create static methods and class methods as needed.

 
Static method

"""
//Static method
version:0.1
author:coke
"""
from math import sqrt

class Triangle(object):
    def __init__(self,a,b,c):
        self._a = a
        self._b = b
        self._c = c
    
    @staticmethod
    def is_valid(a,b,c):
        return a + b > c and b + c > a and a + c > b
    
    def perimeter(self):
        return self._a + self._b + self._c
    
    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))
    
def main():
    a,b,c = 3,4,5
    if Triangle.is_valid(a,b,c):
        t = Triangle(a,b,c)
        print(t.perimeter())
        print(t.area())
    else:
        print("Can't form a triangle")

if __name__ == '__main__':
    main()
        

Summary: Modification by modifier @static method is called static method, and static method can be directly invoked by class object.

 

Class method

"""
//Class method
version:0.1
author:coke
"""
from time import time, localtime, sleep

class Clock(object):
    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        ctimes = localtime(time())
        return cls(ctimes.tm_hour, ctimes.tm_min, ctimes.tm_sec)

    def run(self):
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._hour += 1
                self._minute = 0
                if self._hour == 24:
                    self._hour = 0
    
    def show(self):
        return "%02d:%02d:%02d" % \
        (self._hour,self._minute,self._second)
            
    
def main():
    clock = Clock.now()
    while True:
        print(clock.show())
        sleep(1)
        clock.run()

if __name__ == "__main__":
    main()

Summary: The modifier @classmethod is used to identify the class method. For the class method, the first parameter must be class object. Generally, cls is used as the first parameter. It can be accessed through instance object and class object. Because the cls parameter is equal to the indirect class information, we can also get the class information by using cls parameter. Class method creates a class object

 

5. Single Inheritance and Multiple Inheritance

In the program, inheritance describes the relationship between things, such as cats and dogs belong to animals, which can be described as cats and dogs inheritance automata. Similarly, Persian cats and Bali cats inherit from cats, while sandpigs and spotted dogs inherit sufficiently, as follows:

Single inheritance refers to inheriting only one parent class information, while multiple inheritance refers to inheriting more than one parent class information. It should be noted that most programming languages only allow single inheritance, because there will be problems caused by diamond inheritance. But in python, it accidentally allowed multiple inheritance to occur.
 
Single inheritance

# Inheritance of object class parent information
class Person(object):
    """people"""

    def __init__(self,name,age):
        self._name = name
        self._age = age
    
    @property
    def name(self):
        return self._name
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self,age):
        self._age = age
    
    def play(self):
        print("%s Playing happily."% self._name)

    def watch_tv(self):
        if self._age >= 18:
            print("%s Watching exciting movies"%self._name)
        else:
            print("%s Watching bears come and go"%self._name)
    
# (person) inherits person parent information
class Student(Person):
    def __init__(self,name,age,grade):
        super().__init__(name,age)
        self._grade = grade
    
    @property
    def grade(self):
        return self._grade
    
    @grade.setter
    def grade(self):
        self._grade = grade
    
    def study(self,course):
        print("%s Of%s I am learning%s."%(self._grade,self._name,course))

#Inheritance of person parent information
class Teacher(Person):
    """Teacher"""
    def __init__(self,name,age,title):
        super().__init__(name,age)
        self._title = title
    
    @property
    def title(self):
        return self._title
    
    @title.setter
    def title(self,title):
        self._title = title
    
    def teacher(self,course):
        print("%s%s Talking about%s."%(self._name,self._title,course))
    
def main():
    stu = Student("Jack",15,"Second day")
    stu.study("Mathematics")
    stu.watch_tv()
    t = Teacher("Marry",38,"Expert Professor")
    t.teacher("Chinese")
    t.watch_tv()

if __name__ == "__main__":
    main()    

Output result

 

Multiple inheritance

#coding=utf-8
class base(object):
    def test(self):
        print('----base test----')
class A(base):
    def test(self):
        print('----A test----')

# Define a parent class
class B(base):
    def test(self):
        print('----B test----')

# Define a subclass that inherits from A and B
class C(A,B):
    pass


obj_C = C()
obj_C.test()

print(C.__mro__) #You can see the sequence of object search methods for class C

Output result

Summary: When the problem of diamond inheritance arises, who to call depends on the order of parsing.( MRO)

 

6. polymorphism

After inheriting the methods of the parent class, the subclass can give a new implementation version of the existing methods of the parent class. This action is called override. Through method rewriting, we can make the same behavior of the parent class have different implementation versions in the subclass. When we call the method rewritten by the subclass, different subclass objects will show different behavior, which is poly morphism.

"""
//polymorphic
version:0.1
author:coke
"""
from abc import ABCMeta,abstractmethod

class Pet(object,metaclass=ABCMeta):
    """
        //Pets
    """
    def __init__(self, nickname):
        self._nickname = nickname
    
    @abstractmethod
    def make_voice(self):
        """Voice"""
        pass

class Dog(Pet):
    """Dog"""
    def make_voice(self):
        print('%s: Wang Wang Wang...' %self._nickname)

class Cat(Pet):
    def make_voice(self):
        print("%s: cat...." %self._nickname)

def main():
    #Using Polymorphism to Output Different Sounds
    pets = [Dog('Prosperous wealth'),Cat('Katie'),Dog('Sola')]
    for pet in pets:
        pet.make_voice()

if __name__ == '__main__':
    main()

Parsing: using ABC module to implement Abstract classes, abc.ABCMeta is a basic class to implement Abstract classes, and @ abstractmethod defines abstract methods without implementing functions. Subclasses inherit abstract classes and must rewrite abstract methods of abstract classes. An abstract method is like a template method

 

7. del method

When an object is created, the python interpreter defaults to calling the _init_() method; when an object is deleted, the python interpreter also defaults to calling a method, which is the _del_() method.

import time
class Animal(object):
    #Initialization method
    #Called automatically after the object is created
    def __init__(self,name):
        print("init Method is called")
        self.__name = name
    
    #Deconstruction method
    #When an object is deleted, it is automatically called
    def __del__(self):
        print("del Method is called")
        print("%s The object was immediately destroyed...."%self.__name)

dog = Animal("Pastoral dogs")
#delete object
del dog

cat = Animal("Persian cat")
print("Ready to delete the Persian cat....")
del cat

Output result

Posted by HughbertD on Thu, 26 Sep 2019 04:04:13 -0700