【问题标题】:generate a list of arguments in correct order from args and kwargs?从 args 和 kwargs 生成正确顺序的参数列表?
【发布时间】:2013-01-03 15:28:30
【问题描述】:

关注这个话题:allow users to "extend" API functions

class Inspector:
    def __init__(self, passedFunc):
        self.passedFunc = passedFunc

    def __call__(self, *args, **kwargs):
        # Inspector needs to generate a list of arguments of the passed function and print them in *correct* order

        # now how to generate a list of arguments using data from both ''args' and 'kwargs'?
        # the user might keep default argument values, in which case both will be None,
        # he might only use args, in which case it is easy,
        # but he might also use kwargs, in which case I don't see how to generate a list with correct order of arguments
        # and he might use all 3 from above together

        # I found this solution for when only default arguments are used
        if args == () and kwargs == {}: args = self.passedFunc.__defaults__

        print args  

@Inspector
def exampleFunc(value=0, otherValue=3):
    pass

exampleFunc()

如何为所有场景生成正确的order args列表?

【问题讨论】:

  • 由于kwargsdict,没有顺序,我认为不可能。
  • kwargs 是“关键字参数”,它是一个字典,字典没有在 python 中排序,因此它们没有“顺序”,但您始终可以按您想要的任何方式按其键或值对字典进行排序- 但他们没有预设定义的顺序。
  • 我知道,这就是我问的原因,也许还有其他方法。也许使用类似于__defaults__ 的东西获取订单并从字典中获取它们的值

标签: python arguments decorator args keyword-argument


【解决方案1】:

这是在装饰器中构建实际参数列表的方法:

import inspect

class Inspector:
    def __init__(self, passedFunc):
        self.passedFunc = passedFunc

    def __call__(self, *args, **kwargs):

        spec = inspect.getargspec(self.passedFunc)
        params = dict(zip(spec.args, args))
        defaults = dict(zip(spec.args[-len(spec.defaults):], spec.defaults))

        for k, v in kwargs.items():
            if k not in spec.args:
                raise TypeError('unexpected argument', k)
            if k in params:
                raise TypeError('mulitple values for argument', k)
            params[k] = v

        for k in spec.args:
            if k not in params:
                if k in defaults:
                    params[k] = defaults[k]
                else:
                    raise TypeError('missing argument', k)

        args_in_order = [params[x] for x in spec.args]

        print args_in_order

例子:

@Inspector
def exampleFunc(value=0, otherValue=3):
    pass

exampleFunc()  # 0,3
exampleFunc('foo')  # foo,3
exampleFunc(otherValue='foo', value=555) # 555,foo

【讨论】:

  • 警告:spec.defaults 可能是None,在这种情况下调用len 会引发错误。
【解决方案2】:
In [244]: def myinspector(func):
     ...:     def inner(*args,**kwargs):
     ...:         myrs1=[list(x) for x in zip(func.func_code.co_varnames[-len(func.func_defaults):],func.func_defaults)]
     ...:         if kwargs:
     ...:             for x in myrs1:
     ...:                 if x[0] in kwargs: x[1]=kwargs.get(x[0])
     ...:             for x in kwargs:
     ...:                 if x not in func.func_code.co_varnames: myrs1.append([x,kwargs.get(x)])
     ...:         if args:myrs1=list(args)+ myrs1
     ...:         print myrs1
     ...:     return inner

In [245]: @myinspector
     ...: def exampleFunc(value=0,othervalue=3):
     ...:     pass

In [246]: exampleFunc()
[['value', 0], ['othervalue', 3]]

In [247]: exampleFunc(1,4,5,value=9,name=5)
[1, 4, 5, ['value', 9], ['othervalue', 3], ['name', 5]]

In [248]: exampleFunc(name=5, othervalue=6)
[['value', 0], ['othervalue', 6], ['name', 5]]

【讨论】:

  • IMO 得到一个字典会更好,现在我考虑一下
  • @user975135 你想要有序的 args 和 kwrags 吗?因为我刚刚用过 kwargs .. .
  • 是的,我正要说它没有将它们考虑在内,如果使用则给出“无”
  • @user975135 我稍后更新了它(对于 args 和 kwargs).. 检查最新的.. . .
  • 好极了,也许也可以发布一个生成字典的版本,每个人都会很高兴
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2017-01-28
  • 1970-01-01
  • 2021-07-26
  • 2022-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多