bounds with typyvar

Question:

I want to make sure that the input is the same as output, I tried to use TypeVar to bound the typing but I can’t get it to work…

from typing import TypeVar, Union, Any
import pandas as pd

class my_Class():
    def __init__(self):
        self.days = []
        self.count = 0

    def __call__(self, 
                 input: Union[dict, list[dict]], 
                 *args, 
                 **kwargs
                 ) -> Union[dict, list[dict]]:
        "some code"

what I tried:

from typing import TypeVar, Union, Any
import pandas as pd

T = TypeVar("T", bound=Union[dict, list[dict]])

class my_Class():
    def __init__(self):
        self.days = []
        self.count = 0
    def __call__(self, input: T, *args, **kwargs) -> T:
        "some code"

It’s saying that it’s expecting "T" and got either Dict or List but I thought since I bounded it, it will look into that Union that I defined in T? Can someone direct me to what I’m doing wrong here?

Asked By: shaftel

||

Answers:

You need a constrained type variable, not a bound type variable, in order to require that the same type be bound to T in both cases.

from typing import TypeVar

T = TypeVar('T', pd.DataFrame, dict, list[dict])

class MyClass:
    def __init__(self):
        self.days = []
        self.count = 0

    def __call__(self, input: T, *args, **kwargs) -> T:
        ...

With a union bound, both the argument and the return type are restricted to one of the three given types, but each use of T can be bound independently of the other. Further, you have no idea, statically speaking, which of the three will be returned. With a constrained type variable, the same type has to be bound to T in every occurrence within a single call to __call__.


Here’s a simple example:

from typing import Generic, TypeVar

T = TypeVar('T', int, str)

class Foo:
    def __call__(self, x: T) -> T:
        return x

x: int = Foo()(9)  # OK, 9 makes return value int
y: str = Foo()("foo")  # OK, "foo" makes return value str
z: float = Foo()(3.14)  # Fails, 3.14 not an int or str
w: str = Foo()(9)  # Fails, can' assign an int to w
Answered By: chepner

The problem may be that you’re using list instead List, as well dict instead of Dict; try importing them from typing.

from typing import TypeVar, Union, Any, Dict, List
import pandas as pd

T = TypeVar("T", bound=Union[pd.DataFrame, Dict[Any, Any], List[Dict[Any, Any]]])

class my_Class():
    def __init__(self):
        self.days = []
        self.count = 0
    def __call__(self, input: T, *args, **kwargs) -> T:
        "some code"
Answered By: Luca Anzalone
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.