Type hint for return, return None, and no return at all?

Question:

Is there any difference in the return type hint amongst these three functions?

def my_func1():
    print("Hello World")
    return None

def my_func2():
    print("Hello World")
    return

def my_func3():
    print("Hello World")

Should they all have -> None return type hint, since that’s what they in fact return, explicitly or implicitly? Or should my_func2 or my_func3 have literally no return type hint?

Motivations for asking are this question, and this nice answer, and the fact that I’m learning Type Hints.

Asked By: Raf

||

Answers:

They all should have the -> None return type, since they all clearly return None.

Note that there also exists the typing.NoReturn type for functions that actually never return anything, e.g.

from typing import NoReturn

def raise_err() -> NoReturn:
    raise AssertionError("oops an error")

Other types of functions (pointed out by @chepner) that actually never return and thus should be type hinted with -> NoReturn would be for example an event loop that only ends using sys.exit or any of the os.exec* functions

Or should my_func2 or my_func3 have literally no return type hint?

In my opinion, they should always have a type hint, since as @yedpodtrzitko said in their answer, functions with no type hints are by default not type checked by Mypy at all, and their return values are basically treated as if they would’ve been typed to be Any. This greatly reduces the benefits of type checking, and that’s one of the reasons I always use the Mypy setting disallow_untyped_defs = True for new projects.

Answered By: ruohola

if your function don’t have any type hint in its signature, mypy won’t check them at all by default. Consider following:

$ cat foo.py

def foo():
    """this function has no type hint in its signature 
    it won't be checked and the error will be ignored."""
    "foo" + 1
    return None

def bar() -> None:
    """this has type hint in the signature
    it will be checked and error will be reported"""
    "bar" + 1
    return None
$ mypy ./foo.py
foo.py:6: error: Unsupported operand types for + ("str" and "int")
Found 1 error in 1 file (checked 1 source file)
Answered By: yedpodtrzitko