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

Mat*_*oth 11 python python-typing

我理解(如这个问题文档中所解释的)X or 的类型提示Y可以表示为:

Union[X,Y]
Run Code Online (Sandbox Code Playgroud)

但是如何表达X and Y的类型提示呢?当表达相关对象必须是 和 的子类时,这将很有XY

只要所有继承这两者XY事先已知的类,以下示例就可以工作:

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
Run Code Online (Sandbox Code Playgroud)

但是如果另一个依赖于上面代码的包定义了:

class C(X,Y): pass
Run Code Online (Sandbox Code Playgroud)

Csome_function也将按设计工作。我正在寻找更好的类型提示来使用,而不是Union[X,Y]包含任何可能的子类XY

我理解解决方法可能是定义:

class XY(X,Y): pass
Run Code Online (Sandbox Code Playgroud)

然后将其用作基类和类型提示:

class A(XY): pass
class B(XY): pass
class C(XY): pass
def some_function(arg: XY): pass
Run Code Online (Sandbox Code Playgroud)

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

我们如何为作为 和 的子类的任何类创建类型X 提示 Y

ale*_*ame 11

Python 类型提示不支持显式交集注释。但你至少有两个解决方法:

您可以引入混合类,例如:

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()
Run Code Online (Sandbox Code Playgroud)

或者使用结构子类型,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())
Run Code Online (Sandbox Code Playgroud)