您如何测试 python 类型协议是另一个协议的子类?
How can you test that a python typing Protocol is a subclass of another Protocol?
问题的明显解决方案是使用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
有关 python Protocols
主题的更多信息,请参阅
在 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
所选答案虽然没有错,但并未反映 Protocol
的实际用途,后者提供结构子类型化。 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
此外,runtime_checkable
仅在基础 class 中需要,即使被检查的 class 是 Protocol
subclass.
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
问题的明显解决方案是使用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
有关 python Protocols
主题的更多信息,请参阅
在 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
所选答案虽然没有错,但并未反映 Protocol
的实际用途,后者提供结构子类型化。 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
此外,runtime_checkable
仅在基础 class 中需要,即使被检查的 class 是 Protocol
subclass.
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