【问题标题】:python - specify type with multiple bases (typing AND operator) [duplicate]python - 指定具有多个基础的类型(键入AND运算符)[重复]
【发布时间】:2020-07-27 14:42:30
【问题描述】:

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

Union[X,Y]

但是如何表达X 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

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

class C(X,Y): pass

C 在设计上也可以在some_function 中工作。我正在寻找一个更好的类型提示来代替 Union[X,Y] 使用,它包括任何可能的子类 XY

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

class XY(X,Y): pass

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

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

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

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

【问题讨论】:

  • 泛型类型是具有一个或多个类型变量的类。我不认为我在谈论泛型类型。
  • 对于未来的读者,我想强调 python 协议完全支持这里的要求,尽管语法有点难看。你可以在这里看到一个例子:peps.python.org/pep-0544/#unions-and-intersections-of-protocols。您基本上可以随意要求混合接口,例如 rust 中的特征或 haskell 中的类型类。这个想法真的很强大,目前的答案并没有真正突出这一点,恕我直言。

标签: python python-typing


【解决方案1】:

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

你可以引入一个mix类,例如:

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())

【讨论】:

  • 有趣! Protocol 非常接近我正在寻找的内容。
猜你喜欢
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
相关资源
最近更新 更多