【问题标题】:Combine explicit keyword arguments and **kwargs结合显式关键字参数和 **kwargs
【发布时间】:2020-01-30 20:01:10
【问题描述】:

在 Python 中,我可以显式列出函数接受的仅限关键字的参数:

def foo(arg, *, option_a=False, option_b=False):
    return another_fn(arg, option_a=option_a, option_b=option_b)

虽然调用另一个函数的语法有点冗长,但我确实在函数调用中对命名参数进行了很好的自动完成:

我可以通过使用**kwargs来消除函数调用中的冗余:

def foo(arg, **kwargs):
    return another_fn(arg, **kargs)

但后来我失去了编辑器中的自动完成功能(并且函数签名不太清晰):

我怎样才能两全其美?我想写一个显式的函数签名,但仍然在函数体中得到一个kwargs dict。

【问题讨论】:

  • 当您想要传递给函数的关键字参数的数量是任意数量时,最好使用**kwargs。在您的情况下,您只有两个关键字参数要传递。因此,请使用option_a=False, option_b=True,在这种情况下更清楚。
  • @Ch3steR 假设我有十个关键字参数,需要将它们全部传递给另一个采用相同关键字参数的函数。您可以看到样板如何在没有 **kwargs 的情况下扩展。

标签: python python-3.x keyword-argument


【解决方案1】:

这是locals()的可能使用场景:

def foo(arg, arg2=None):
    return another_fn(**locals())

如果需要,也可以解压self

class bar:
    def foo(self, arg):
        kwargs = locals()
        kwargs.pop('self')
        return another_fn(**kwargs)

警告:如果您在调用 locals() 之前在方法中定义了任何局部变量,它们最终会出现在输出中,您必须将它们过滤掉。

def foo(self, arg=None):
    baz = 'Oops'
    kwargs = locals() # {'self': <bar at 0x0000>, 'arg': None, 'baz': 'Oops'}
    return another_fn(**kwargs)

简单的解决方案是在执行任何其他操作之前调用locals(),为安全起见复制一份,并记住在实例方法中清理self

class bar:
    def foo(self, arg=None):
        kwargs = locals().copy() # {'self': <bar at 0x0000>, 'arg': None}
        kwargs.pop('self')
        baz = 'Oops'
        return another_fn(**kwargs)

希望这会有所帮助!

【讨论】:

  • locals() 非常挑剔,远远超过乍一看。例如,它在调试器中的行为不同。它在函数中的行为也不同于在类或模块范围内的行为,它与推导有惊人的交互,它与super() 有一种奇怪的交互,它通常包括闭包变量,除了在一个特殊情况下涉及访问闭包变量一个类体。
  • 使用locals().copy() 总是立即复制dict 可以避免一些但不是全部的问题。特别是,通过这种方式应该可以避免与调试器的不良交互。但是,我仍然不建议使用locals()
  • 在 OP 的问题中,这些边缘情况不适用。任何能给 OP 提供他们想要的解决方案的东西都会变得很挑剔,因为它会涉及到一定程度的内省。根据他们的需求(例如他们的foo() 的上下文是什么),他们可能会更好地使用不需要显式创建这些包装器方法的方法。
  • 调试器交互几乎与任何代码相关,这甚至不是奇怪交互的完整列表。
猜你喜欢
  • 2015-09-02
  • 2016-11-12
  • 1970-01-01
  • 2015-09-20
  • 2022-12-01
  • 1970-01-01
  • 2023-04-06
  • 2012-12-09
  • 2014-09-07
相关资源
最近更新 更多