sho*_*yer 3 python duck-typing type-hinting python-3.x
Python的typing模块定义了许多duck类型,例如,typing.SupportsAbs表示实现__abs__特殊方法的任何类型.
是否可以以某种方式定义自定义鸭类型,以便我可以将它们用作有效的类型注释?
例如,我希望能够注释一个参数应该是一个鸭子类型的等价物threading.Lock,即任何实现acquire和release方法的对象.理想情况下,我可以注释这样的论点,SupportsAcquireAndRequire或者DuckLock而不是object.
typing已更新以支持像这样的用例 - 您可以用于typing.Protocol此目的。
from typing import Protocol, runtime_checkable
@runtime_checkable
class LockLike(Protocol):
def acquire(self) -> None:
...
def release(self) -> None:
...
Run Code Online (Sandbox Code Playgroud)
@runtimecheckable如果您希望能够使用isinstanceMartijn 的答案,则需要。
>>> from threading import Lock
>>> isinstance(Lock(), RuntimeCheckable)
True
Run Code Online (Sandbox Code Playgroud)
您可以定义一个抽象基类(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
Run Code Online (Sandbox Code Playgroud)
这基本上是协议(如typing.SupportsAbs)的实现方式,尽管没有直接使用ABCMeta.
通过给ABC一个__subclasshook__方法,你可以使用它isinstance()和issubclass()测试,这对于像以下工具来说已经足够好了mypy:
>>> from threading import Lock
>>> isinstance(Lock(), SupportsAcquireAndRequire)
True
Run Code Online (Sandbox Code Playgroud)