Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3:使用参数字典动态调用方法_Python_Python 3.x - Fatal编程技术网

Python3:使用参数字典动态调用方法

Python3:使用参数字典动态调用方法,python,python-3.x,Python,Python 3.x,我需要能够在一个类上动态调用一个方法,该类接受基于字符串名称和变量字典的各种参数。我知道如何使用inspect模块查找签名,并且可以使用getattr获取方法,但是我不知道如何以正确的顺序分配参数,以便以纯动态的方式调用它 class MyClass(): def call_me(a, b, *args, foo='bar', **kwargs): print('Hey, I got called!') command = { 'action':'c

我需要能够在一个类上动态调用一个方法,该类接受基于字符串名称和变量字典的各种参数。我知道如何使用inspect模块查找签名,并且可以使用getattr获取方法,但是我不知道如何以正确的顺序分配参数,以便以纯动态的方式调用它

class MyClass():
    def call_me(a, b, *args, foo='bar', **kwargs):
        print('Hey, I got called!')

command = {
          'action':'call_me',
          'parameters':{
                        'a': 'Apple',
                        'b': 'Banana',
                        'args':['one','two','three','four'],
                        'foo':'spam',
                        'clowns':'bad',
                        'chickens':'good'
                       }
           }

me = MyClass()
action = getattr(me,command['action'])

... now what?
我需要能够动态调用此函数,就像使用此代码一样,而不预先知道方法的实际参数:

a = command['parameters']['a']
b = command['parameters']['b']
args = command['parameters']['args']
foo = command['parameters']['foo']
kwargs = {
          'clowns': command['parameters']['clowns'],
          'chickens':command['parameters']['chickens']
         }

value = action(a, b, *args, foo=foo, **kwargs)
当然,有一种很好的蟒蛇式方法可以做到这一点

编辑:修复了getattr直接调用MyClass而不是MyClass实例的问题。

尝试如下操作:

action = getattr(me,command['action'])
action(**{'a': 'Apple',
      'b': 'Banana',
      'args':['one','two','three','four'],
      'foo':'spam',
      'clowns':'bad',
      'chickens':'good'
     })

这是迄今为止我发现的最好的方法,可以捕获正常args、*args、关键字args和**kwargs的所有可能组合,而不会出现任何错误:

import inspect
class MyClass():
    def a(self):
        pass
    def b(self,foo):
        pass
    def c(self,foo,*extras):
        pass
    def d(self,foo,food='spam'):
        pass
    def e(self,foo,**kwargs):
        pass
    def f(self,foo,*extras,food='spam'):
        pass
    def g(self,foo,*extras,**kwargs):
        pass
    def h(self,foo,*extras,food='spam',**kwargs):
        pass
    def i(self,*extras):
        pass
    def j(self,*extras,food='spam'):
        pass
    def k(self,*extras,**kwargs):
        pass
    def l(self,*extras,food='spam',**kwargs):
        pass
    def m(self,food='spam'):
        pass
    def n(self,food='spam',**kwargs):
        pass
    def o(self,**kwargs):
        pass


def dynamic_invoke(obj,name,parameters):
    action = getattr(obj,name)
    spec = inspect.getfullargspec(action)

    used = []
    args = ()
    kwargs = {}

    for a in spec.args[1:]:
        # skip the "self" argument since we are bound to a class
        args += (parameters[a], )
        used.append(a)

    if spec.varargs:
        args += tuple(parameters[spec.varargs])
        used.append(spec.varargs)

    for kw in spec.kwonlyargs:
        try:
            kwargs[kw] = parameters[kw]
            used.append(kw)
        except KeyError:
            pass

    # pass remaining parameters to kwargs, if allowed
    if spec.varkw:
        for k,v in parameters.items():
            if k not in used:
                kwargs[k] = v

    return action(*args,**kwargs)

me = MyClass()
params = {
        'foo':'bar',
        'extras':['one','two','three','four'],
        'food':'eggs',
        'parrot':'blue'
        }

dynamic_invoke(me,'a',params)
dynamic_invoke(me,'b',params)
dynamic_invoke(me,'c',params)
dynamic_invoke(me,'d',params)
dynamic_invoke(me,'e',params)
dynamic_invoke(me,'f',params)
dynamic_invoke(me,'g',params)
dynamic_invoke(me,'h',params)
dynamic_invoke(me,'i',params)
dynamic_invoke(me,'j',params)
dynamic_invoke(me,'k',params)
dynamic_invoke(me,'l',params)
dynamic_invoke(me,'m',params)
dynamic_invoke(me,'n',params)
dynamic_invoke(me,'o',params)
print('done!')

action(**command['parameters'])
@falsetru因为
*args
args=command['parameters'].pop('args',None),所以这并不容易;操作(**命令['parameters'],*args)