如何使用类型提示指定“可空”返回类型

问题:如何使用类型提示指定“可空”返回类型

假设我有一个函数:

def get_some_date(some_argument: int=None) -> %datetime_or_None%:
    if some_argument is not None and some_argument == 1:
        return datetime.utcnow()
    else:
        return None

如何为可以指定的东西指定返回类型None

Suppose I have a function:

def get_some_date(some_argument: int=None) -> %datetime_or_None%:
    if some_argument is not None and some_argument == 1:
        return datetime.utcnow()
    else:
        return None

How do I specify the return type for something that can be None?


回答 0

您正在寻找Optional

由于您的返回类型可以是datetime(从返回datetime.utcnow()),None也应该使用Optional[datetime]

from typing import Optional

def get_some_date(some_argument: int=None) -> Optional[datetime]:
    # as defined

在有关打字的文档中,Optional是以下内容的简写:

Optional[X]等同于Union[X, None]

其中Union[X, Y]表示类型X或的值Y


如果由于担心其他人可能偶然发现Optional而没有意识到它的含义而希望变得明确,则可以始终使用Union

from typing import Union

def get_some_date(some_argument: int=None) -> Union[datetime, None]:

但是我怀疑这是一个好主意,Optional是一个指示性名称,并且确实节省了几次击键。

正如@ Michael0x2a的注释中指出的那样,Union[T, None]已转换为,Union[T, type(None)]因此无需在type此处使用。

在视觉上,这两种方法可能有所不同,但在编程上,结果是完全相同的Union[datetime.datetime, NoneType]将是存储在get_some_date.__annotations__*中的类型:

>>> from typing import get_type_hints
>>> print(get_type_hints(get_some_date))
{'return': typing.Union[datetime.datetime, NoneType],
 'some_argument': typing.Union[int, NoneType]}

*typing.get_type_hints抢的对象的__annotations__直接访问它的属性来代替。

You’re looking for Optional.

Since your return type can either be datetime (as returned from datetime.utcnow()) or None you should use Optional[datetime]:

from typing import Optional

def get_some_date(some_argument: int=None) -> Optional[datetime]:
    # as defined

From the documentation on typing, Optional is shorthand for:

Optional[X] is equivalent to Union[X, None].

where Union[X, Y] means a value of type X or Y.


If you want to be explicit due to concerns that others might stumble on Optional and not realize it’s meaning, you could always use Union:

from typing import Union

def get_some_date(some_argument: int=None) -> Union[datetime, None]:

But I doubt this is a good idea, Optional is an indicative name and it does save a couple of keystrokes.

As pointed out in the comments by @Michael0x2a Union[T, None] is tranformed to Union[T, type(None)] so no need to use type here.

Visually these might differ but programatically, in both cases, the result is exactly the same; Union[datetime.datetime, NoneType] will be the type stored in get_some_date.__annotations__*:

>>> from typing import get_type_hints
>>> print(get_type_hints(get_some_date))
{'return': typing.Union[datetime.datetime, NoneType],
 'some_argument': typing.Union[int, NoneType]}

*Use typing.get_type_hints to grab the objects’ __annotations__ attribute instead of accessing it directly.