Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return None from python function annotated with mypy, multiple return types

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.

like image 689
Corey Cole Avatar asked Sep 10 '18 19:09

Corey Cole


People also ask

Can a Python function have multiple return types?

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.

Can a Python function return None?

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.

Is return and return None the same Python?

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.

How do you stop returning None in Python?

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().


1 Answers

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
like image 88
Corey Cole Avatar answered Sep 17 '22 04:09

Corey Cole