Home > OS >  NameError in function, nested in __init__ method
NameError in function, nested in __init__ method

Time:10-02

class sheet:
    def __init__(self):
        def close_game():
            print("game closed")
        def click():
            eval("close_game()")

        click()

s1 = sheet()

I'm getting such error:

  File "<string>", line 6, in click
NameError: name 'close_game' is not defined

But if I replace 'eval("close_game()")' with 'close_game()' it works correctly. Please explain to me why it works like that.

CodePudding user response:

eval does not have access to the scope chain. It can only see immediate local variables by default:

def outer():
    non_loc = 1

    def inner_var():
        print(non_loc)

    def inner_eval():
        print(eval('non_loc'))

    inner_var()   # ok
    inner_eval()  # not ok


outer()

You can, however, pass whatever you want in the locals argument.

CodePudding user response:

The reason is that eval sets up its own namespace and close_game is not present in that namespace by default. You can add it explicitly like this:

...
        def close_game():
            print("game closed")
        def click():
            eval("close_game()", {"close_game": close_game})

Then it will resolve properly and the function will be called as expected.

PS: I suppose it is prudent to mention that using eval is usually risky business. Just in case you are not aware, it is easy to introduce huge security vulnerabilities. This has been discussed on this platform extensively, so I am just going to leave this warning.

  • Related