jac*_*118 20 python type-hinting python-3.x
我试图了解如何使用Optional类型提示.从PEP 434,我知道我可以使用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
Run Code Online (Sandbox Code Playgroud)
Optional[type]似乎意味着同样的事情Union[type, None],我为什么要使用它Optional[]?
Mar*_*ers 29
Optional[...]是一种简写符号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
Run Code Online (Sandbox Code Playgroud)
请注意,在使用Optional[]a Union[]或仅添加None到技术上没有区别Union[].所以Optional[Union[str, int]],Union[str, int, None]完全是一回事.
就个人而言,我总是坚持使用Optional[]设置用于= None设置默认值的关键字参数的类型,这记录了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.
"""
Run Code Online (Sandbox Code Playgroud)
然后通过拉出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.
"""
Run Code Online (Sandbox Code Playgroud)
移动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[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
Run Code Online (Sandbox Code Playgroud)
Mic*_*ura 15
请注意,从 Python 3.10 开始,您可以简化代码并键入:
def foo(
bar: int | None = None,
another_bar: Callable[[int, list, float, datetime | None], str],
):
Run Code Online (Sandbox Code Playgroud)
Tro*_*roy 14
虽然接受的答案是正确的答案,但需要注意的另一件事是,在 的上下文中kwargs, 和Optional[...]都是Union[..., None]多余且不必要的。如果您立即将 kwarg 设置为None,那么 IDEmypy和 IDE 都会假定显而易见的情况并自动将 arg 视为Optional[...]。
集成开发环境:
我的:
然而,对于变量和方法/函数返回值,Optional[...]仍然是必要的,因为mypy在这些情况下无法知道自动假设任何内容。
kev*_*und 12
直接来自mypy 输入模块文档。