python - 指定具有多个基数的类型(键入 AND 运算符)

python - specify type with multiple bases (typing AND operator)

我理解(如 and the docs) 中所述,X Y 的类型提示可以表示为:

Union[X,Y]

但是如何表达XY的类型提示呢?这在表示所讨论的对象必须是 XY.

的子 class 时很有用

只要预先知道继承 XY 的所有 classes,下面的示例就可以工作:

class X: pass
class Y: pass
class A(X,Y): pass
class B(X,Y): pass

def some_function(arg: Union[A,B]): 
    pass
    # do stuff with arg that only depends on inherited members from X and Y

但是如果依赖于上述代码的另一个包定义了怎么办:

class C(X,Y): pass

C 也将按设计在 some_function 中工作。我正在寻找一个更好的类型提示来代替 Union[X,Y],它包括任何可能的 class,sub-class 是 XY

我知道解决方法是定义:

class XY(X,Y): pass

然后将其用作基础 class 并键入提示:

class A(XY): pass
class B(XY): pass
class C(XY): pass
def some_function(arg: XY): pass

但我不确定是否值得为类型提示定义一个新的 class,它无论如何都不会影响运行时。

我们如何为 class 创建类型提示,它是 X [=17= 的子class ]?

Python type-hints 不支持显式 intersection 注释。但是你至少有两个解决方法:

您可以引入 mix class,例如:

class A:
    def foo_a(self):
        pass

class B:
    def foo_b(self):
        pass
    

class Mix(A, B):
    pass


def foo(p: Mix) -> None:
    p.foo_a()
    p.foo_b()

或使用结构子类型,Protocol,例如:

from typing import Protocol

class Supports_ab(Protocol):
    def a(self):
        pass
    
    def b(self):
        pass

class A:
    def a(self):
        pass

class B:
    def b(self):
        pass

class Derived(A, B):
    pass

    
class SomeClassAB:  # no need superclass
    def a(self):
        pass
    
    def b(self):
        pass
    
def foo(p: Supports_ab) -> None:
    p.a()
    p.b()

foo(SomeClassAB())
foo(Derived())