使用 typing 模块和 mypy 的多重继承
Multiple inheritance using typing module and mypy
考虑以下代码:
from typing import Union
class A:
def function_in_a(self) -> str:
return 'a'
class B:
def function_in_b(self) -> str:
return "b"
class C(A, B):
pass
def call_functions(c: Union[A, B]) -> None:
print(c.function_in_a())
print(c.function_in_b())
if __name__=="__main__":
c = C()
call_functions(c)
请注意,函数 call_functions
依赖于 类 A
和 B
中包含的定义。它期望从这两个 类.
继承的对象
此代码将在 运行 使用 python test.py
时编译。但是 mypy --strict test.py
抛出一个错误:
test.py:15: note: Revealed type is "Union[test.A, test.B]"
test.py:16: error: Item "B" of "Union[A, B]" has no attribute "function_in_a"
test.py:17: error: Item "A" of "Union[A, B]" has no attribute "function_in_b"
Found 2 errors in 1 file (checked 1 source file)
这对我来说很有意义。 Union
表示 c
可以是 A
或 B
的子类,但 不能同时是 。我在 PEP483 but a quick perusal of the typing
module docs 中看到 Intersection
类型的提及表明这种类型从未实现过。
如何让 mypy
识别 call_functions
的参数是继承自 both A and[=39 的对象=] B 使用类型提示?
使用 typing.Protocol
定义必须实现函数中调用的两种方法的类型。
from typing import Protocol
class A:
def function_in_a(self) -> str:
return 'a'
class B:
def function_in_b(self) -> str:
return "b"
class C(A, B):
pass
class D(B):
pass
class ProtoAB(Protocol):
def function_in_a(self) -> str:
...
def function_in_b(self) -> str:
...
def call_functions(obj: ProtoAB) -> None:
print(obj.function_in_a())
print(obj.function_in_b())
def main() -> None:
c = C()
call_functions(c)
d = D()
call_functions(d)
if __name__ == "__main__":
main()
另一个解决方案是使A
和B
Protocol
。协议可以正常使用 class:
from typing import Protocol
class A(Protocol):
def function_in_a(self) -> str:
return 'a'
class B(Protocol):
def function_in_b(self) -> str:
return "b"
class AB(A, B, Protocol):
pass
def call_functions(c: AB) -> None:
print(c.function_in_a())
print(c.function_in_b())
class C(A, B):
pass
call_functions(C())
考虑以下代码:
from typing import Union
class A:
def function_in_a(self) -> str:
return 'a'
class B:
def function_in_b(self) -> str:
return "b"
class C(A, B):
pass
def call_functions(c: Union[A, B]) -> None:
print(c.function_in_a())
print(c.function_in_b())
if __name__=="__main__":
c = C()
call_functions(c)
请注意,函数 call_functions
依赖于 类 A
和 B
中包含的定义。它期望从这两个 类.
此代码将在 运行 使用 python test.py
时编译。但是 mypy --strict test.py
抛出一个错误:
test.py:15: note: Revealed type is "Union[test.A, test.B]"
test.py:16: error: Item "B" of "Union[A, B]" has no attribute "function_in_a"
test.py:17: error: Item "A" of "Union[A, B]" has no attribute "function_in_b"
Found 2 errors in 1 file (checked 1 source file)
这对我来说很有意义。 Union
表示 c
可以是 A
或 B
的子类,但 不能同时是 。我在 PEP483 but a quick perusal of the typing
module docs 中看到 Intersection
类型的提及表明这种类型从未实现过。
如何让 mypy
识别 call_functions
的参数是继承自 both A and[=39 的对象=] B 使用类型提示?
使用 typing.Protocol
定义必须实现函数中调用的两种方法的类型。
from typing import Protocol
class A:
def function_in_a(self) -> str:
return 'a'
class B:
def function_in_b(self) -> str:
return "b"
class C(A, B):
pass
class D(B):
pass
class ProtoAB(Protocol):
def function_in_a(self) -> str:
...
def function_in_b(self) -> str:
...
def call_functions(obj: ProtoAB) -> None:
print(obj.function_in_a())
print(obj.function_in_b())
def main() -> None:
c = C()
call_functions(c)
d = D()
call_functions(d)
if __name__ == "__main__":
main()
另一个解决方案是使A
和B
Protocol
。协议可以正常使用 class:
from typing import Protocol
class A(Protocol):
def function_in_a(self) -> str:
return 'a'
class B(Protocol):
def function_in_b(self) -> str:
return "b"
class AB(A, B, Protocol):
pass
def call_functions(c: AB) -> None:
print(c.function_in_a())
print(c.function_in_b())
class C(A, B):
pass
call_functions(C())