<p>从python3.8开始,<a href="https://www.python.org/dev/peps/pep-0544/" rel="nofollow noreferrer">PEP 544 Protocols: Structural subtyping (static duck typing)</a>添加了对<a href="https://en.wikipedia.org/wiki/Structural_type_system" rel="nofollow noreferrer">structural subtyping</a>的支持。对于3.8之前的版本,相应的实现由PyPI上的<a href="https://pypi.org/project/typing-extensions/" rel="nofollow noreferrer">typing-extensions</a>包提供。在</p>
<p>与所讨论的场景相关的是<a href="https://docs.python.org/3.8/library/typing.html#typing.Protocol" rel="nofollow noreferrer">^{<cd1>}</a>,正如PEP <a href="https://www.python.org/dev/peps/pep-0544/#defining-a-protocol" rel="nofollow noreferrer">in more detail</a>所解释的那样。这允许定义<a href="https://www.python.org/dev/peps/pep-0544/#terminology" rel="nofollow noreferrer">implicit subtypes</a>,因为不需要继承,所以可以避免元类冲突问题。代码如下:</p>
<pre><code>from typing import Protocol # Python 3.8+
from typing_extensions import Protocol # Python 3.5 - 3.7
class Fooish(Protocol):
x : int
def foo(self) -> int:
raise NotImplementedError
# No inheritance required, implementing the defined protocol implicitly subtypes 'Fooish'.
class Foo:
def __init__(self, x: int):
self.x = x
def foo(self):
pass
class MyMeta(type):
pass
class Bar(metaclass=MyMeta):
def bar(self):
pass
# Here, we again create an implicit subtype of 'Fooish'.
class FooBar(Bar):
"""Objects of this type are bar and they are foo-ish."""
@property
def x(self) -> int:
return 0
@x.setter
def x(self, val):
pass
def foo(self):
pass
class Worker:
def __init__(self, obj: Fooish):
self.x = obj.x
</code></pre>