Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗pyOpPtSv 143 of 174 menu
◀ ▶

Несколько протоколов в ООП в Python

В Python класс может подходить сразу под несколько протоколов. Для этого не нужно перечислять протоколы в объявлении класса - достаточно иметь все нужные методы.

В этом протоколы похожи на интерфейсы PHP: можно описать несколько контрактов, а класс соберет методы из всех. Наследовать несколько абстрактных классов нельзя, а методы нескольких протоколов - можно.

Давайте попробуем на практике. Пусть есть протокол фигуры и протокол четырехугольника с геттерами сторон:

from typing import Protocol, runtime_checkable @runtime_checkable class FigureProto(Protocol): def get_square(self) -> float: ... def get_perimeter(self) -> float: ... @runtime_checkable class TetragonProto(Protocol): def get_a(self) -> float: ... def get_b(self) -> float: ... def get_c(self) -> float: ... def get_d(self) -> float: ...

Класс Quadrate реализует оба контракта одним набором методов. Протоколы в скобках класса писать не обязательно:

class Quadrate: def __init__(self, a): self.__a = a def get_a(self): return self.__a def get_b(self): return self.__a def get_c(self): return self.__a def get_d(self): return self.__a def get_square(self): return self.__a * self.__a def get_perimeter(self): return 4 * self.__a

Проверим соответствие каждому протоколу отдельно через isinstance:

quad = Quadrate(5) print(isinstance(quad, FigureProto)) # True print(isinstance(quad, TetragonProto)) # True

Однако, не имеет значения, квадрат это или трапеция - важно, что фигура имеет описанные методы и работает однотипно.

Тот же прием для User с именем и возрастом: два протокола, один класс:

@runtime_checkable class HasName(Protocol): def name(self) -> str: ... @runtime_checkable class HasAge(Protocol): def age(self) -> int: ... class User: def __init__(self, name, age): self.__name = name self.__age = age def name(self): return self.__name def age(self): return self.__age

Проверим оба протокола:

user = User('john', 25) print(isinstance(user, HasName)) # True print(isinstance(user, HasAge)) # True

Сделайте класс Rectangle, подходящий под FigureProto и TetragonProto.

Сделайте протокол CircleProto с методами get_radius и get_diameter.

Сделайте класс Disk с методами FigureProto и CircleProto. Проверьте isinstance для каждого протокола.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить