Python的typing
模块定义了许多鸭子类型(duck typing),例如typing.SupportsAbs
来表示实现__abs__
特殊方法的任何类型。
是否可以通过某种方式定义自定义鸭子类型(duck typing),以便可以将它们用作有效的类型注释?
例如,我希望能够注释一个参数应该是threading.Lock
的鸭子类型(duck typing)等效项,即,任何实现acquire
和release
方法的对象。理想情况下,我可以注释诸如SupportsAcquireAndRequire
或DuckLock
这样的参数,而不是object
。
最佳答案
您可以定义一个abstract base class (ABC)来指定接口(interface):
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
基本上,这是协议(protocol)(如
typing.SupportsAbs
)的实现方式,尽管不直接使用ABCMeta
。通过给ABC一个
__subclasshook__
method,您可以在isinstance()
和issubclass()
测试中使用它,对于 mypy
这样的工具来说已经足够了:>>> from threading import Lock
>>> isinstance(Lock(), SupportsAcquireAndRequire)
True