自定义duck类型的Python类型注释

时间:2016-11-07 21:01:53

标签: python python-3.x type-hinting duck-typing

Python的typing模块定义了许多duck类型,例如typing.SupportsAbs来表示实现__abs__特殊方法的任何类型。

是否可以以某种方式定义自定义鸭类型,以便将其用作有效的类型注释?

例如,我希望能够注释参数应该是threading.Lock的鸭类型等价物,即实现acquirerelease方法的任何对象。理想情况下,我可以注释SupportsAcquireAndRequireDuckLock这样的论证,而不是object

2 个答案:

答案 0 :(得分:6)

您可以定义abstract base class (ABC)来指定界面:

for segment in segments:
#calc_function returns a DataFrame that has the same structure as consolidated_df
    consolidated_df.loc[idx[segment, :, :], :] = calc_function(segment)

这基本上是协议(如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

通过向ABC提供__subclasshook__ method,您可以在ABCMetaisinstance()测试中使用它,这对于像mypy这样的工具来说已经足够了:

issubclass()

答案 1 :(得分:1)

typing已更新为支持这样的用例-您可以为此使用typing.Protocol

from typing import Protocol, runtime_checkable

@runtime_checkable
class LockLike(Protocol):
    def acquire(self) -> None:
        ...

    def release(self) -> None:
        ...

如您想使用isinstance一样,您需要@runtimecheckable,就像Martijn的回答一样。

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