1, Object oriented
The core of process oriented programming is process (pipeline thinking). Process is the step to solve the problem. Process oriented design is like carefully designing a pipeline and considering when to deal with what.
The advantage is that it greatly reduces the complexity of writing programs, and only needs to stack the code along the steps to be executed.
The disadvantage is: a set of pipeline or process is used to solve a problem, and the code affects the whole body.
Application scenario: once the scenario is completed, it rarely changes. Famous examples include Linux kernel, git, Apache HTTP Server, etc.
The core of object-oriented programming is the object (God thinking). To understand what the object is, we must regard ourselves as God. In God's eyes, all things in the world are objects, and those that do not exist can also be created.
The advantage is that it solves the scalability of the program. If you modify an object individually, it will be immediately reflected in the whole system. For example, it is easy to modify the characteristics and skills of a character parameter in the game.
Disadvantages: poor controllability, unable to predict the processing flow and results of problems to the process oriented programming pipeline. Once the object-oriented program starts, the problems are solved by the interaction between objects, and even God cannot predict the final results.
In python, object-oriented programming is not all.
Object oriented programming can make program maintenance and expansion easier, and can greatly improve program development efficiency. In addition, object-oriented program can make it easier for people to understand your code logic, so as to make team development more leisurely.
Know some nouns: class, object, instance, instantiation
Class: a class of things (people, dogs, tigers) with the same characteristics
Object / example: a specific thing (ah Hua next door, Wangcai downstairs)
Instantiation: the process of class - > object (this is not obvious in life, we will explain it later)
def functionName(args): 'Function document string' Function body ''' class Class name: 'Class' Class body ''' #Let's create a class class Data: pass
class Person: #Define a human being role = 'person' #People's role attributes are people def walk(self): #People can walk, that is, there is a way to walk print("person is walking...") print(Person.role) #View person's role properties print(Person.walk) #Reference the walking method of people. Note that this is not a call
Instantiation: the class name is instantiated with parentheses, which will be triggered automatically__ init__ Function can be used to customize its own characteristics for each instance
class Person: #Define a human being role = 'person' #People's role attributes are people def __init__(self,name): self.name = name # Each character has its own nickname; def walk(self): #People can walk, that is, there is a way to walk print("person is walking...") print(Person.role) #View person's role properties print(Person.walk) #Reference the walking method of people. Note that this is not a call
The process of instantiation is the process of class - > object
Originally, we had only one Person class. In this process, we generated an egg object with its own specific name, attack power and health value.
Syntax: object name = class name (parameter)
self: automatically pass the object / instance itself to the__ init__ For the first parameter, you can also give him an individual name, but normal people don't do that.
Because you changed, others don't know
Class attribute supplement
1: Where are the properties of the class we defined? There are two ways to view dir(Class name): It's a list of names Class name.__dict__:It's a dictionary, key Is the property name, value Attribute value 2: Special class properties Class name.__name__# Class name (string) Class name.__doc__# Class Class name.__base__# The first parent class of class (I will talk about inheritance) Class name.__bases__# Class is a tuple composed of all parent classes (I will talk about inheritance) Class name.__dict__# Dictionary properties of class Class name.__module__# The module where the class definition is located Class name.__class__# Class corresponding to instance (only in new class)
class Class name: def __init__(self,Parameter 1,Parameter 2): self.Property 1 of object = Parameter 1 self.Properties of object 2 = Parameter 2 def Method name(self):pass def Method name 2(self):pass Object name = Class name(1,2) #An object is an instance that represents a concrete thing #Class name (): class name + parentheses is to instantiate a class, which is equivalent to calling__ init__ method #Parameters are passed in parentheses. Parameters do not need to be passed to self. Other parameters correspond to the formal parameters in init one by one #The result returns an object Object name.Property 1 of object #To view the properties of an object, you can directly use the object name. Property name Object name.Method name() #Call the method in the class directly with the object name. Method name ()
Exercise 1: output the following information at the terminal
Xiao Ming, 10 years old, male, went up the mountain to cut firewood
Xiao Ming, 10 years old, male, drives to the northeast
Xiao Ming, 10 years old, male, loves big health care best
Lao Li, 90, male, went up the mountain to cut firewood
Lao Li, 90, male, drove to the northeast
Lao Li, 90 years old, male, loves big health care best
Class namespace and object namespace
Creating a class will create a class namespace to store all the names defined in the class. These names are called class properties
Classes have two kinds of properties: static properties and dynamic properties
Static attributes are variables defined directly in a class
A dynamic attribute is a method defined in a class
The data properties of the class are shared to all objects
>>>id(egg.role) 4341594072 >>>id(Person.role) 4341594072 The dynamic properties of a class are bound to all objects >>>egg.attack <bound method Person.attack of <__main__.Person object at 0x101285860>> >>>Person.attack <function Person.attack at 0x10127abf8>
Creating an object / instance will create an object / instance namespace to store the name of the object / instance, which is called the attribute of the object / instance
In obj.name, you will first find name from obj's own namespace. If you can't find it, you will find it in the class. If the class can't find it, you will find the parent class... Finally, if you can't find it, you will throw an exception
2, Three characteristics of object-oriented: inheritance, polymorphism and encapsulation
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 superclass, and the new class is called a derived class or subclass
Class inheritance in python is divided into single inheritance and multi inheritance
class ParentClass1: #Define parent class pass class ParentClass2: #Define parent class pass class SubClass1(ParentClass1): #Single inheritance, the base class is ParentClass1, and the derived class is SubClass pass class SubClass2(ParentClass1,ParentClass2): #python supports multiple inheritance, separating multiple inherited classes with commas pass
Importance of inheritance
========================================PART ONE for example Cats can climb trees, eat, drink, pull and scatter Dogs can: watch the door, eat, drink, pull and sprinkle If we want to create a class for cats and dogs respectively, we need to implement all their functions for cats and dogs. The pseudo code is as follows: #Cats and dogs have a lot in common class Cat: def climb up a tree(self): print 'climb up a tree' def eat(self): # do something def drink(self): # do something def PULL(self): # do something def Scatter(self): # do something class dog: def Janitor(self): print 'Janitor' def eat(self): # do something def drink(self): # do something def PULL(self): # do something def Scatter(self): # do something ===================================PART TWO It is not difficult to see from the above code that eating, drinking, pulling and scattering are the functions of both cats and dogs, but we have written them twice in the cat and dog classes respectively. If the idea of inheritance is used, the implementation is as follows: Animals: eat, drink, pull and sprinkle Cat: climbing trees (cats inherit animal functions) Dog: watchdog (dog inherits animal function) The pseudo code is as follows: class animal: def eat(self): # do something def drink(self): # do something def PULL(self): # do something def Scatter(self): # do something # Write another class name in parentheses after the class, indicating that the current class inherits another class class cat(animal): def climb up a tree(self): print 'climb up a tree' # Write another class name in parentheses after the class, indicating that the current class inherits another class class dog(animal): def Janitor(self): print 'Janitor' ================================PART THREE #Inherited code implementation class Animal: def eat(self): print("%s eat " %self.name) def drink(self): print ("%s drink " %self.name) def shit(self): print ("%s PULL " %self.name) def pee(self): print ("%s Scatter " %self.name) class Cat(Animal): def __init__(self, name): self.name = name self.breed = 'cat' def climb up a tree(self): print 'climb up a tree' class Dog(Animal): def __init__(self, name): self.name = name self.breed='dog' def Janitor(self): print 'Janitor' # ######### implement ######### c1 = Cat('Xiaobai's little black cat') c1.eat() c2 = Cat('Little black little white cat') c2.drink() d1 = Dog('Fat man's little thin dog') d1.eat()
So much inheritance?
Can I inherit multiple classes
If the inherited multiple classes have the same function in each class, which one will be used?
1. Python classes can inherit multiple classes, while Java and C # can only inherit one class
2. If a Python class inherits multiple classes, there are two ways to find methods: depth first and breadth first
When the class is a classic class, in the case of multiple inheritance, it will be searched according to the depth first method
When the class is a new class, in the case of multiple inheritance, it will be searched according to the breadth first method
The classic class and the new class can be seen literally, one old and one new. The new class must contain the following functions, which is also the recommended writing method. If the writing method is distinguished, if the current class or parent class inherits the object class, then the class is a new class, otherwise it is a classic class.
class D: def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar(self): print 'B.bar' class A(B, C): def bar(self): print 'A.bar' a = A() # When executing the bar method # First, search in class A. if it is not found in class A, continue to search in class B. if it is not found in class B, continue to search in class D. if it is not found in class D, continue to search in class C. if it is still not found, an error is reported # Therefore, the search order is: a -- > B -- > D -- > C # In the above search method, once found, the search process will be interrupted immediately, and the search will not continue a.bar() Classic class multi inheritance
class D(object): def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar(self): print 'B.bar' class A(B, C): def bar(self): print 'A.bar' a = A() # When executing the bar method # First, search in class A. if it is not found in class A, continue to search in class B. if it is not found in class B, continue to search in class C. if it is not found in class C, continue to search in class D. if it is still not found, an error will be reported # Therefore, the search order is: a -- > B -- > C -- > D # In the above search method, once found, the search process will be interrupted immediately, and the search will not continue a.bar() New class multi inheritance
Python does not support polymorphic writing in strongly typed languages such as Java and C#, but it is native polymorphic. Python advocates "duck type".
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' # Because in Java or C#When defining a function parameter in, you must specify the type of the parameter # In order to enable Func function to execute both the show method of S1 object and the show method of S2 object, a parent class of S1 and S2 classes is defined # The parameters actually passed in are S1 object and S2 object
def Func(F1 obj): """Func Function needs to receive a F1 Type or F1 Type of subclass""" print obj.show() s1_obj = S1() Func(s1_obj) # Pass in S1 class object S1 in Func function_ Obj, execute the show method of S1. Result: S1.show s2_obj = S2() Func(s2_obj) # Pass in the object Ss of the Ss class in the Func function_ Obj, execute the show method of Ss, and the result is S2.show Python Pseudo code implementation Java or C#Polymorphism of
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' def Func(obj): print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj) Python ""Duck type"
Hide the properties and implementation details of the object, and only provide public access.
- Isolate changes;
- Easy to use;
- Improve reusability;
- Improve safety;
1. Hide all contents that do not need to be provided externally;
2. Hide all attributes and provide public methods to access them.
1. Abstract class and interface class
Like java, python also has the concept of abstract class, but it also needs to be implemented with the help of modules. Abstract class is a special class. Its particularity is that it can only be inherited and cannot be instantiated
Why abstract classes
If a class extracts the same content from a pile of objects, then an abstract class extracts 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 perspective, if a class is abstracted from a real object, then the abstract class is based on class abstraction.
From the implementation point of view, the difference between abstract classes and ordinary classes is that there are abstract methods in abstract classes. This class can not be instantiated, but can only be inherited, and subclasses must implement abstract methods. This is a bit similar to the interface, but it is actually different. The answer will be revealed soon
Inheritance serves two purposes:
1: Inherit the methods of the base class and make your own changes or extensions (code reuse)
2: Declare that a subclass is compatible with a base class and define an Interface class Interface. Some Interface names (i.e. function names) are defined in the Interface class and do not implement the functions of the Interface. The subclass inherits the Interface class and implements the functions in the Interface
1. Multiple inheritance
In the process of inheriting abstract classes, we should try to avoid multiple inheritance;
When inheriting interfaces, we encourage you to inherit more interfaces
Interface isolation principle:
Use multiple specialized interfaces instead of a single general interface. That is, the client should not rely on interfaces that are not needed.
2. Implementation of the method
In abstract classes, we can make basic implementations of some abstract methods;
In the interface class, any method is only a specification, and the specific functions need to be implemented by subclasses
Object oriented composite usage
In addition to inheritance, there is another important way of software reuse, that is, composition
Composition refers to taking objects of another class as data attributes in one class, which is called class composition
class Person: def __init__(self,nickname,sex,hp,ad): self.nickname = nickname self.sex = sex self.hp = hp self.ad = ad def attack(self,p1): p1.hp -= self.ad print('%s Attacked%s,%s Remaining%s Blood volume'%(self.nickname,p1.nickname,p1.nickname,p1.hp)) def weapon_attack(self,wea): # Weapon objects are encapsulated into human objects as an attribute. It is called composition self.weapon = wea class Weapon: def __init__(self,name,att): self.name = name self.att = att def Aux_attack(self,p,p1): p1.hp -= self.att print('%s utilize%s Yes%s%s Dripping blood,%s Remaining%s Dripping blood' %(p.nickname,self.name,p1.nickname,self.att,p1.nickname,p1.hp)) # alex = Person('alex ',' male ', 100,20) # barry = Person('taibai ',' male ', 200,50) # axe = Weapon('axe ', 30) # barry.weapon_attack(axe) # barry.weapon.Aux_attack(barry,alex) # axe.Aux_attack(alex) # alex.attack(barry) # alex.attack(barry)
A ring consists of two circles. The area of the ring is the area of the outer circle minus the area of the inner circle. The circumference of the ring is the circumference of the inner circle plus the circumference of the outer circle.
At this time, we first implement a circle class to calculate the circumference and area of a circle. Then, in the "ring class", combine instances of circles as their own properties
from math import pi class Circle: ''' Defines a circular class; Provide calculated area(area)And perimeter(perimeter)Method of ''' def __init__(self,radius): self.radius = radius def area(self): return pi * self.radius * self.radius def perimeter(self): return 2 * pi *self.radius circle = Circle(10) #Instantiate a circle area1 = circle.area() #Calculate circle area per1 = circle.perimeter() #Calculate circumference of circle print(area1,per1) #Print circle area and perimeter class Ring: ''' Defines a torus class Method for providing the area and perimeter of a ring ''' def __init__(self,radius_outside,radius_inside): self.outsid_circle = Circle(radius_outside) self.inside_circle = Circle(radius_inside) def area(self): return self.outsid_circle.area() - self.inside_circle.area() def perimeter(self): return self.outsid_circle.perimeter() + self.inside_circle.perimeter() ring = Ring(10,5) #Instantiate a ring print(ring.perimeter()) #Calculate the circumference of the ring print(ring.area()) #Calculate the area of the ring
The relationship between classes and combined classes is established in the way of composition. It is a kind of "yes" relationship. For example, professors have birthdays and teach python courses
class BirthDate: def __init__(self,year,month,day): self.year=year self.month=month self.day=day class Couse: def __init__(self,name,price,period): self.name=name self.price=price self.period=period class Teacher: def __init__(self,name,gender,birth,course): self.name=name self.gender=gender self.birth=birth self.course=course def teach(self): print('teaching') p1=Teacher('egon','male', BirthDate('1995','1','27'), Couse('python','28000','4 months') ) print(p1.birth.year,p1.birth.month,p1.birth.day) print(p1.course.name,p1.course.price,p1.course.period) ''' Operation results: 1 27 python 28000 4 months '''
When there are significant differences between classes, and the smaller class is the component required by the larger class, it is better to use composition
2. Private variables and methods
In python, the attribute is hidden (set to private) by starting with a double underscore
#In fact, this is just a deformation operation #All double underlined names in the class, such as__ x will automatically become:_ Class name__ Form of x: class A: __N=0 #The data attributes of a class should be shared, but grammatically, the data attributes of a class can be set to private, such as__ N. Will deform into_ A__N def __init__(self): self.__X=10 #Deform to self_ A__ X def __foo(self): #Deformation as_ A__foo print('from A') def bar(self): self.__foo() #It can only be passed inside a class__ foo form access to #A._A__N is accessible, that is, this operation is not strictly restricting external access, but just a deformation in the grammatical sense
Features of this automatic deformation:
1. Defined in class__ X can only be used internally, such as self__ x. The reference is the result of deformation.
2. This deformation is actually aimed at the external deformation, which cannot be passed externally__ The name x is accessible.
3. Defined in subclass__ X does not override the definition of the parent class__ x. Because the subclass becomes:_ Subclass name__ x. The parent class changes into:_ Parent class name__ x. That is, when the attribute at the beginning of the double sliding line is inherited to the subclass, the subclass cannot be overwritten.
The problems needing attention in this deformation are:
1. This mechanism does not really restrict us from directly accessing attributes from the outside. We can spell the name after knowing the class name and attribute name:_ Class name__ Property, and then you can access it, such as a_ A__ N
2. The deformation process only takes effect inside the class. The assignment operation after definition will not deform
In inheritance, if the parent class does not want the child class to override its own method, it can define the method as private
#Normal condition >>> class A: ... def fa(self): ... print('from A') ... def test(self): ... self.fa() ... >>> class B(A): ... def fa(self): ... print('from B') ... >>> b=B() >>> b.test() from B #Define FA as private, i.e__ fa >>> class A: ... def __fa(self): #When defined, it deforms into_ A__fa ... print('from A') ... def test(self): ... self.__fa() #It will only be subject to its own class, that is, call_ A__fa ... >>> class B(A): ... def __fa(self): ... print('from B') ... >>> b=B() >>> b.test() from A
3. Packaging and expansion
Encapsulation is to clearly distinguish the inside and outside, so that the class implementer can modify the things in the encapsulation without affecting the code of the external caller; External users only know one interface (function). As long as the interface (function) name and parameters remain unchanged, the user's code never needs to be changed. This provides a good basis for cooperation -- in other words, code changes are not a concern as long as the basic interface convention remains unchanged.
#Class designer class Room: def __init__(self,name,owner,width,length,high): self.name=name self.owner=owner self.__width=width self.__length=length self.__high=high def tell_area(self): #The external interface hides the internal implementation details. At this time, what we want is the area return self.__width * self.__length #User >>> r1=Room('bedroom','egon',20,20,20) >>> r1.tell_area() #User call interface tell_area #The designer of the class easily extends the function, and the user of the class does not need to change his code at all class Room: def __init__(self,name,owner,width,length,high): self.name=name self.owner=owner self.__width=width self.__length=length self.__high=high def tell_area(self): #The external interface hides the internal implementation. At this time, what we want is the volume. The internal logic has changed. We only need to repair the following line to achieve a very simple implementation. Moreover, the external call is not aware of it. We still use this method, but the function has changed return self.__width * self.__length * self.__high #For still using tell_area interface people can use new functions without changing their own code >>> r1.tell_area()