Well I'm considering a case where I have a baseclass with (several) children. I have a function that takes a list of baseclass objects, and returns a new list with these objects in it.
Now if I would use a child class obviously the return is a list of those child class objects: consider the following trivial case:
from typing import Sequence, List, TypeVar
class BaseClass:
def __init__(self, data=None, *args, **kwargs):
super().__init__()
self.CanCalculate = True
if data is None:
data = []
self.CanCalculate = False
self._mydata = list(data)
self.multiplier = 1
@property
def data(self):
return self._mydata
class ChildClass(BaseClass):
def sum_mul_data(self):
return self.multiplier * sum(self.data)
class SecondChildClass(BaseClass):
def sum_div_data(self):
return sum(self.data) / self.multiplier
def myFun(input: Sequence[BaseClass]) -> List[BaseClass]:
out = []
for n, i in enumerate(input):
if i.CanCalculate:
i.multiplier = 10**n
out.append(i)
return out
childs = [ChildClass([1,2,3,4]), ChildClass(), ChildClass([1,2,3,4])]
t = myFun(childs)
for idx in t:
print(idx.sum_mul_data())
childs = [SecondChildClass([1,2,3,4]), SecondChildClass(), SecondChildClass([1,2,3,4])]
t = myFun(childs)
for idx in t:
print(idx.sum_div_data())
Legal code: however pycharm (and the standard type hints) shows an error during static code analysis:
"unresolved attribute reference" @ idx.sum_mul_data()
Now apparently this is due to pycharm thinking the return of the function is of type "BaseClass" - not a child. So how would I state: "return same type as input"?
I tried using a typevar: T = TypeVar("T", BaseClass)
, though that gave an actual error, that a single contraint can't be used in TypeVar
. Interestingly using T = TypeVar("T", BaseClass, ChildClass)
did work, and pycharm correctly deduced the type(hint) for sum_div_data.
The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc. This module provides runtime support for type hints. The most fundamental support consists of the types Any , Union , Callable , TypeVar , and Generic .
Introduction to Python type hints It means that you need to declare types of variables, parameters, and return values of a function upfront. The predefined types allow the compilers to check the code before compiling and running the program.
If you indicate (with type hinting) that a variable is going to store a string, but you assign it to a boolean, your code is going to run without any error, because that's how it works in Python, but the code editor is going to yell at me.
Here's how you can add type hints to our function: Add a colon and a data type after each function parameter. Add an arrow ( -> ) and a data type after the function to specify the return data type.
You should use typevars with an upper bound: do T = TypeVar('T', bound=BaseClass)
instead of T = TypeVar('T', BaseClass)
.
Details:
When you do something like T = TypeVar('T', ClassA, ClassB, ClassC...)
, you're creating a type variable with a value restriction. That is, you're insisting that T
must be exactly one of the classes you listed.
This is why doing T = TypeVar('T', ClassA)
is disallowed: the typevar can only be equal to one class, so you might as well just use the ClassA
type directly.
When you do something like T = TypeVar('T', bound=ClassA)
, you're creating a type variable with an upper bound. You're insisting that T
must either be ClassA
, or any of its subclasses.
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