python:带字符串输入的dispatch方法

时间:2016-03-28 20:11:59

标签: python

我需要编写一个接受3个参数的方法:

  1. a string,其名称为
  2. 该函数的有序list个参数。这包括具有默认值和*varargs的参数,但不包括**kwargs
  3. 表示任何其他关键字参数的dict,如果没有
  4. ,则为None

    我需要使用此输入来检索函数并调用它。例如:

    def dispatch(name, args, kwargs=None):
        do_magic_here(name, args, kwargs)
    
    def meth1():
        print "meth1"
    
    def meth2(a, b):
        print "meth2: %s %s" % (a, b)
    
    def meth3(a, **kwargs):
        print "meth3: " + a
        for k,v in kwargs.iteritems():
            print "%s: %s" % (k,v)
    

    我需要能够调用这样的事情:

    >>> dispatch("meth1", [])
    meth1
    >>> dispatch("meth2", [1, 3])
    meth2: 1 3
    >>> dispatch("meth3", [1], {"hello":2, "there":3})
    meth3: 1
    hello: 2
    there: 3
    

    我可以这样做:

    def do_magic_here(name, args, kwargs=None):
        if name=="meth1":
            meth1()
        if name=="meth2":
            meth2(args[0], args[1])
        if name=="meth3":
            meth3(args[0], **kwargs)
    

    但是我试图像40种方法一样调度,而且这个数字可能会扩大,所以我希望有更多的编程方式来实现它。我正在寻找getattr的东西,但我无法弄明白。

2 个答案:

答案 0 :(得分:4)

我会用

def dispatch(name, *args, **kwargs):
    func_name_dict[name](*args, **kwargs)

func_name_dict = {'meth1':meth1,
                  'meth2':meth2,
                  ...}

允许您更自然,更透明地通过argskwargs

>>> dispatch("meth2", 1, 3)
meth2: 1 3

您当然可以使用globals()locals()代替dict,但是您可能需要注意每个命名空间中您执行或不希望向调用者公开哪些函数

答案 1 :(得分:2)

确实,getattr会帮助你。

class X:
    def a(self):
        print('a called')
    def b(self, arg):
        print('b called with ' + arg)

x = X()
getattr(x, 'a')()
# a called
getattr(x, 'b')('foo')
# b called with foo

就像getattr以相同的方式处理方法和字段一样,您可以处理 通过引用locals()globals()来与函数和变量无关的函数和变量。

如果要引用全局范围内的函数:

globals()['meth'](args)

例如:

def dispatch(name, *args, **kwargs):
  globals()[name](*args, **kwargs)

dispatch('meth3', 'hello', foo='bar')
# meth3: hello
# foo: bar

请记住,在Python中,您始终可以使用**传递参数列表或关键字参数的词典:

dispatch('meth3', *['hello'], **{'foo':'bar'})

如果您真的更喜欢将参数作为list / dict传递给dispatch

def dispatch(name, args, kwargs):
  globals()[name](*args, **kwargs)

dispatch('meth3', ['hello'], {'foo': 'bar'})