Python Glossary Русский

all Python 3OOPterm

Polymorphism

polymorphism

One interface — different implementations. In Python it comes from overriding methods and from duck typing.

Syntax

for obj in objects:
    obj.method()  # разные реализации

In Python objects need no common ancestor — matching method names are enough (duck typing), so polymorphism works with no inheritance at all. A base class raising NotImplementedError is only a convention; to have a missing method caught when the object is created rather than when it's called, use abc.ABC with @abstractmethod.

Examples

class Shape:
    def area(self):
        raise NotImplementedError
class Circle(Shape):
    def __init__(self, r):
        self.r = r
    def area(self):
        import math
        return math.pi * self.r**2
class Rectangle(Shape):
    def __init__(self, w, h):
        self.w = w; self.h = h
    def area(self):
        return self.w * self.h
shapes = [Circle(3), Rectangle(4,5)]
for s in shapes:
    print(round(s.area(), 2))  # → 28.27 / 20
# Duck typing
class Dog:
    def speak(self):
        return 'Woof!'
class Cat:
    def speak(self):
        return 'Meow!'
class Duck:
    def speak(self):
        return 'Quack!'
for animal in [Dog(), Cat(), Duck()]:
    print(animal.speak())  # → Woof! Meow! Quack!
# Общая функция — полиморфный вызов
def make_sound(animal):
    print(animal.speak())
make_sound(Dog())   # → Woof!
make_sound(Duck())  # → Quack!
# Перегрузка операторов — полиморфизм
class Vector:
    def __init__(self, x):
        self.x = x
    def __add__(self, other):
        return Vector(self.x + other.x)
class Matrix:
    def __init__(self, data):
        self.data = data
    def __add__(self, other):
        return Matrix([[a + b for a, b in zip(r1, r2)]
                       for r1, r2 in zip(self.data, other.data)])
print((Vector(1)+Vector(2)).x)  # → 3
# isinstance + полиморфизм
def describe(obj):
    if isinstance(obj, list):
        return f'list of {len(obj)}'
    elif isinstance(obj, str):
        return f'string: {obj!r}'
    else:
        return f'other: {type(obj).__name__}'
print(describe([1,2,3]))  # → list of 3
print(describe('hi'))     # → string: 'hi'

See also

Open in the full glossarydocs.python.orgReport an inaccuracy