首页 > 解决方案 > 如何键入可变的默认参数

问题描述

在 Python 中处理可变默认参数的方法是将它们设置为 None

例如:

def foo(bar=None):
    bar = [] if bar is None else bar
    return sorted(bar)

如果我输入函数定义,那么 for 的唯一类型是bar什么时候,很明显,它不是我期望在它上面运行该函数的时间:barOptionalOptionalsorted

def foo(bar: Optional[List[int]]=None):
    bar = [] if bar is None else bar
    return sorted(bar) # bar cannot be `None` here

那我应该投吗?

def foo(bar: Optional[List[int]]=None):
    bar = [] if bar is None else bar
    bar = cast(List[int], bar) # make it explicit that `bar` cannot be `None`
    return sorted(bar)

我是否应该只希望通读该函数的人看到处理默认可变参数的标准模式并理解对于函数的其余部分,参数不应该是Optional

处理这个问题的最佳方法是什么?

编辑:为了澄清,这个函数的用户应该能够调用fooasfoo()foo(None)foo(bar=None)。(我认为以其他方式拥有它没有意义。)

编辑#2:如果您从不键入as而只键入它, Mypy 将不会出现任何错误,尽管默认值为. 但是,强烈不建议这样做,因为这种行为将来可能会改变,并且它还隐式地将参数键入为. (有关详细信息,请参阅内容。)barOptionalList[int]NoneOptional

标签: pythonmutabletypingdefault-arguments

解决方案


None不是唯一可用的哨兵。您可以选择自己的列表值用作标记​​,None在运行时将其(而不是 )替换为新的空列表。

_sentinel = []

def foo(bar: List[int]=_sentinel):
    bar = [] if bar is _sentinel else bar
    return sorted(bar)

只要没有人调用foousing_sentinel作为显式参数,bar总会得到一个新的空列表。在类似的调用foo([])中,bar is _sentinel将是错误的:两个空列表不是同一个对象,因为列表的可变性意味着您不能拥有一个始终被 引用的空列表[]


推荐阅读