1

I have an Class which creates objects that contain a dict of functions. These functions are defined in the class.

class Foo:

    def __init__(self, name, functions):
        self.name = name
        self.functions = functions

    def myFunction1(self):
        print self.name
        return 'foo'

    def myFunction2(self):
        return 'bar'

In another file, I instance an object of the previous class and I want to run one of the functions that is in the dict.

from foo import Foo

myFunctions = Foo.('a name', {0 : Foo.myFunction1, 1 : Foo.myFunction2})

myFunctions.functions[0]()

I have this error : TypeError: unbound method myFunction1() must be called with Foo instance as first argument.

I understand that when I execute the last line, I just call the function without call it with an object of Foo as first argument. But I can not write this :

myFunctions.myFunctions.functions[0]()

How can I call a function of this class which is stored in a dict attribute ?

alexis.
  • 13
  • 1
  • 7
  • What is `Foo` here? Do you mean it to be a class or should it be an instance? You don't need to resolve the method on the class *again*, you already have an unbound method (which includes a reference to the `Foo` class). – Martijn Pieters Feb 13 '15 at 12:17
  • `myFunctions.functions[0](myfunctions)`? Also, no need for the `foo` module reference in your assignment, since your import statement of the form `from othermodule import name` adds `name` to the current module's namespace. – PaulMcG Feb 13 '15 at 12:19
  • `Foo` is my class that create `Foo` objects. When I create a Foo object, I store in `myFunctions` attribute a dict of the functions that the object is supposed to use. The stored functions are defined in the same class than my object. I just want to call one of these functions by using the dict. – alexis. Feb 13 '15 at 12:31

4 Answers4

4

I do not really understand what you are trying to achieve with this functions dictionary, but note that instance.function() is equivalent to Class.function(instance). In the former, instance is implicitly passed as the self parameter; in the latter, you pass it explicitly.

Thus, you could try the following.

foo = Foo({0 : Foo.myFunction1, 1 : Foo.myFunction2})
print foo.functions[0](foo)
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • 1
    Thanks a lot, I replaced by Foo.functions[0](myFunctions)` (as `Class.function(instance`) and it works. I forgot this equivalence. – alexis. Feb 13 '15 at 12:56
0

You can call functions as a dictionary like this:

tmp = Foo()
tmp.functions={0:tmp.myFunction1, 1:tmp.myFunction2}
myFunctions = tmp.functions
print myFunctions.functions[0]()
dsummersl
  • 6,588
  • 50
  • 65
Valijon
  • 12,667
  • 4
  • 34
  • 67
  • It works when I don't pass self argument. But I need to use attributes of the object. I edit my question to be more comprehensive. – alexis. Feb 13 '15 at 12:44
0

If you need an object method, best way is to write another function that will call the correct function

class Foo:

    def __init__(self, functions):
        self.functions = functions

    def myFunction1(self):
        return 'foo'

    def myFunction2(self):
        return 'bar'

    def run_func(self, func_key, *args, **kwargs):
        func_name = self.functions.get(func_key)
        if func_name and hasattr(self, func_name):
            return getattr(self, func_name)(*args, **kwargs)
        else:
            return None

fun_dict = {0:'myFunction1', 1:'myFunction2'}
a = Foo(fun_dict)
print a.run_func(0)

You can send even arguments in this way.

def myFunction1(self, name):
    return name

print a.run_func(0, "test")

This will print test by the myFunction1

thiruvenkadam
  • 4,170
  • 4
  • 27
  • 26
0

Here is the simplest way to switch between functions:

       dict = {0 : Foo.myFunction1(), 1 : Foo.myFunction2()}
       function = fn_dict.get(0)
       function()
Karam Qusai
  • 713
  • 12
  • 16