I'm relatively new to python and would like to make a class that has a dictionary that corresponds to different methods in the class. I currently have :
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)
Then in my main.py I have the following:
from Test import Test
t = Test()
t.call_me('Test1')
When I call this function I get an error saying name test1 is not defined. Can anyone tell me what I am doing wrong? Any help would be greatly appreciated.
You've got multiple problems here.
First, in this line:
functions = {"Test1":test1, "Test2":test2}
At the time Python executes this line of code, there is nothing called test1
or test2
, so you're going to get an immediate NameError
. If you want to do things this way, you're going to have define functions
after all of the functions have been defined, not before.
Next, on the same line, test1
and test2
at this point are plain-old functions. But you're trying to call them as if they were methods, with the magic self
and everything. That isn't going to work. If you understand how methods work, it should be obvious that you can work around this in the call_me
method:
def call_me(self, arg): self.functions[arg].__get__(self, type(self))(arg)
(In this case, you can also get away with just explicitly passing self
as an extra argument. But make sure you understand why before doing that.)
Finally, you're trying to call call_me
with the function test1
, instead of the name 'Test1'
. Presumably the whole reason you've created this mapping is so that you can use the names (dynamically, as strings), so let's actually use them:
t.call_me('Test1')
Note that if the only reason you can't use getattr
is that the runtime names you want to look up aren't the same as the method names you want to define, you can always have a map of strings to strings, and look up the resulting strings with getattr
, which avoids all the other problems here. Borrowing from aruisdante's answer, adding in the name lookup and remembering to pass arg
:
functions = {"Test1": "test1", "Test2": "test2"}
def call_me(self, arg):
return getattr(self, self.functions[arg])(arg)