polymorphism

Ask almost everyone about the three main features of object orientation: encapsulation, inheritance, and polymorphism. Today we’re going to talk about polymorphism in Python.

Polymorphism means that the same method of a class instance has different manifestations in different situations. The polymorphism mechanism enables objects with different internal structures to share the same external interface. This means that although the specific operations on different objects are different, they (those operations) can be invoked in the same way through a common class.

I described the implementation of policy patterns in detail in Python design Patterns: Policy Patterns, and policy patterns are typical polymorphic applications.

I will not paste the previous code, you can go to the original view. Again, I’ll use the classic example of product discounts. In the policy pattern article, I also implemented the traditional policy pattern in Python code, and in languages such as Java or C#, the implementation is similar. Here is the C# code, I just listed a shelf:

interface Promotion { double discount(Order order); } class FidelityPromo: Promotion // first specific strategy {// Offer 5% discount to customers with credits of 1000 or more (Order Order) {... }} class BulkItemPromo: Promotion // the second specific strategy {// a single item for 20 or more 10% discount public double discount(Order Order) {... }} class LargeOrderPromo: Promotion // the third specific strategy {// the Order of 10 or more different items to provide 7% discount public double discount(Order Order) {... }}Copy the code

As you can see, there is an interface (Promotion), which is then implemented by each policy. However, the Python language does not have the interface keyword, that is, Python does not have an interface like Java or C#.

In the implementation of strategy pattern, Abstract Base Class (ABC) is used to realize the interface, which is mainly for writing looks more like Java, C# and other languages, easy to understand and compare with the students who have the foundation of these languages.

Abstract base classes were introduced in Python 2.6, 15 years after the birth of the Python language. We won’t cover abstract base classes in detail here, because very little code uses abstract base classes even now. For polymorphism, Python has a better implementation — duck typing.

Protocol and duck type

A duck type is a bird that walks like a duck, swims like a duck and quacks like a duck. The concept takes its name from James Whitcomb Riley’s duck test.

To understand duck types, we have to refer to another term — agreement.

In object-oriented programming, a protocol is an informal interface, a set of methods defined only by documents and conventions; therefore, protocols cannot impose the same coercive constraints as formal interfaces. The Philosophy of Python is to support basic protocols as much as possible.

There are no interfaces in Python, so where interfaces are needed, protocols are used instead. A protocol is simply a set of methods, the same as those defined in an interface. Only the agreement is not mandatory agreement, if you don’t abide by the agreement, then it doesn’t matter, just run the wrong.

Just to make sense of duck types, “If a bird walks like a duck, swims like a duck, quacks like a duck” means that agreement has been followed, “then it’s a duck,” which means you can use “this bird” wherever you use “duck.” Isn’t that polymorphism?

Implementing the policy pattern with a “duck type” is also easy, just drop the abstract base class. (This is why abstract base classes are rarely used, because it’s just as good to delete code.) If you are interested, try the code yourself.

Examples of protocols in Python

There are many protocols in Python, such as the iterator protocol. Any object that implements the __iter__ and __next__ methods can be called an iterator, but there is no restriction on what type the object itself can be, thanks to the duck type.

from collections import Iterable
from collections import Iterator


class MyIterator:
    def __iter__(self):
        pass

    def __next__(self):
        pass


print(isinstance(MyIterator(), Iterable)) 
print(isinstance(MyIterator(), Iterator)) 
Copy the code

Output:

True
True
Copy the code

conclusion

Duck types are a design style in dynamically typed languages in which the characteristics of an object are determined not by its superclass but by the object’s methods.

It’s not that Python doesn’t support polymorphism, it’s that Python itself is a polymorphic language.


The Path of Python for older code farmers