Динамический вызов вложенных функций на основе аргументов - PullRequest
2 голосов
/ 25 ноября 2010

Если у меня есть следующий класс Python:

class Test(object):
    funcs = {
        "me"    : "action",
        "action": "action",
        "say"   : "say",
        "shout" : "say"
    }

    def dispatch(self, cmd):
        def say:
            print "Nested Say"

        def action:
            print "Nested Action"

        # The line below gets the function name as a string,
        # How can I call the nested function based on the string?
        Test.funcs.get(cmd, "say")

Я хотел бы иметь возможность сделать следующее:

>>> Test().dispatch("me")
Nested Action
>>> Test().dispatch("say")
Nested Say

Любые предложения относительно того, как я могу сделать это

Ответы [ 2 ]

4 голосов
/ 25 ноября 2010

Я бы, вероятно, сделал что-то вроде этого:

def register(dict_, *names):
    def dec(f):
        m_name = f.__name__
        for name in names:
            dict_[name] = m_name
        return f
    return dec

class Test(object):

    commands = {}

    @register(commands, 'foo', 'fu', 'fOo')
    def _handle_foo(self):
        print 'foo'

    @register(commands, 'bar', 'BaR', 'bAR')
    def _do_bar(self):
        print 'bar'

    def dispatch(self, cmd):
        try:
            return getattr(self, self.commands[cmd])()
        except (KeyError, AttributeError):
            # Command doesn't exist. Handle it somehow if you want to
            # The AttributeError should actually never occur unless a method gets 
            # deleted from the class

Теперь класс предоставляет dict, чьи ключи являются командами для проверки членства.Все методы и словарь создаются только один раз.

t = Test()

if 'foo' in t.commands:
    t.dispatch('foo')

for cmd in t.commands:
    # Obviously this will call each method with multiple commands dispatched to it once
    # for each command
    t.dispatch(cmd)

И т. Д.

2 голосов
/ 25 ноября 2010
class Test(object):

    def dispatch(self):
        def say():
            print "Nested Say"

        def action():
            print "Nested Action"

        funcs = {
            "me"    : action,
            "action": action,
            "say"   : say,
            "shout" : say
        }

        Test.funcs.get(cmd, say)()

Или, сохраняя вашу текущую структуру:

class Test(object):

    funcs = {
        "me"    : "action",
        "action": "action",
        "say"   : "say",
        "shout" : "say"
        }

    def dispatch(self, cmd):
        def say():
            print "Nested Say"

        def action():
            print "Nested Action"

        locals()[Test.funcs.get(cmd, "say")]()

Хотя я нахожу этот дизайн немного странным.Почему классный уровень должен знать о локальных функциях диспетчеризации?

...