python - 如何键入可变的默认参数
问题描述
在 Python 中处理可变默认参数的方法是将它们设置为 None。
例如:
def foo(bar=None):
bar = [] if bar is None else bar
return sorted(bar)
如果我输入函数定义,那么 for 的唯一类型是bar
什么时候,很明显,它不是我期望在它上面运行该函数的时间:bar
Optional
Optional
sorted
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
?
处理这个问题的最佳方法是什么?
编辑:为了澄清,这个函数的用户应该能够调用foo
asfoo()
和foo(None)
和foo(bar=None)
。(我认为以其他方式拥有它没有意义。)
编辑#2:如果您从不键入as而只键入它, Mypy 将不会出现任何错误,尽管默认值为. 但是,强烈不建议这样做,因为这种行为将来可能会改变,并且它还隐式地将参数键入为. (有关详细信息,请参阅此内容。)bar
Optional
List[int]
None
Optional
解决方案
None
不是唯一可用的哨兵。您可以选择自己的列表值用作标记,None
在运行时将其(而不是 )替换为新的空列表。
_sentinel = []
def foo(bar: List[int]=_sentinel):
bar = [] if bar is _sentinel else bar
return sorted(bar)
只要没有人调用foo
using_sentinel
作为显式参数,bar
总会得到一个新的空列表。在类似的调用foo([])
中,bar is _sentinel
将是错误的:两个空列表不是同一个对象,因为列表的可变性意味着您不能拥有一个始终被 引用的空列表[]
。
推荐阅读
- javascript - Boostrap 4:模态不会显示在我的反应应用程序上
- android - NetworkOnMainThreadException 尽管 RxJava2 subscribeOn(Schedulers.io)
- python - 将 http 重定向到 https flask + appengine
- ios - 如何创建一个跨越多个部分的粘性标题
- sql - 具有多个值的 CASE 语句
- go - base64 decode then json decode: base64.NewDecoder EOF 错误和 json invalid character 错误
- c# - 如何转换 XDocument 只留下选定的路径?
- ios - 以编程方式获取 AVAudioEngineGraph
- python - Python:捕获异常后如何停止执行?
- python - Grahite、Carbon、CollectD、StatsD - Python 程序中的标记系列