Python class, inheritance, and polymorphism

Source: Internet
Author: User
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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.