Python 3 type hinting for None?

PythonPython 3.xNonetypeType Hinting

Python Problem Overview


def foo(
        hello: str='world', bar: str=None,
        another_string_or_None: str|????=None):
    pass

I'm trying to set a type hint in Python in a function, you can add more than one type hint with something: str|bool='default value', but, what are the type hinting for None? :/

Python Solutions


Solution 1 - Python

From your example:

def foo(
        hello: str='world', bar: str=None,
        another_string_or_None: str|????=None):
    ...

I've noticed that your use case is "something or None".

Since version 3.5, Python supports type annotations via typing module. And in your case, the recommended way of annotating is by using typing.Optional[something] hint. This has exact meaning you're looking for.

Therefore the hint for another_string_or_None would be:

import typing

def foo(
        hello: str='world', bar: str=None,
        another_string_or_None: typing.Optional[str]=None):
    ...

Solution 2 - Python

It's just None!

>>> def nothing(nun: None) -> None:
...     return nun
... 
>>> nothing(None)
>>> 

Or at least, it can be.

Since these annotations are meaningless to Python beyond being in/correct syntax, it's sort of up to the tools.

If you use typecheck-decorator for example, then you'll need to use type(None):

>>> import typecheck as tc
>>>
>>> @tc.typecheck
>>> def nothing(nun: type(None)) -> type(None):
...     return nun
... 
>>> nothing(None)
>>> nothing(0)
typecheck.framework.InputParameterError: nothing() has got an incompatible value for nun: 0
>>> nothing(False)
typecheck.framework.InputParameterError: nothing() has got an incompatible value for nun: False

Typecheck also allows you to somewhat more clearly "add more than one type hint with" with tc.any() (OR), tc.all() (AND), and far more besides.

Beware that tc.none() is a NAND-like predicate; not what you are looking for - with no arguments it will accept any type, equivalent to tc.all() or the more apt tc.anything.

Solution 3 - Python

Python 3.10 will support your original desired notation: str | None.

Source

Solution 4 - Python

I know this question is considered answered thanks to @mbdevpl, however, I've wanted to add that type(None) is how you get the actual for None type, this can be useful for example in an if statement check like:

if isinstance(x_var, type(None)):
    pass

and since python3.5, you can also use do Union of a bunch of types with None as shown here:

x_var: typing.Union[str, None]
y_var: typing.Union[Dict, List, None]

this is equivalent to:

x_var: typing.Optional[str]
y_var: typing.Optional[typing.Union[Dict, List]]

Solution 5 - Python

According to PEP-0484: "When used in a type hint, the expression None is considered equivalent to type(None)."

I came around it when using in a type-hint signature for @functools.singledispatch, and annotating an argument with None does work for the function dispatch decorators.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionfj123xView Question on Stackoverflow
Solution 1 - PythonmbdevplView Answer on Stackoverflow
Solution 2 - PythonOJFordView Answer on Stackoverflow
Solution 3 - PythonOddthinkingView Answer on Stackoverflow
Solution 4 - PythonHocine Abdellatif HouariView Answer on Stackoverflow
Solution 5 - Pythonoyd11View Answer on Stackoverflow