TypeVar绑定到另一个TypeVar

时间:2019-08-21 10:57:06

标签: python types type-bounds typehints

是否有某种方法可以使用python的类型提示来表达此Scala代码?

trait List[A] {
  def ::[B >: A](x: B): List[B]  # I got the `>` the wrong way round first time
}

我尝试过……

from typing import TypeVar, Generic

A = TypeVar('A')
B = TypeVar('B', bound=A)


# also got A and B the wrong way round first time :D
class MyList(Generic[B]):
    def __init__(*o: B):
        ...

    def extended_by(x: A) -> MyList[A]:
        ...

但是我得到了(上面是在main.py中)

  

main.py:4:错误:类型“ main.A”无效

Afaict,不允许绑定到TypeVar。在这种情况下有解决方法吗?

我正在尝试实现这种目标...

class X: pass
class Y(X): pass

ys = MyList(Y(), Y())  # inferred as MyList[Y], I know how to do this
xs = ys.extended_by(X())  # inferred as MyList[X], I don't know how to do this

1 个答案:

答案 0 :(得分:0)

我不太了解Scala,但我认为您只是在指定子类型关系。 Python typing doesn't allow type variables to be used as bounds,说:

  

上限不能与类型约束结合使用(如使用的AnyStr,请参见前面的示例);类型约束导致推断的类型完全是约束类型之一,而上限仅要求实际类型是边界类型的子类型。

也就是说,您可以使用covariantcontravariant参数来获得一些控制权:

from typing import TypeVar, Generic, List

A = TypeVar('A', contravariant=True)

class MyList(Generic[A]):
    objs: List[A]

    def __init__(self, objs: List[A]):
        self.objs = objs

    def extend(self, x: A) -> "MyList[A]":
        return MyList([x] + self.objs)

class X: pass
class Y(X): pass

l = MyList([X(), X()])
l.extend(Y())

类型检查,同时添加:

class Z: pass
l.extend(Z())

失败