T_co = TypeVar("T_co", covariant=True)
class Indexable(Protocol[T_co]): def __getitem__(self, i: int) -> T_co: ...
def f(x: Indexable[str]) -> None: print(x[0])
I am failing to format it proprely here, but you get the idea.
T_co = TypeVar("T_co", covariant=True)
class Indexable(Protocol[T_co]): def __getitem__(self, i: int) -> T_co: ...
def f(x: Indexable[str]) -> None: print(x[0])
I am failing to format it proprely here, but you get the idea.
> Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.)
If you'd want monospace you should indent the snippet with two or more spaces:
from typing import Protocol, TypeVar
T_co = TypeVar("T_co", covariant=True)
class Indexable(Protocol[T_co]):
def __getitem__(self, i: int) -> T_co: ...
def f(x: Indexable[str]) -> None:
print(x[0])Generally it’s not worth trying to fix this stuff. The type signature is hell to write and ends up being super complex if you get it to work at all. Write a cast or Any, document why it’s probably ok in a comment, and move on with your life. Pick your battles.
Sequence[SupportsFloat] | Mapping[int,SupportsFloat]
Whether or not you explicitly write out the type, I find that functions with this sort of signature often end up with code that checks the type of the arguments at runtime anyway. This is expensive and kind of pointless. Beware of bogus polymorphism. You might as well write two functions a lot of the time. In fact, the type system may be gently prodding you to ask yourself just what you think you’re up to here.This is really just the same mistake as the original expanding union, but with overly narrow abstract types instead of overly narrow concrete types. If it relies on “we can use indexing with an int and get out something whose type we don’t care about”, then its a Protocol with the following method:
def __getitem__(self, i: int, /) -> Any: ...
More generally, even if there is a specific output type when indexing, or the output type of indexing can vary but in a way that impacts the output or other input types of the function, it is a protocol with a type parameter T and this method: def __getitem__(self, i: int, /) -> T: ...
It doesn’t need to be union of all possible concrete and/or abstract types that happen to satisfy that protocol, because it can be expressed succinctly and accurately in a single Protocol.So, just:
class Indexable[T](Protocol):
def __getitem__(self, i: int,/) -> T: ...
is enough.