Python void return type annotation
Question:
In python 3.x, it is common to use return type annotation of a function, such as:
def foo() -> str:
return "bar"
What is the correct annotation for the "void" type?
I’m considering 3 options:
def foo() -> None:
- not logical IMO, because
None
is not a type,
def foo() -> type(None):
- using the best syntax I know for obtaining
NoneType
,
def foo():
- omit explicit return type information.
Option 2. seems the most logical to me, but I’ve already seen some instances of 1.
Answers:
This is straight from PEP 484 — Type Hints documentation:
When used in a type hint, the expression None
is considered equivalent to type(None)
.
And, as you can see most of the examples use None
as return type.
TLDR: The idiomatic equivalent of a void
return type annotation is -> None
.
def foo() -> None:
...
This matches that a function without return
or just a bare return
evaluates to None
.
def void_func(): # unannotated void function
pass
print(void_func()) # None
Omitting the return type does not mean that there is no return value. As per PEP 484:
For a checked function, the default annotation for arguments and for the return type is Any
.
This means the value is considered dynamically typed and statically supports any operation. That is practically the opposite meaning of void
.
Type-hinting in Python does not strictly require actual types. For example, annotations may use strings of type names: Union[str, int]
, Union[str, 'int']
, 'Union[str, int]'
and various variants are equivalent.
Similarly, the type annotation None
is considered to mean "is of NoneType
". This can be used in other situations as well as return types, though you will see it most often as a return-type annotation:
bar : None
def foo(baz: None) -> None:
return None
This also applies to generic types. For example, you can use None
in Generator[int, None, None]
to indicate a generator does not take or return values.
Even though PEP 484 suggests that None
means type(None)
, you should not use the latter form explicitly. The type-hinting specification does not include any form of type(...)
. This is technically a runtime expression, and its support is entirely up to the type checker. The mypy project is considering whether to remove support for type(None)
and remove it from 484 as well.
Or maybe we should update PEP 484 to not suggest that type(None)
is valid as a type, and None
is the only correct spelling? There should one — and preferably only one — obvious way to do it etc.
In python 3.x, it is common to use return type annotation of a function, such as:
def foo() -> str:
return "bar"
What is the correct annotation for the "void" type?
I’m considering 3 options:
def foo() -> None:
- not logical IMO, because
None
is not a type,
- not logical IMO, because
def foo() -> type(None):
- using the best syntax I know for obtaining
NoneType
,
- using the best syntax I know for obtaining
def foo():
- omit explicit return type information.
Option 2. seems the most logical to me, but I’ve already seen some instances of 1.
This is straight from PEP 484 — Type Hints documentation:
When used in a type hint, the expression
None
is considered equivalent totype(None)
.
And, as you can see most of the examples use None
as return type.
TLDR: The idiomatic equivalent of a void
return type annotation is -> None
.
def foo() -> None:
...
This matches that a function without return
or just a bare return
evaluates to None
.
def void_func(): # unannotated void function
pass
print(void_func()) # None
Omitting the return type does not mean that there is no return value. As per PEP 484:
For a checked function, the default annotation for arguments and for the return type is
Any
.
This means the value is considered dynamically typed and statically supports any operation. That is practically the opposite meaning of void
.
Type-hinting in Python does not strictly require actual types. For example, annotations may use strings of type names: Union[str, int]
, Union[str, 'int']
, 'Union[str, int]'
and various variants are equivalent.
Similarly, the type annotation None
is considered to mean "is of NoneType
". This can be used in other situations as well as return types, though you will see it most often as a return-type annotation:
bar : None
def foo(baz: None) -> None:
return None
This also applies to generic types. For example, you can use None
in Generator[int, None, None]
to indicate a generator does not take or return values.
Even though PEP 484 suggests that None
means type(None)
, you should not use the latter form explicitly. The type-hinting specification does not include any form of type(...)
. This is technically a runtime expression, and its support is entirely up to the type checker. The mypy project is considering whether to remove support for type(None)
and remove it from 484 as well.
Or maybe we should update PEP 484 to not suggest that
type(None)
is valid as a type, andNone
is the only correct spelling? There should one — and preferably only one — obvious way to do it etc.