当前位置: 首页 > 面试题库 >

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

羊舌兴文
2023-03-14
问题内容

我试图了解如何使用Optional类型提示。从PEP-484,我知道我可以使用Optionaldef 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],它告诉类型检查器特定类型的对象是必需的 还是
None必需的。...代表 任何有效的类型提示
,包括复杂的复合类型或Union[]更多类型。只要您有带有默认值的关键字参数None,就应该使用Optional

因此,对于您的两个示例,您有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

请注意,在技术上是使用没有任何区别Optional[]Union[],或者只是添加NoneUnion[]。所以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.

    """

然后通过将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毕竟,该值不是“ subwidget id”,也不是该值的一部分,None它旨在标记不存在值。

旁注:除非您的代码仅需要支持Python
3.9或更高版本,否则您要避免在类型提示中使用标准库容器类型,因为您无法说明它们必须包含哪些类型。因此,分别使用和代替dict和。当仅从容器类型
读取 时,您也可以接受任何不可变的抽象容器类型。列表和元组对象,同时是一个类型:list``typing.Dict``typing.List
__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

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



 类似资料:
  • 问题内容: 我正在尝试决定要选择哪种mime类型来返回mp3数据(由php提供) 根据此mime类型列表:http : //www.webmaster-toolkit.com/mime-types.shtml 这些之间有什么区别,我应该使用哪个? 问题答案: 最好的选择是使用RFC定义的 mime-type 。

  • 问题内容: 我正在为电子商务应用程序设计数据库/域,但很难弄清楚如何存储产品。 该网站将出售各种各样的产品,笔,丁字裤,纹身,雨伞等等。这些产品中的每一个将共享一些共同的属性,例如高度,宽度,长度,重量等,但是某些产品具有特殊的数据。例如,钢笔具有不同的墨水颜色,笔尖/笔盖和小册子可以具有不同类型的折痕。到目前为止,我已经考虑了20多个额外的属性,但是这些属性可能仅适用于网站上1%的产品。 因此,

  • 主要内容:1.强制解包,2.自动解包,3.Optional绑定Swift 4还引入了类型,它处理缺少值。 简单的解释是:“有一个值,它等于x”或“根本没有值”。 一个本身就是一种类型,实际上是Swift 4的新超级枚举之一。 它有两个可能的值,和,其中是Swift 4中可用的正确数据类型的关联值。 这是一个的整数声明 - 下面是一个的声明 - 通过以下示例来了解如何在Swift 4中工作 - 当使用playground运行上述程序时,得到以下结果 - 类似于

  • 问题内容: 假设我有一个函数: 如何为可以指定的东西指定返回类型? 问题答案: 您正在寻找。 由于您的返回类型可以是(从返回),也应该使用: 在有关打字的文档中,是以下内容的简写: 等价于。 其中表示类型或的值。 如果由于担心别人可能偶然发现而没有意识到它的含义而希望变得露骨,则可以始终使用: 但是我怀疑这是一个好主意,是一个指示性名称,它确实节省了几次击键。 正如@ Michael0x2a的注释

  • 问题内容: 我不太清楚当我这样说时会做什么: 我可以稍微了解使用它的原因,因为它不浏览整个数据库表以更新字段,而是仅更新新添加的记录。如我错了请纠正我。 所以我想做的是使用这样创建索引: 一旦执行此操作,文档就根本不会上传到索引。我要去哪里错了? 任何帮助,不胜感激。 问题答案: 如果您的表中有一个时间戳列(例如),则最好使用它代替ID号。这样,当记录更新时,您也可以修改该时间戳,输入插件将提取记

  • 问题内容: 在Objective- C中,我调用该方法来记录异常。如何在Swift中调用它? 问题答案: 使用Swift 2,您可以将Swift函数和闭包作为C函数指针传递 原始答案 从Xcode 6 beta 6开始,您不能这样做。 Swift确实支持传递函数指针,但是它们几乎就像不透明指针一样被对待。您既不能定义指向Swift函数的C函数指针,也不能在Swift中调用C函数指针。 这意味着您从