I come from a Typescript background. I'm bringing static type checking into a python project I'm working on (using mypy).
In Typescript, it is valid to return null from a function that is annotated to return something else, i.e. a string:
function test(flag: boolean): string {
if(flag) {
return 'success';
} else {
return null;
}
}
It is also valid to annotate your function to have multiple potential return types, i.e. string or boolean:
function test(flag: boolean): string | boolean {
if(flag) {
return 'success';
} else {
return false;
}
}
But, in python using mypy, I'm disallowed from returning None from a function that is annotated to return str
.
def test(flag: bool) -> str:
if flag:
return 'success'
else:
return None
# [mypy] error:Incompatible return value type (got "None", expected "str")
Furthermore, I don't see a way to annotate multiple return types, i.e. str | None
.
How should I approach something like this using mypy? Functions that return None from the error state are all over my codebase.
Python functions can return multiple values. These values can be stored in variables directly. A function is not restricted to return a variable, it can return zero, one, two or more values.
If we get to the end of any function and we have not explicitly executed any return statement, Python automatically returns the value None. Some functions exists purely to perform actions rather than to calculate and return a result. Such functions are called procedures.
In Python, every function returns something. If there are no return statements, then it returns None. If the return statement contains an expression, it's evaluated first and then the value is returned.
It might seem unexpected, but it is not. The thing is, in Python, every function has a return value. Therefore, if you do not explicitly return anything, None will get returned by default. In the above code, we are printing the return value of test().
Okay, I found what I was missing in the documentation thanks to @zsol on the mypy gitter!
Two helpful mypy features are the Optional and Union types that can be imported from python's typing module. Documentation here.
If you want to annotate that the function can potentially return None in addition to the primary type, e.g. str
, use Optional
:
from typing import Optional
def test(flag: bool) -> Optional[str]:
if flag:
return 'success'
else:
return None
If you want to annotate that the function can potentially return multiple types, e.g. str | bool
, use Union
:
from typing import Union
def test(flag: bool) -> Union[str, bool]:
if flag:
return 'success'
else:
return False
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