Python: 如何通过字符串名称调用方法?

10 投票
4 回答
4026 浏览
提问于 2025-04-15 18:54

这是为了在一个JSON API中使用。
我不想要这样的:

if method_str == 'method_1':
    method_1()

if method_str == 'method_2':
    method_2()

显然,这样做不是最好的选择。我想知道如何以可重用的方式将字符串映射到像这样的函数(还要注意,我需要把参数传递给被调用的函数)。

下面是一个例子:

接收到的JSON数据:

{
    'method': 'say_something',
    'args': [
        135487,
        'a_465cc1'
    ]
    'kwargs': {
        'message': 'Hello World',
        'volume': 'Loud'
    }
}

# JSON would be turned into Python with Python's built in json module.

最终的调用:

# Either this
say_something(135487, 'a_465cc1', message='Hello World', volume='Loud')

# Or this (this is more preferable of course)
say_something(*args, **kwargs)

4 个回答

6

使用getattr这个函数。

比如说:

class Test(object):
    def say_hello(self):
        print 'Hell no, world!!111'
    def test(self):
        getattr(self, 'say_hello')()
6

做这件事最干净、安全的方法是创建一个字典,把名字和函数对应起来。如果这些实际上是方法,最好的办法还是创建这样的字典,虽然你也可以用 getattr。使用 globalseval 是不安全的,而且不太好。

25

对于实例的方法,可以使用 getattr

>>> class MyClass(object):
...  def sayhello(self):
...   print "Hello World!"
... 
>>> m=MyClass()
>>> getattr(m,"sayhello")()
Hello World!
>>> 

对于函数,你可以查看全局字典。

>>> def sayhello():
...  print "Hello World!"
... 
>>> globals().get("sayhello")()
Hello World!

在这个例子中,由于没有名为 prove_riemann_hypothesis 的函数,所以使用了默认函数 (sayhello)。

>>> globals().get("prove_riemann_hypothesis", sayhello)()
Hello World!

这种方法的问题在于,你和其他内容共享了命名空间。你可能想要防止 json 调用不该调用的方法。一个好的做法是像这样装饰你的函数。

>>> json_functions={}
>>> def make_available_to_json(f):
...  json_functions[f.__name__]=f
...  return f
...
>>> @make_available_to_json
... def sayhello():
...  print "Hello World!"
...
>>> json_functions.get("sayhello")()
Hello World!
>>> json_functions["sayhello"]()
Hello World!
>>> json_functions.get("prove_riemann_hypothesis", sayhello)()
Hello World!

撰写回答