I know what I am asking is rather niche, but it has been bugging me for quite a while. Suppose I have the following function:
def foo(return_more: bool):
....
if return_more:
return data, more_data
return data
You can imagine it is a function that may return more data if given a flag.
How should I typehint this function? When I use the function in both ways
data = foo(False)
data, more_data = foo(True)
either the first or the 2nd statement would say that the function cannot be assigned due to wrong size of return tuple.
Is having variable signature an anti-pattern? Is Python’s typehinting mechanism not powerful enough and thus I am forced to ignore this error?
Edit:
Thanks for all the suggestions.
I was enlightened by this suggestion about the existence of overload
and this solution fit my requirements perfectly
from typing import overload, Literal
@overload
def foo(return_more: Literal[False]) -> Data: ...
@overload
def foo(return_more: Literal[True]) -> tuple[Data, OtherData]: ...
def foo(return_more: bool) -> Data | tuple[Data, OtherData]:
....
if return_more:
return data, more_data
return data
a = foo(False)
a,b = foo(True)
a,b = foo(False) # correctly identified as illegal
def foo(return_more: bool) -> Union[Type1, tuple[Type2,Type3]]:
Python >= 3.10 version:
def foo(return_more: bool) -> DataType | tuple[DataType, MoreDataType]: ...
But i would definitely avoid to do that if possible. I would maybe do something like this instead:
def foo(return_more: bool) -> tuple[DataType, MoreDataType | None]: ... if return_more: return data, more_data return data, None
Or if
data
is adict
, just update it withmore_data
:def foo(return_more: bool) -> dict[str, Any]: ... if return_more: return data.update(more_data) return data
You can also consider the new union that was introduced with Python 3.10, check PEP604 for details:
def foo(return_more: bool) -> Type1 | tuple[Type2,Type3]: