首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么要在python中使用**kwargs?与使用命名参数相比,现实世界中有哪些优势?

为什么要在python中使用**kwargs?与使用命名参数相比,现实世界中有哪些优势?
EN

Stack Overflow用户
提问于 2009-09-12 18:38:01
回答 8查看 28.4K关注 0票数 79

我有静态语言的背景。有人能解释一下(最好是通过示例)使用**kwargs而不是命名参数的实际优势吗?

对我来说,这只会让函数调用变得更加模糊。谢谢。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-09-12 18:50:27

真实世界的例子:

装饰符-它们通常是通用的,所以你不能预先指定参数:

代码语言:javascript
复制
def decorator(old):
    def new(*args, **kwargs):
        # ...
        return old(*args, **kwargs)
    return new

你想用未知数量的关键字参数施展魔法的地方。Django的ORM做到了这一点,例如:

代码语言:javascript
复制
Model.objects.filter(foo__lt = 4, bar__iexact = 'bar')
票数 40
EN

Stack Overflow用户

发布于 2009-09-12 18:52:09

出于一系列原因,您可能希望接受近乎任意的命名参数--这正是**kw表单允许您做的事情。

最常见的原因是将参数直接传递给要包装的其他函数(装饰器是这种情况的一个例子,但不是唯一的一个!) --在这种情况下,**kw松开了包装器和包装器之间的耦合,因为包装器不必知道或关心包装器的所有参数。这是另一个完全不同的原因:

代码语言:javascript
复制
d = dict(a=1, b=2, c=3, d=4)

如果所有的名字都必须事先知道,那么这种方法显然不可能存在,对吧?顺便说一句,在适用的情况下,我更喜欢这种以文字字符串为关键字的字典制作方式:

代码语言:javascript
复制
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

原因很简单,因为后者的标点符号很多,因此可读性较差。

当接受**kwargs的最佳理由都不适用时,不要接受它:就这么简单。如果没有充分的理由允许调用者传递具有任意名称的额外命名参数,请不要允许这种情况发生--只要避免在def语句中将**kw表单放在函数签名的末尾即可。

至于在调用中使用**kw,它允许您将必须传递的命名参数的确切集合放在一个字典中,每个参数都有相应的值,独立于单个调用点,然后在单个调用点使用该字典。比较:

代码语言:javascript
复制
if x: kw['x'] = x
if y: kw['y'] = y
f(**kw)

至:

代码语言:javascript
复制
if x:
  if y:
    f(x=x, y=y)
  else:
    f(x=x)
else:
  if y:
    f(y=y)
  else:
    f()

即使只有两种可能性(而且是最简单的一种!),**kw的缺乏已经使第二种选择变得完全站不住脚和无法容忍--想象一下当有六种可能性时,它会如何发展,可能是在稍微丰富的交互中……没有**kw,在这种情况下,生活将是绝对的地狱!

票数 70
EN

Stack Overflow用户

发布于 2009-09-12 19:15:33

您可能希望使用**kwargs (和*args)的另一个原因是,如果您在子类中扩展现有方法。您希望将所有现有参数传递给超类的方法,但又希望确保即使签名在将来的版本中发生更改,您的类也能继续工作:

代码语言:javascript
复制
class MySubclass(Superclass):
    def __init__(self, *args, **kwargs):
        self.myvalue = kwargs.pop('myvalue', None)
        super(MySubclass, self).__init__(*args, **kwargs)
票数 44
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1415812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档