自定义鸭子类型(duck typing)的 Python 类型注释

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

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

是否可以以某种方式定义自定义鸭子类型(duck typing),以便我可以将它们用作有效的类型注释?

例如,我希望能够注释一个参数应该是 threading.Lock 的鸭子类型(duck typing)等效项,即任何实现 acquire 的对象> 和 release 方法。理想情况下,我可以将这样的参数注释为 SupportsAcquireAndRequireDuckLock,而不是 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

关于自定义鸭子类型(duck typing)的 Python 类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40474537/

相关文章:

python - Pandas:根据行中的多个条件向 DF 添加带有随机数的新列

python - Typehint 方法作为 python 中其他方法的返回类型?

python - 将 PATCH 与 Django 图像字段和 s3 一起使用

Python,将线程与多处理一起使用

python - 在 SQLite 数据库中输入大量条目

python-3.x - 如何编写一个函数,在不使用 return 的情况下更改原始整数列表?

python - Skimage 多边形函数 : Why does the last vertice repeats in the polygon documentation example?

python - 如何键入具有封闭类类型的提示方法?

php - 在接口(interface)中实现类型提示 'parent' 会引发错误

python - 如何在使用append()时避免for循环