可选[…]是Union […,None]的简写符号,告诉类型检查器需要特定类型的对象,或者需要None. …代表任何有效的类型提示,包括复杂的复合类型或更多类型的Union [].每当你有一个默认值为None的关键字参数时,你应该使用Optional.
所以对于你的两个例子,你有dict和list容器类型,但是a关键字参数的默认值表明也允许None,所以使用Optional […]:
from typing import Optional
def test(a: Optional[dict] = None) -> None:
#print(a) ==> {'a': 1234}
#or
#print(a) ==> None
def test(a: Optional[list] = None) -> None:
#print(a) ==> [1, 2, 3, 4, 'a', 'b']
#or
#print(a) ==> None
请注意,在Union []上使用Optional []或在Union []中添加None之间在技术上没有区别.所以可选[Union [str,int]]和Union [str,int,None]是完全相同的.
就个人而言,在设置使用= None来设置默认值的关键字参数的类型时,我总是坚持使用Optional [],这记录了为什么更好地允许None的原因.此外,它可以更容易地将Union […]部分移动到单独的类型别名中,或者如果参数变为必需,则稍后删除Optional […]部分.
例如,假设你有
from typing import Optional, Union
def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
然后通过将Union [str,int]拉出到类型别名来改进文档:
from typing import Optional, Union
# subwidget ids used to be integers, now they are strings. Support both.
SubWidgetId = Union[str, int]
def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
将Union []移动到别名中的重构变得更加容易,因为使用Optional […]而不是Union [str,int,None]. None值毕竟不是’子组件id’,它不是值的一部分,None表示没有值.
附注:您希望避免在类型提示中使用标准库容器类型,因为您无法说明它们必须包含哪些类型;所以不要使用dict和list,而是使用typing.List和typing.Dict.当只从容器类型中读取时,您也可以接受任何不可变的抽象容器类型;列表和元组是Sequence对象,而dict是Mapping类型:
from typing import Mapping, Optional, Sequence, Union
def test(a: Optional[Mapping[str, int]] = None) -> None:
"""accepts an optional map with string keys and integer values"""
# print(a) ==> {'a': 1234}
# or
# print(a) ==> None
def test(a: Optional[List[Union[int, str]]] = None) -> None:
"""accepts an optional sequence of integers and strings
# print(a) ==> [1, 2, 3, 4, 'a', 'b']
# or
# print(a) ==> None