Аннотация типа Python для пользовательского типа утки
Питона typing
модуль определяет количество типов утки, например, typing.SupportsAbs
представлять любой тип, который реализует __abs__
особый метод.
Можно ли определить пользовательские типы утки таким образом, чтобы я мог использовать их в качестве допустимых аннотаций типов?
Например, я хотел бы иметь возможность комментировать, что аргумент должен быть эквивалентом утиного типа threading.Lock
любой объект, реализующий acquire
а также release
методы. В идеале я мог бы прокомментировать такой аргумент, как SupportsAcquireAndRequire
или же DuckLock
, скорее, чем object
,
1 ответ
Вы можете определить абстрактный базовый класс (ABC), чтобы указать интерфейс:
from abc import ABCMeta, abstractmethod
class SupportsAcquireAndRequire(metaclass=ABCMeta):
@abstractmethod
def acquire(self):
pass
@abstractmethod
def release(self):
pass
@classmethod
def __subclasshook__(cls, C):
for method in ('release', 'acquire'):
for B in C.__mro__:
if method in B.__dict__:
if B.__dict__[method] is None:
return NotImplemented
break
else:
return NotImplemented
return True
Это в основном, как протоколы (как typing.SupportsAbs
), хотя и без непосредственного использования ABCMeta
,
Давая ABC __subclasshook__
метод, вы можете использовать его в isinstance()
а также issubclass()
тесты, что более чем достаточно для таких инструментов, как mypy
:
>>> from threading import Lock
>>> isinstance(Lock(), SupportsAcquireAndRequire)
True
typing
обновлен для поддержки таких случаев использования, как этот - вы можете использовать typing.Protocol
для этого.
from typing import Protocol, runtime_checkable
@runtime_checkable
class LockLike(Protocol):
def acquire(self) -> None:
...
def release(self) -> None:
...
Тебе нужно @runtimecheckable
если вы хотите иметь возможность использовать isinstance
как в ответе Мартейн.
>>> from threading import Lock
>>> isinstance(Lock(), RuntimeCheckable)
True