Optional type

The docs say that this is the preferred way. See page.

Import

from typing import Optional

Use Optional

Allow a variable to be None:

Optional[TYPE]

Declare a type for a variable. This was recommended by the docs.

foo: Optional[str] = None

foo = 'abc'

Union approach

Use the Union type. This is not preferred but might be needed in some cases.

Union(float, None)

# Python 3.10
float | None

Function examples

Here we return a string or None.

def foo() -> Optional[str]:
    pass

The second case shows a necessary annotation. Note you must declare the type on the first declaration of a variable and on that one only.

def bar(bazz: bool) -> Optional[str]:
    if bazz:
        buzz: Optional[str] = 'Yes'
    else:
        buzz = None
    
    return buzz

You may can an error from Pylint:

E1136: Value 'Optional' is unsubscriptable (unsubscriptable-object)

You can use use Union instead.

def bar(bazz: bool) -> Union[str, None]:
    if bazz:
        buzz: Union[str, None] = 'Yes'
    else:
        buzz = None
    return buzz

Or you have to use Optional like this.

def bar(bazz: bool) -> Union[str, None]:
    if bazz:
        buzz: Optional[str] = 'Yes'
    else:
        buzz = None
    return buzz

Or, you can use a return None sooner and so donโ€™t define buzz at that point so buzz is never None but the function can return None.

Parameters

For function parameters which have defaults, you can avoid using Optional or Union by ensuring the default is not set as None.

e.g.

def foo(fizz, buzz:Optional[float]=None):
    pass
    
def foo(fizz, buzz:float=0.0):
    pass