'Workaround for TypeVar bound on a TypeVar?
Is there some way of expressing this Scala code with Python's type hints?
trait List[A] {
def ::[B >: A](x: B): List[B]
}
I'm trying to achieve this sort of thing
class X: pass
class Y(X): pass
class Z(X): pass
xs = MyList(X(), X()) # inferred as MyList[X]
ys = MyList(Y(), Y()) # inferred as MyList[Y]
_ = xs.extended_by(X()) # inferred as MyList[X]
_ = xs.extended_by(Y()) # inferred as MyList[X]
_ = ys.extended_by(X()) # inferred as MyList[X]
_ = ys.extended_by(Y()) # inferred as MyList[Y]
_ = ys.extended_by(Z()) # inferred as MyList[X]
Note that the type MyList
is initialised with, and the type it's extended_by
, can be anything. MyList
is immutable. See the comments for more detail.
What I tried
from __future__ import annotations
from typing import TypeVar, Generic
B = TypeVar('B')
A = TypeVar('A', bound=B)
class MyList(Generic[A]):
def __init__(*o: A):
...
def extended_by(self, x: B) -> MyList[B]:
...
but I get (where the above is in main.py)
main.py:5: error: Type variable "main.B" is unbound
main.py:5: note: (Hint: Use "Generic[B]" or "Protocol[B]" base class to bind "B" inside a class)
main.py:5: note: (Hint: Use "B" in function signature to bind "B" inside a function)
Afaict, it's not allowed to bound on a TypeVar
. Is there a workaround in this scenario?
Solution 1:[1]
from __future__ import annotations
from typing import (
TYPE_CHECKING,
Generic,
TypeVar,
)
B = TypeVar('B')
A = TypeVar('A')
class MyList(Generic[A]):
def __init__(*o: A):
...
def extended_by(self, x: B) -> MyList[B]:
...
class Y:
...
class X:
...
ys = MyList(Y(), Y())
xs = ys.extended_by(X())
if TYPE_CHECKING:
reveal_locals()
This produces :
test.py:32: note: Revealed local types are:
test.py:32: note: xs: test.MyList[test.X*]
test.py:32: note: ys: test.MyList[test.Y*]
I didn’t understand the link between A
and B
. Could you give an example with for instance class Y
and X
so I can update my answer?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Cyrille Pontvieux |