在Python中使用类型提示添加默认参数值


235

如果我有这样的功能:

def foo(name, opts={}):
  pass

我想在参数中添加类型提示,该怎么办?我假设的方式给了我一个语法错误:

def foo(name: str, opts={}: dict) -> str:
  pass

以下内容不会引发语法错误,但似乎不是处理这种情况的直观方法:

def foo(name: str, opts: dict={}) -> str:
  pass

我在typing文档或Google搜索中找不到任何内容。

编辑:我不知道默认参数如何在Python中工作,但出于这个问题,我将保留上面的示例。通常,最好执行以下操作:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass

4
最后一个功能是正确的方法。这是同样的方式scala语言做这一点。
以色列Unterman '16

14
你有一个可变的默认类型-这将导致问题
noɥʇʎԀʎzɐɹƆ

看到我更新的答案,@josh
noɥʇʎԀʎzɐɹƆ

@noɥʇʎԀʎzɐɹƆ除非您将其用于备忘录,否则不要这么做。:P
Mateen Ulhaq,

Answers:


280

您的第二种方法是正确的。

def foo(opts: dict = {}):
    pass

print(foo.__annotations__)

这个输出

{'opts': <class 'dict'>}

的确没有在PEP 484中列出它,但是类型提示是函数注释的一种应用,在PEP 3107中进行了记录。语法部分明确指出,关键字参数以这种方式与函数注释一起使用。

我强烈建议您不要使用可变的关键字参数。更多信息在这里


1
参见legacy.python.org/dev/peps/pep-3107/#syntax。类型提示只是功能注释的一种应用。
chepner '16

@chepner是。不知道PEP 3107与关键字参数有关。
noɥʇʎԀʎzɐɹƆ

2
哇,我不知道Python中可变的默认参数...特别是来自Javascript / Ruby的默认参数以不同的方式工作。不想重新谈论围绕它的恶作剧,我很高兴我在被我咬伤之前就知道了这一点。谢谢!
2013年

6
始终建议我使用None而不是使用诸如{}或[]之类的可变类型或默认对象,因为在不进行深度复制的情况下对该对象的突变将在两次迭代之间持续存在。
MrMesees '18 -10-25

2
用可变的关键字参数定义足够的函数,这只是时间问题,您会发现自己回头进行了4个小时的调试会议,质疑您的生活选择
Joseph Sheedy


7

我最近看到了这种单线:

def foo(name: str, opts: dict=None) -> str:
    opts = {} if not opts else opts
    pass

嗨,@ Kirkalicious,谢谢您的回答。您能解释一下它是如何工作的吗?
弥敦道

1
作为默认参数传递的空字典对于每个调用都是相同的字典。因此,如果函数对其进行了更改,则默认的下一次时间将是上一次的值。制作None默认,然后检查里面的方法,每个方法被调用时分配一个新的字典避免了这个问题。
伊恩·高德比
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.