I'm using mypy
and the typing
module in python. Imagine I have a generic type:
ContainerT = TypeVar('ContainerT')
class Thingy(Generic[ContainerT]):
pass
However I want to get at another type inside the concrete type associated with the TypeVar like in the example below:
class SomeContainer(object):
Iterator = SomeCustomIterator
ContainerT = TypeVar('ContainerT')
class Thingy(Generic[ContainerT]):
def foo(self) -> ContainerT.Iterator:
pass
I get an error saying that TypeVar
does not have a member Iterator
. Is there another way to reformulate this so I can associate one type with another?
Thank you.
Maybe you are thinking about something like this.
from __future__ import annotations
from abc import abstractmethod
from typing import Generic, TypeVar, Iterator, Protocol
_Iterator = TypeVar('_Iterator', bound=Iterator, covariant=True)
class SomeContainer:
iterator: Iterator[int]
def __init__(self, iterator: Iterator[int]):
self.iterator = iterator
def get_iterator(self) -> Iterator[int]:
return self.iterator
class SomeContainerProtocol(Protocol[_Iterator]):
@abstractmethod
def __init__(self, iterator: _Iterator):
pass
@abstractmethod
def get_iterator(self) -> _Iterator:
pass
_SomeContainer = TypeVar('_SomeContainer', bound='SomeContainerProtocol', covariant=True)
class Thingy(Generic[_SomeContainer]):
container: _SomeContainer
def __init__(self, container: _SomeContainer):
self.container = container
def foo(self: Thingy[SomeContainerProtocol[_Iterator]]) -> _Iterator:
pass
def bar(self) -> _SomeContainer:
pass
thingy = Thingy(SomeContainer(range(10).__iter__()))
reveal_type(thingy) # Revealed type is '...Thingy[...SomeContainer*]'
reveal_type(thingy.foo) # Revealed type is 'def () -> typing.Iterator[builtins.int]'
reveal_type(thingy.bar) # Revealed type is 'def () -> ...SomeContainer*'
You can annotate self with a generic protocol (available starting Python 3.8) in place of your type var and mypy will then infer the type of the iterator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With