Is it possible to bind a name inside a python function after the function has been compiled?

79 Views Asked by At

I know this pattern is would be very bad, I'm asking the question out of curiosity not because I'm planning on doing this in production code.

Suppose I define a function:

def function(x, y):
    return x + y + z

And the variable z doesn't exist in the module the function was defined.

Is it possible to import the function from another module and somehow manipulate the code object, or play some sort of dirty trick with a decorator, or something, in order to make it work correctly?

I've tried setting co_varnames and co_argcount to (x, y, z) and 3 respectively, but this still doesn't bind the name z to the argument it seems.

To be clear, I know if I define a global named z in the same module this works, I'm asking about importing this function and somehow making z bind to a variable I want, in a different module.

1

There are 1 best solutions below

0
Kelly Bundy On BEST ANSWER

Maybe use the function's code to create a new function using different globals:

# create module for demo
with open('module.py', 'w') as f:
    f.write('''
def function(x, y):
    return x + y + z
''')

from module import function

function = type(function)(function.__code__, globals())

z = 100
print(function(20, 3))

Output (Try it online!):

123

Or if you want a different variable name, maybe indeed use a "decorator" that sets z to the value of your variable before calling the function:

from module import function

f = function
def function(*args):
    f.__globals__['z'] = foobar
    return f(*args)

foobar = 100
print(function(20, 3))

Try it online!