简体   繁体   English

你如何测试一个 python 类型协议是另一个协议的子类?

[英]How can you test that a python typing Protocol is a subclass of another Protocol?

The obvious solution to the problem is to use issubclass , but this raises TypeError (using Python 3.6.7), eg该问题的明显解决方案是使用issubclass ,但这会引发TypeError (使用 Python 3.6.7),例如

>>> from typing_extensions import Protocol
>>> class ProtoSubclass(Protocol):
...     pass
... 
>>> issubclass(ProtoSubclass, Protocol)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/envs/airflow/lib/python3.6/site-packages/typing_extensions.py", line 1265, in __subclasscheck__
    raise TypeError("Instance and class checks can only be used with"
TypeError: Instance and class checks can only be used with @runtime protocols
>>> from typing_extensions import runtime
>>> @runtime
... class ProtoSubclass(Protocol):
...     pass
... 
>>> issubclass(ProtoSubclass, Protocol)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/conda/envs/airflow/lib/python3.6/site-packages/typing_extensions.py", line 1265, in __subclasscheck__
    raise TypeError("Instance and class checks can only be used with"
TypeError: Instance and class checks can only be used with @runtime protocols

For more on the topic of python Protocols , see有关 python Protocols主题的更多信息,请参见

In Python 3.6.7, one way to solve this is to use the @runtime_checkable decorator:在 Python 3.6.7 中,解决此问题的一种方法是使用@runtime_checkable装饰器:

>>> from typing_extensions import Protocol
>>> from typing_extensions import runtime_checkable

>>> @runtime_checkable
... class CustomProtocol(Protocol):
...     def custom(self):
...         ...
... 

>>> @runtime_checkable
... class ExtendedCustomProtocol(CustomProtocol, Protocol):
...     def extended(self):
...         ...
... 

>>> issubclass(ExtendedCustomProtocol, CustomProtocol)
True

The selected answer, although not wrong, doesn't reflect the actual use of Protocol , which is providing structural subtyping.所选答案虽然没有错,但并未反映Protocol的实际使用,它提供了结构子类型。 Nominal subtyping was always available to Python 3.名义子类型始终可用于 Python 3。

from typing import Protocol, runtime_checkable

@runtime_checkable
class Closable(Protocol):
    def close(self):
        ...

class AnyClass:
    def close(self):
        ...

issubclass(AnyClass, Closable)
#> True

Also, runtime_checkable is only needed in the base class, even if the class being checked is a Protocol subclass.此外,仅在基类中需要runtime_checkable ,即使被检查的类是Protocol子类。

class ExtendedProtocol(Closable, Protocol):
    ...

class AnotherProtocol(Protocol):
    def close(self):
        ...

class NotAProtocol(Closable):
    # just inherits the protocol's default implementation
    ...

issubclass(ExtendedProtocol, Closable)
#> True
issubclass(AnotherProtocol, Closable)
#> True
issubclass(NotAProtocol, Closable)
#> True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM