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

jos*_*osh 169 python type-hinting python-3.x

如果我有这样的功能:

def foo(name, opts={}):
  pass
Run Code Online (Sandbox Code Playgroud)

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

def foo(name: str, opts={}: dict) -> str:
  pass
Run Code Online (Sandbox Code Playgroud)

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

def foo(name: str, opts: dict={}) -> str:
  pass
Run Code Online (Sandbox Code Playgroud)

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

编辑:我不知道默认参数在Python中如何工作,但为了这个问题,我将保留上面的例子.一般来说,做以下事情要好得多:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass
Run Code Online (Sandbox Code Playgroud)

noɥ*_*ɐɹƆ 198

你的第二种方式是正确的.

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

print(foo.__annotations__)
Run Code Online (Sandbox Code Playgroud)

这个输出

{'opts': <class 'dict'>}
Run Code Online (Sandbox Code Playgroud)

确实,它没有在PEP 484中列出,但类型提示是函数注释的应用程序,在PEP 3107中有记录.语法部分清楚地表明关键字参数以这种方式与函数注释一起工作.

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

  • 始终建议我使用None而不是使用诸如{}或[]之类的可变类型或默认对象,因为在不进行深度复制的情况下,对该对象的突变将在迭代之间持续存在。 (5认同)
  • 使用可变关键字参数定义足够多的函数,您会发现自己回顾 4 小时的调试会话质疑您的生活选择只是时间问题 (3认同)
  • 像非类型提示关键字参数的约定一样,“dict = {}”中的“=”周围不应该有空格吗? (3认同)
  • @actual_panda 不符合 [PEP 8](https://peps.python.org/pep-0008/#other-recommendations:~:text=when%20combining%20an%20argument%20annotation%20with%20a%20default%20value %2C%20然而%2C%20do%20use%20spaces%20around%20the%20%3D%20sign%3A),至少。 (3认同)
  • 请参阅http://legacy.python.org/dev/peps/pep-3107/#syntax。类型提示只是函数注释的一种应用。 (2认同)
  • 哇,我不知道Python中的可变默认参数...特别是来自Javascript/Ruby,默认参数的工作方式不同.不会重新讨论那些已经说过的关于它的恶作剧,我很高兴我在发现它之前发现了这一点.谢谢! (2认同)

小智 17

我最近看到了这个单行:

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

  • 作为默认参数传递的空字典对于每次调用都是相同的字典。因此,如果函数对其进行了变异,那么下一次的默认值将是上次变异的值。将 `None` 设为默认值,然后在方法内部进行检查,通过在每次调用该方法时分配一个新的 dict 来避免这个问题。 (9认同)
  • 与此相关的一个问题 - 如果 *opts* 是一个可变参数,调用者希望在其中看到修改后的值,那么当传入 `{}` 时它将失败。坚持使用传统的两行 `if opts 可能更安全无:opts = {}`。如果您需要一行,我更喜欢“opts = {} if opts is None else opts”。 (8认同)
  • `opts = opts 或 {}` 怎么样? (5认同)
  • 您可以[更新您的答案](https://stackoverflow.com/posts/56467744/edit)(***没有***“编辑:”、“更新:”或类似内容)吗?评论可能随时消失。 (2认同)

Tom*_*iak 9

If you're using typing (introduced in Python 3.5) you can use typing.Optional, where Optional[X] is equivalent to Union[X, None]. It is used to signal that the explicit value of None is allowed . From typing.Optional:

def foo(arg: Optional[int] = None) -> None:
    ...
Run Code Online (Sandbox Code Playgroud)

  • @actual_panda 答案是正确的。当有类型提示时,风格会有所不同。[PEP 484](https://www.python.org/dev/peps/pep-0484/)中有示例 (6认同)
  • 或新语法中的 `def foo(arg: int | None = None) -&gt; None:` (4认同)
  • “Optional[int] = None”中的“=”周围不应该有空格吗?就像非类型提示关键字参数的约定一样? (3认同)