This article through an example to explain in detail the Python class, inheritance and polymorphism of the definition and usage, very practical, the need for small partners can refer to the following
Definition of Class
If you want to define a class point that represents two-dimensional coordinate points:
# Point.pyclass point: def __init__ (self, x=0, y=0): self.x, self.y = x, y
The most basic is the __init__ method, which is equivalent to the C + +/Java constructor. With double underline __ methods are special methods, in addition to __init__ there are many, the following will be introduced.
The parameter self corresponds to C + + 's This, which represents the current instance, and all methods have this parameter, but the call does not need to be specified.
>>> from point import *>>> p = Point (Ten) # __init__ is called >>> type (p) <class ' point. Point ' >>>> p.x, P.Y (10, 10)
Almost all of the special methods (including __init__) are implicitly invoked (not directly called).
For Python of all objects, the class itself is also an object:
>>> type <class ' type ' >>>> dir (point) [' __class__ ', ' __delattr__ ', ' __dict__ ', ..., ' __ Init__ ', ...] >>> point.__class__<class ' type ' >
Point is an instance of type, which is one thing with P being an instance of point.
Now Add method set:
Class point: ... def set (self, x, y): self.x, self.y = x, y
>>> p = Point (Ten) >>> p.set (0, 0) >>> p.x, p.y (0, 0)
P.set (...) is actually just a syntactic sugar, you can also write Point.set (p, ...), so that you can clearly see that p is the self parameter:
>>> Point.set (p, 0, 0) >>> p.x, p.y (0, 0)
It is important to note that self is not a keyword and can even be substituted with other names, such as this:
Class point: ... def set (this, x, y): this.x, this.y = x, y
Unlike C + +, member variables must be self-added. prefix, otherwise it becomes a property of the class (equivalent to a C + + static member), not the object's properties.
Access control
Python does not have access controls such as Public/protected/private, and if you want to represent "private", the habit is to double-underline the prefix.
Class point: def __init__ (self, x=0, y=0): self.__x, self.__y = x, y def set (self, x, y): self.__x, Self._ _y = x, y def __f (self): Pass
__x, __y, and __f are the equivalent of private:
>>> p = Point (Ten) >>> p.__x ... Attributeerror: ' Point ' object have no attribute ' __x ' >>> p.__f () ... Attributeerror: ' Point ' object has no attribute ' __f '
_repr_
Try to print a point instance:
>>> p = Point (Ten) >>> p<point. Point object at 0x000000000272aa20>
Usually, this is not the output we want, we want to:
>>> PPoint (10, 10)
Adding a special method __repr__ can be implemented:
Class point: def __repr__ (self): return ' point ({}, {}) '. Format (self.__x, self.__y)
It is not difficult to see that the interactive mode when printing p is actually called REPR (p):
>>> repr (P)
' Point (10, 10) '
_str_
If __str__,str () is not provided, the result of using repr () is defaulted.
Both are representations of the object's string form, but they are somewhat different. In short, the results of repr () are oriented to the interpreter, which is usually a valid Python code, such as Point (10, 10), while the result of STR () is user-friendly, more concise, such as (10, 10).
In accordance with this principle, we provide the __str__ definition for point as follows:
Class point: def __str__ (self): return ' ({}, {}) '. Format (self.__x, self.__y)
_add_
The addition of two coordinate points is a very reasonable requirement.
>>> P1 = Point (Ten) >>> P2 = point (Ten) >>> p3 = p1 + p2traceback (most recent call last): File "<stdin>", line 1, in <module>typeerror:unsupported operand type (s) for +: ' point ' and ' point '
Add a special method __add__ can do:
Class point: def __add__ (self, Other): return Point (self.__x + other.__x, self.__y + other.__y)
>>> P3 = p1 + p2>>> p3point (20, 20)
This is just like operator overloading in C + +.
Python's built-in types, such as strings and lists, are "overloaded" with the + operator.
There are many special methods, which are not introduced here.
Inherited
Give the most common example of a textbook. Circle and Rectangle inherit from shape, and different shapes, areas (area) are computed in different ways.
# Shape.pyclass Shape: def area (self): return 0.0 class Circle (Shape): def __init__ (self, r=0.0): SELF.R = r def area (self): return Math.PI * SELF.R * self.rclass Rectangle (Shape): def __init__ (self, A, b): self.a, self.b = A, b def area (self): return SELF.A * self.b
Usage Comparison Direct:
>>> from shape import *>>> circle = Circle (3.0) >>> Circle.area () 28.274333882308138>> > Rectangle = Rectangle (2.0, 3.0) >>> Rectangle.area () 6.0
If Circle does not define its own area:
Class Circle (Shape): Pass
Then it inherits the area of the parent Shape:
>>> Shape.area is Circle.areatrue
Once Circle has defined its area, the area inherited from Shape is rewritten (overwrite):
>>> from shape import *>>> Shape.area is Circle.areafalse
This can be clearly seen through a dictionary of classes:
>>> shape.__dict__[' area ']<function shape.area at 0x0000000001fdb9d8>>>> circle.__dict__[' Area ']<function Circle.area at 0x0000000001fdbb70>
So, the subclass overrides the parent class's method, but actually binds the same property name to a different function object. It is visible that Python is not a concept of overwrite (override).
Similarly, even if shape does not have an area defined, shape is an "interface" and cannot be guaranteed by syntax.
You can even add a method dynamically:
Class Circle (Shape): ... # def area (self): # return Math.PI * SELF.R * self.r# Add area method to Circle. Circle.area = Lambda Self:math.pi * SELF.R * SELF.R
Dynamic languages are generally so flexible, and Python is no exception.
The official Python tutorial "9. The first sentence of classes"is:
Compared with other programming languages, Python's class mechanism adds classes with a minimum of new syntax and semantic S.
It's amazing how Python implements the class mechanism with minimal new syntax and semantics, but also makes C + +/Java programmers feel uncomfortable.
Polymorphic
As mentioned earlier, Python does not overwrite (override) the concept. In strict terms, Python does not support polymorphism.
In order to solve the problem of interfaces and implementations in the inheritance structure, or to better interface programming with Python (as advocated by the design pattern), we need to set some specifications artificially.
Please consider Shape.area () in addition to the simple return 0.0, is there a better implementation?
Built-in module Asyncio as an example, Abstracteventloop is in principle an interface, similar to a Java interface or a pure virtual class in C + +, but Python does not have the syntax to guarantee this, in order to embody Abstracteventloop as an interface , first, it is abstract in the name, and then each method throws an exception Notimplementederror.
Class Abstracteventloop: def run_forever (self): raise Notimplementederror ...
Even so, you can't prevent users from instantiating Abstracteventloop:
loop = Asyncio. Abstracteventloop () Try: loop.run_forever () except Notimplementederror: Pass
C + + can be protected by pure virtual functions or constructors to avoid the instantiation of the interface, not to mention Java, interface is interface, there is complete syntax support.
You cannot force a subclass to implement each of the methods defined in the interface, and the pure virtual function of C + + enforces this (not to mention Java).
Even if the subclass "thinks" of implementing the "interface" method, there is no guarantee that the name of the method is not written wrong, C + + 's override keyword can guarantee this (not to mention Java).
The absence of static types makes it difficult for Python to implement a strict polymorphic check mechanism like C + +/Java. Therefore, interface-oriented programming, for Python, more to rely on the quality of the programmer.
Back to the example of Shape, modeled after Asyncio, we changed the "interface" to this:
Class Abstractshape: def area (self): raise Notimplementederror
That way, it's more like an interface.
Super
Sometimes, you need to call a method of the parent class in the child class.
The shape has the color of this property, so add a parameter color to __init__:
Class Abstractshape: def __init__ (self, color): Self.color = Color
Then the subclass of __init__ () is bound to follow the changes:
Class Circle (Abstractshape): def __init__ (self, Color, r=0.0): super (). __init__ (color) SELF.R = R
Pass color to the parent class's __init__ () by Super. In fact, no super is OK:
Class Circle (Abstractshape): def __init__ (self, Color, r=0.0): abstractshape.__init__ (self, color) SELF.R = R
But super is recommended because it avoids hard coding and can handle multiple inheritance situations.