50
class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func_name = 'function' + self.i
        self.func_name() # <-- this does NOT work.

    def function1(self):
        pass # do something

    def function2(self):
        pass # do something

This gives the error: TypeError: 'str' object is not callable

How would I go about doing this?

Note: self.func_name also does not work

DDriggs00
  • 87
  • 2
  • 9
dev-vb
  • 755
  • 1
  • 6
  • 13
  • 3
    Depending on your usage, you might be better off with either a list/dict of functions, or using a lambda function to pass an additional argument to the functions (the latter is mainly useful for callbacks). – sapi May 20 '13 at 03:34
  • This is not the code for which you got this error. when you do `self.func_name` you do not even access the local variable `func_name`. You are trying to access an instance variable named `class name` inside `self` - but such variable does not exist. – Elazar May 20 '13 at 03:37
  • 1
    @Elazar yes my mistake. I was translating the code and missed this one. – dev-vb May 20 '13 at 03:57
  • 5
    There is a subtle difference between this question and question 3061. This question focuses on calling _methods within a class_. 3061 focuses on regular functions. Python newbies may not be a able to apply the answers that were written there to this situation. – ChaimG Sep 17 '15 at 03:19
  • 2
    Voted to reopen. I am said newbie and it's completely non-obvious to me how this is a duplicate of the linked question. – quant Apr 27 '19 at 14:02

2 Answers2

69
def get(self):
      def func_not_found(): # just in case we dont have the function
         print 'No Function '+self.i+' Found!'
      func_name = 'function' + self.i
      func = getattr(self,func_name,func_not_found) 
      func() # <-- this should work!
Sergey Pugach
  • 5,561
  • 1
  • 16
  • 31
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • 1
    Thanks a lot for the response. Just for everyone's information, you can also give a default value to avoid exception. e.g., 'func = getattr(self, func_name, None)'. From python help (= help(getattr)): "When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case." – dev-vb May 20 '13 at 04:10
  • How can I unittest it? I tried but When I assert the function call it gives me false – 3nomis Jan 31 '20 at 11:15
6

Two things:

  1. In line 8 use,

    func_name = 'function' + str(self.i)

  2. Define a string to function mapping as,

      self.func_options = {'function1': self.function1,
                           'function2': self.function2
                           }
    
  3. So it should look as:

    class MyClass:

    def __init__(self, i):
          self.i = i
          self.func_options = {'function1': self.function1,
                               'function2': self.function2
                               }
    def get(self):
          func_name = 'function' + str(self.i)
          func = self.func_options[func_name]
          func() # <-- this does NOT work.
    
    def function1(self):
          //do something
    
    def function2(self):
          //do something
    
sinhayash
  • 2,693
  • 4
  • 19
  • 51
  • this should work as well. but the getattr solution is a very clean solution that we all can use. Thanks again Sinhayash for this novel solution. It may be useful to solve some other related issue. thanks. – dev-vb May 20 '13 at 03:59