2014-10-30 5 views
1

Я относительно новичок в python и хотел бы создать класс, который имеет словарь, соответствующий различным методам в классе. Я в настоящее время:Вызов словаря функции python из класса

class Test: 
    functions = {"Test1":test1, "Test2":test2} 

    def test1(self, arg1): 
    print "test1" 

    def test2(self, arg1): 
    print "test2" + arg1 

    def call_me(self, arg): 
    self.functions[arg](arg) 

Тогда в моем main.py У меня есть следующие:

from Test import Test 

t = Test() 

t.call_me('Test1') 

Когда я вызываю эту функцию, я получаю сообщение об ошибке сказав имя test1 не определено. Может ли кто-нибудь сказать мне, что я делаю неправильно? Любая помощь будет принята с благодарностью.

ответ

4

У вас есть несколько проблем здесь.

Во-первых, в этой строке:

functions = {"Test1":test1, "Test2":test2} 

В то время Python выполняет эту строку кода, нет ничего называют test1 или test2, так что вы собираетесь получить немедленный NameError. Если вы хотите так поступать, у вас будет определение functionsпосле все функции были определены, а не раньше.


Далее, на той же линии, test1 и test2 на данный момент являются набившие оскомину функции. Но вы пытаетесь назвать их так, как если бы они были методами, с магией self и все остальное. Это не сработает.Если вы понимаете, как работают методы, это должно быть очевидно, что вы можете обойти это в call_me метода:.

def call_me(self, arg): self.functions[arg].__get__(self, type(self))(arg) 

(В этом случае, вы можете уйти только с явно передавая self как дополнительный аргумент Но убедитесь, что вы понимаете, почему, прежде чем делать это.)


Наконец, вы пытаетесь вызвать call_me с функцией test1, вместо имени 'Test1'. Предположительно вся причина, как вы создали это отображение так, что вы можете использовать имена (динамически, как строки), так что давайте на самом деле их использовать:

t.call_me('Test1') 

Обратите внимание, что если единственная причина, вы можете» t use getattr заключается в том, что имена исполняемых файлов, которые вы хотите просмотреть, не совпадают с именами методов, которые вы хотите определить, вы всегда можете иметь карту строк для строк и искать полученные строки с помощью getattr, что позволяет избежать всех другие проблемы здесь. Заимствования из aruisdante's answer, добавляя в поиск имени и запоминания передать arg:

functions = {"Test1": "test1", "Test2": "test2"} 

def call_me(self, arg): 
    return getattr(self, self.functions[arg])(arg) 
+0

Упреждайте вас за предложение статической str: str-карты для решения проблемы произвольного сопоставления при использовании 'getattr' для решения проблемы привязки. – aruisdante

+0

@aruisdante: И ни один нисходящий знак для неправильного написания вашего имени в ссылке? :) Я пойду исправить это ... – abarnert

0

В вашем dict, "Test1" и "Test2" капитализируются, а соответствующие функции - нет. Измените клавиши dict на нижний регистр, и все должно работать.

3

Вы должны строковые кавычки вокруг аргумента, и T должно быть капитализированы:

t.call_me('Test1') 

Однако питон уже имеет функциональность, которую вы пытаетесь реплицировать встроенный в него с помощью метода getattr. И.Е. вы можете просто сделать:

def call_me(self, arg): 
    return getattr(self, arg)() 

Обратите внимание, что в этом случае имя должно быть точно таким же, как имя метода или он будет поднимать AttributeError, так что было бы:

t.call_me('test1') 

UPDATE

Так что теперь вы изменили свой вопрос, то ясно, что проблема:

class Test: 
    functions = {"Test1":test1, "Test2":test2} 

Это определение functions в области статического/класса. На данный момент test1 и test2 еще не созданы, и они не привязаны к экземпляру класса (так что не знаете, что должно быть self). «Правильное» решение, если вы хотите иметь произвольные отображения (так getattr не соответствует законопроекту) будет двигаться в этом внутри __init__():

class Test: 
    def __init__(self): 
     self._functions = {"Test1":self.test1, "Test2":self.test2} 

    def call_me(self, arg): 
     return self._functions[arg](arg) 
+0

Я не думаю, что GetAttr это именно то, что я ищу. Я пытаюсь избежать многих утверждений if else. Я читаю в файле, и каждое ключевое слово, найденное в файле, вызывает другой вызов функции. Таким образом, мне нужен способ связать ключ (ключевое слово, найденное в файле) со значением (соответствующая функция). – user3766476

+0

Я имею в виду, что если имена точны, 'getattr' будет делать то, что вы хотите. См. Мой обновленный ответ ... Я думаю, что многие из нас на самом деле неправильно поняли, что вы сделали, и пропустили, почему это не сработало. – aruisdante

+0

@aruisdante: Нет, это не единственная проблема, с которой он столкнулся. Он также определяет dict с значениями, которые еще не существуют, и используют функции, как если бы они были методами; просто решение первой проблемы не поможет вообще с двумя другими, они также должны быть решены. – abarnert

Смежные вопросы