python - 我应该如何使用 Optional 类型提示?

标签 python python-3.x type-hinting python-typing

我正在尝试了解如何使用 Optional 类型提示。来自 PEP-484 ,我知道我可以将 Optional 用于 def test(a: int = None) 或者作为 def test(a: Union[int, None])def test(a: Optional[int])

但是下面的例子怎么样?

def test(a : dict = None):
    #print(a) ==> {'a': 1234}
    #or
    #print(a) ==> None

def test(a : list = None):
    #print(a) ==> [1,2,3,4, 'a', 'b']
    #or
    #print(a) ==> None

如果 Optional[type] 似乎与 Union[type, None] 意思相同,我为什么要使用 Optional[]有没有?

最佳答案

Optional[...]Union[..., None] 的简写符号,告诉类型检查器特定类型的对象是必需, 是必需的。 ... 代表任何有效的类型提示,包括复杂的复合类型或更多类型的 Union[]。每当您有默认值为 None 的关键字参数时,您应该使用 Optional。 (注意:如果您的目标是 Python 3.10 或更高版本,PEP 604 引入了更好的语法,请参见下文)。

因此对于您的两个示例,您有 dictlist 容器类型,但是 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[] 或仅将 None 添加到 Union 在技术上没有区别[]。所以 Optional[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 值毕竟不是“subwidget id”,它不是值的一部分,None 是为了标记值的缺失。

旁注:除非您的代码只需要支持 Python 3.9 或更新版本,否则您希望避免在类型提示中使用标准库容器类型,因为您无法说明它们必须包含哪些类型。因此,不要使用 dictlist,而是分别使用 typing.Dicttyping.List。当仅读取容器类型时,您也可以接受任何不可变的抽象容器类型;列表和元组是 Sequence 对象,而 dictMapping 类型:

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[Sequence[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

在 Python 3.9 及更高版本中,标准容器类型已全部更新以支持在类型提示中使用它们,请参阅 PEP 585 . 但是,虽然您现在可以使用dict[str, int]list[Union[int, str]],您仍然可能希望使用更具表现力的 MappingSequence 注释来指示函数不会改变内容(它们被视为“只读” ),并且这些函数可以与分别用作映射或序列的任何对象一起使用。

Python 3.10 将 | 联合运算符引入到类型提示中,参见 PEP 604 .你可以写 str | 而不是 Union[str, int]整数。与其他类型提示语言一致,在 Python 3.10 及更高版本中表示可选参数的首选(且更简洁)方式现在是 Type |无,例如海峡 |无列表 |无

关于python - 我应该如何使用 Optional 类型提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51710037/

相关文章:

Python 元编程 : generate a function signature with type annotation

python获取列表的前x个元素并删除它们

python - 测试和模拟使用 async with 语句的异步代码

python - 类型提示中的可选联合

python - map、lambda 和 append.. 为什么不起作用?

python - 我需要使用 kubernetes python 客户端获取 Kubernetes 集群中 Pod 的资源使用情况

python - 关闭 'Python version 3.5 does not support variable annotations' 错误信息

python - pd.read_json() 到 pandas 中的数据框

python - 如何处理 Shapely 中的舍入错误

python - 更改满足 DataFrame 条件的行上的列值