Python的typing模块定义了许多鸭子类型,例如,typing.SupportsAbs来表示实现__abs__特殊方法的任何类型。
是否有可能以这样的方式定义自定义鸭子类型,以便我可以将它们用作有效的类型注释?
例如,我希望能够注释一个参数应该是一个鸭子类型的等价的threading.Lock,即实现acquire和release方法的任何对象。理想情况下,我可以将这样的论点注释为SupportsAcquireAndRequire或DuckLock,而不是object。
发布于 2016-11-07 21:30:07
您可以定义一个抽象基类(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一个方法,您可以在isinstance()和issubclass()测试中使用它,这对于mypy这样的工具来说已经足够了。
>>> from threading import Lock
>>> isinstance(Lock(), SupportsAcquireAndRequire)
True发布于 2020-04-16 18:01:54
typing已经更新以支持像这样的用例,您可以为此使用typing.Protocol。
from typing import Protocol, runtime_checkable
@runtime_checkable
class LockLike(Protocol):
def acquire(self) -> None:
...
def release(self) -> None:
...如果您希望能够像Martijn的答案那样使用isinstance,则需要使用isinstance。
>>> from threading import Lock
>>> isinstance(Lock(), RuntimeCheckable)
Truehttps://stackoverflow.com/questions/40474537
复制相似问题