Home > Enterprise >  eval on an argument obtained through `function.__code__.co_varnames` isn't working
eval on an argument obtained through `function.__code__.co_varnames` isn't working

Time:12-10

def initialize_network(n_inputs, n_hidden1, n_hidden2, n_outputs):
     print(eval('n_inputs'))
     perceptron_count = [eval(arg) for arg in initialize_network.__code__.co_varnames[:4]]

initialize_network(1,2,3,4)

The above code when executed on my loacal machine produces the error: NameError: name 'n_inputs' is not defined

When executed on Google Colab produces the error: NameError: name 'n_hidden1' is not defined

But, if I do print(eval('n_inputs')) or print(eval('n_hidden1')) the correct values of the variables get printed.

What's happening here?

CodePudding user response:

The problem lies in the fact that a list-comprehension ([i for i in x]) is executed like a sub-function. Aka:

square = [i*i for i in nums]

Is executed the same way as:

def _s(i):
    return i*i
square = list(map(_s, nums))

The i*i is executed in an inner-scope. The documentation states: Note, eval() does not have access to the nested scopes (non-locals) in the enclosing environment.

n_inputs is a variable of the enclosing environment of the list comprehension. The only value eval sees in your example is arg and any global variables.

Try the following and you'll see why eval says n_inputs is not defined.

def my_func(x,y):
    print(locals())
    _ = [print(locals()) for z in range(1)]

locals() and globals() is automatically passed to eval if not explicitly given. But locals() inside of the list-comprehension doesn't contain n_inputs.

So how to fix? Pass the functions locals to eval.

def initialize_network(n_inputs, n_hidden1, n_hidden2, n_outputs):
     print(eval('n_inputs'))
     _locals = locals()
     perceptron_count = [eval(arg, locals=_locals) for arg in initialize_network.__code__.co_varnames[:4]]

initialize_network(1,2,3,4)
  • Related