ChatGPT解决这个技术问题 Extra ChatGPT

使用类型提示时如何向函数添加默认参数?

如果我有这样的功能:

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

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

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

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

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

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

编辑:我不知道默认参数在 Python 中是如何工作的,但为了这个问题,我将保留上面的示例。一般来说,最好执行以下操作:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass
最后一个函数是正确的方法。 scala 语言也是如此。
你有一个可变的默认类型——这会导致问题
@noɥʇʎԀʎzɐɹƆ 除非您将其用于记忆,否则不会。 :P

n
noɥʇʎԀʎzɐɹƆ

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

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

print(foo.__annotations__)

这输出

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

确实,它没有在 PEP 484 中列出,但类型提示是函数注释的应用,在 PEP 3107 中有记录。The syntax section 清楚地表明关键字参数以这种方式与函数注释一起使用。

我强烈建议不要使用可变关键字参数。更多信息here


请参阅legacy.python.org/dev/peps/pep-3107/#syntax。类型提示只是函数注释的一种应用。
哇,我不知道 Python 中的可变默认参数……尤其是来自 Javascript/Ruby,其中默认参数的工作方式不同。不会重复已经说过的关于它的恶心,我很高兴我在它咬我之前发现了这一点。谢谢!
我总是被建议使用 None 而不是像 {} 或 [] 这样的可变类型或默认对象,因为没有深拷贝的该对象的突变将在迭代之间持续存在。
用可变的关键字参数定义足够多的函数,你会发现自己回顾 4 小时的调试会议来质疑你的生活选择只是时间问题
dict = {} 中的 = 周围不应该没有空格,就像它是非类型提示关键字参数的约定一样?
T
Tomasz Bartkowiak

如果您使用 typing(在 Python 3.5 中引入),则可以使用 typing.Optional,其中 Optional[X] 等同于 Union[X, None]。它用于表示允许 None 的显式值。从 typing.Optional

def foo(arg: Optional[int] = None) -> None:
    ...

Optional[int] = None 中的 = 周围不应该没有空格,就像它是非类型提示关键字参数的约定一样?
@actual_panda 答案是正确的。当有类型提示时,样式会有所不同。 PEP 484 中有示例
K
Kirkalicious

我最近看到了这个单行:

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

嗨@Kirkalicious,感谢您的回答。你能解释一下它是如何工作的吗?
作为默认参数传递的空字典对于每个调用都是相同的字典。因此,如果函数对其进行了变异,那么下一次的默认值将是上次的变异值。将 None 设为默认值,然后在方法内部进行检查,通过在每次调用该方法时分配一个新的 dict 来避免此问题。
您可以update your answer没有“编辑:”、“更新:”或类似内容)吗?评论可能随时消失。
opts = opts or {}怎么样
一个问题——如果 opts 是一个可变参数,调用者希望在其中查看修改后的值,则传入 {} 时它将失败。坚持使用传统的双线可能更安全if opts is None: opts = {}。如果您需要单线,我更喜欢 opts = {} if opts is None else opts