Skip to content
Advertisement

Defining functions dynamically does not work inside class objects?

In my current project, I am constructing functions dynamically by assembling a string, executing this string, then appending the resulting functions to a list. This works well inside a console, even when looped, but strangely does not work when I attempt to do the same thing inside a class object. Do you know why, and how I could get this to work?

The example snippet below is a minimal example. Constructing a function from a string is not an issue inside the main script, but when used inside a class object, the function is no longer assembled and an attempt to append it to a list returns an error.

import numpy as np

# Create a string for a function
funstr  = "def fun1(x): return x"

# Create a function
exec(funstr)

# Call the function
print('Evaluate the function:')
print(fun1(5))
print('Success!')

# Create functions in a loop
funlist = []
for i in range(5):
    funstr  = "def fun2(x): return x+"+str(i)
    exec(funstr)
    funlist.append(fun2)

# Check if the stored functions work
print('Evaluate the list functions:')
for i in range(5):
    print(funlist[i](5))
print('Success!')

# Try the same thing in a class
class testobject:
    
    def build_functions(self):
        
        # Do the same thing we did outside inside the class
        self.funlist = []
        for i in range(5):
            funstr  = "def fun3(x): return x+"+str(i)
            exec(funstr)
            print("Here, a function fun3 should have been assembled. For some reason, it hasn't been.")
            # !! Here, the function crashes because 'fun3' does not exist. !!
            self.funlist.append(fun3)
            
        print('Evaluate the list functions inside the object:')
        for i in range(5):
            print(self.funlist[i](5))
            
# Initialize an object
obj     = testobject()

# Create the functions inside
obj.build_functions()

Advertisement

Answer

fun3 is being defined in the local scope, but self.funlist.append(fun3) is looking for the variable fun3 in the global scope (because there’s no local variable definition visible in the source code of the function).

You can use the locals() function to get a dictionary of the local variables.

self.funlist.append(locals()['fun3'])
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement