Anotación de tipo Python para el tipo de pato personalizado

El módulo de typing de Python define una serie de tipos de pato, por ejemplo, typing.SupportsAbs . typing.SupportsAbs para representar cualquier tipo que implemente el método especial __abs__ .

¿Es posible definir tipos personalizados de pato de tal manera que pueda usarlos como anotaciones de tipo válidas?

Por ejemplo, me gustaría poder anotar que un argumento debería ser un equivalente tipo pato de un threading.Lock . Es decir, cualquier objeto que implemente métodos de acquire y release . Idealmente, podría anotar un argumento como SupportsAcquireAndRequire o DuckLock , en lugar de un object .

Puede definir una clase base abstracta (ABC) para especificar la interfaz:

 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 

Esto es básicamente cómo se implementan los protocolos (como typing.SupportsAbs ), aunque sin usar directamente ABCMeta .

Al darle al método ABC __subclasshook__ , puede usarlo en las isinstance() y issubclass() , lo cual es más que suficiente para herramientas como mypy :

 >>> from threading import Lock >>> isinstance(Lock(), SupportsAcquireAndRequire) True