Python:当你只有方法的字符串名称时,如何调用方法?

时间:2021-02-26 22:24:46

This is for use in a JSON API. I don't want to have:

这适用于JSON API。我不想要:

if method_str == 'method_1':
    method_1()

if method_str == 'method_2':
    method_2()

For obvious reasons this is not optimal. How would I use map strings to methods like this in a reusable way (also note that I need to pass in arguments to the called functions).

出于显而易见的原因,这不是最佳的我如何以可重用的方式将地图字符串用于这样的方法(还要注意我需要将参数传递给被调用的函数)。

Here is an example:

这是一个例子:

INCOMING JSON:

进入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.

Resulting call:

致电:

# 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 个解决方案

#1


23  

For methods of instances, use getattr

对于实例方法,请使用getattr

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

For functions you can look in the global dict

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

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

In this case, since there is no function called prove_riemann_hypothesis the default function (sayhello) is used

在这种情况下,由于没有名为prove_riemann_hypothesis的函数,因此使用默认函数(sayhello)

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

The problem with this approach is that you are sharing the namespace with whatever else is in there. You might want to guard against the json calling methods it is not supposed to. A good way to do this is to decorate your functions like this

这种方法的问题在于您与其他任何内容共享命名空间。您可能希望防范它不应该使用的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!

#2


6  

The clean, safe way to do this is to make a dict mapping names to functions. If these are actually methods, the best way is still to make such a dict, though getattr is also available. Using globals or eval is unsafe and dirty.

干净,安全的方法是将dict映射到函数名称。如果这些实际上是方法,最好的方法仍然是制作这样的dict,尽管getattr也可用。使用全局或eval是不安全和脏的。

#3


6  

Use getattr. For example:

使用getattr。例如:

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

#4


1  

Assuming the functions are all global variables (they are, unless they were defined inside another functions), they can be accessed with the globals() function. globals() returns a dictionary of all global variables, including functions.

假设函数都是全局变量(除非它们在另一个函数中定义,否则它们可以使用globals()函数访问它们)。 globals()返回所有全局变量的字典,包括函数。

For example:

例如:

$ python
Python 2.6.2 (r262:71600, Apr 16 2009, 09:17:39) 
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def some_function():
...     print "Hello World!"
... 
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'some_function': <function some_function at 0x6326b0>, '__package__': None}
>>> globals()['some_function']()
Hello World!

#1


23  

For methods of instances, use getattr

对于实例方法,请使用getattr

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

For functions you can look in the global dict

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

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

In this case, since there is no function called prove_riemann_hypothesis the default function (sayhello) is used

在这种情况下,由于没有名为prove_riemann_hypothesis的函数,因此使用默认函数(sayhello)

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

The problem with this approach is that you are sharing the namespace with whatever else is in there. You might want to guard against the json calling methods it is not supposed to. A good way to do this is to decorate your functions like this

这种方法的问题在于您与其他任何内容共享命名空间。您可能希望防范它不应该使用的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!

#2


6  

The clean, safe way to do this is to make a dict mapping names to functions. If these are actually methods, the best way is still to make such a dict, though getattr is also available. Using globals or eval is unsafe and dirty.

干净,安全的方法是将dict映射到函数名称。如果这些实际上是方法,最好的方法仍然是制作这样的dict,尽管getattr也可用。使用全局或eval是不安全和脏的。

#3


6  

Use getattr. For example:

使用getattr。例如:

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

#4


1  

Assuming the functions are all global variables (they are, unless they were defined inside another functions), they can be accessed with the globals() function. globals() returns a dictionary of all global variables, including functions.

假设函数都是全局变量(除非它们在另一个函数中定义,否则它们可以使用globals()函数访问它们)。 globals()返回所有全局变量的字典,包括函数。

For example:

例如:

$ python
Python 2.6.2 (r262:71600, Apr 16 2009, 09:17:39) 
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def some_function():
...     print "Hello World!"
... 
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'some_function': <function some_function at 0x6326b0>, '__package__': None}
>>> globals()['some_function']()
Hello World!