Python: Как вы вызываете метод, когда у вас есть только строковое имя метода? - PullRequest
10 голосов
/ 05 февраля 2010

Это для использования в 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 ]

25 голосов
/ 05 февраля 2010

Для методов экземпляров используйте getattr

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

Для функций вы можете посмотреть в глобальном dict

>>> 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!
6 голосов
/ 05 февраля 2010

Чистый, безопасный способ сделать это состоит в том, чтобы назначить имена для функций. Если это на самом деле методы, лучший способ все еще сделать такой диктат, хотя getattr также доступен. Использование globals или eval небезопасно и грязно.

6 голосов
/ 05 февраля 2010

Используйте getattr. Например:

class Test(object):
    def say_hello(self):
        print 'Hell no, world!!111'
    def test(self):
        getattr(self, 'say_hello')()
1 голос
/ 05 февраля 2010

Предполагая, что все функции являются глобальными переменными (если они не были определены внутри других функций), к ним можно получить доступ с помощью функции globals(). globals() возвращает словарь всех глобальных переменных, включая функции.

Например:

$ 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!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...