【问题标题】:Unpacking keyword arguments, but only the ones that match the function解包关键字参数,但仅限与函数匹配的参数
【发布时间】:2012-06-16 17:04:29
【问题描述】:

假设我有一个函数:

def foo(a=None, b=None, c=None):
  return "a:%s, b:%s, c:%s" % (a, b, c)

我有一个字典,其中包含一些(或没有)上述参数,但也包含函数中未命名参数的键,例如:

d = {'a': 1, 'x': 4, 'b': 2, 'y': 5}

如果我调用以下命令,我会得到一个错误,因为 'x' 和 'y' 不是 foo 函数中的关键字参数。

foo(**d)  # error

是否有一种优雅的方式将参数从字典传递给函数,但只有那些键与函数参数匹配的值。

如果我的参数/参数术语不正确,请纠正我。

【问题讨论】:

    标签: python


    【解决方案1】:

    @Ashwini Chaudhary 有一种非常 Pythonic 的方式来解决您的问题。但是,它需要更改 foo 函数的签名。

    如果您不想更改函数签名,可以使用introspection 找出您的函数期望的参数:

    arg_count = foo.func_code.co_argcount
    args = foo.func_code.co_varnames[:arg_count]
    
    args_dict = {}
    for k, v in d.iteritems():
        if k in args:
            args_dict[k] = v
    
    foo(**args_dict)
    

    【讨论】:

      【解决方案2】:

      有趣的问题。我认为现实生活中的大多数人都使用@Ashwini Chaudhary 方法。

      我同意@Rodrigue 的观点,有时您不能修改函数的调用签名(可能是其他人的模块)。

      发生这种情况时,使用函数装饰器

      from inspect import getargspec
      from funtools import wraps
      
      def allow_kwargs(foo):
          argspec = getargspec(foo)
          # if the original allows kwargs then do nothing
          if  argspec.keywords:
              return foo
          @wraps(foo)
          def newfoo(*args, **kwargs):
              #print "newfoo called with args=%r kwargs=%r"%(args,kwargs)
              some_args = dict((k,kwargs[k]) for k in argspec.args if k in kwargs) 
              return foo(*args, **some_args)
          return newfoo
      
      
      # with your function:
      @allow_kwargs
      def foo(a = None, b=None, c=None):
        return "a:%s, b:%s, c:%s " % (a,b,c)
      
      # with someone_elses function:
      from some_place import foo
      foo = allow_kwargs(foo)
      

      来自 functools 的@wraps 保持__name__ 和__doc__ 字符串完好无损。您还可以:

      • 查看装饰器模块中的FunctionMaker,但这应该是一种更可重用的方法。
      • 修改 newfoo 以允许不传递额外的非关键字变量。

      【讨论】:

        【解决方案3】:
        def foo(a = None, b=None, c=None,**extras):
            return "a:%s, b:%s, c:%s" % (a, b, c)
        

        **extras 将收集所有额外的命名/关键字参数。

        【讨论】:

        • 仅当您被允许修改 foo 并且不介意它丢弃未知参数时才有效。在大多数情况下可能不是您想要的,如果该功能来自某个第三方包,则不可能。
        猜你喜欢
        • 2014-10-03
        • 2016-01-13
        • 2021-07-24
        • 1970-01-01
        • 2010-11-27
        • 2023-03-31
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多