rob...@robertlehmann.de wrote: > On Friday, June 13, 2014 8:07:45 AM UTC+2, Marko Rauhamaa wrote: >> >> The documentation is a bit vague about it: >> >> If only globals is provided, it must be a dictionary, which will be >> used for both the global and the local variables. If globals and >> locals are given, they are used for the global and local variables, >> respectively. If provided, locals can be any mapping object. > > > Interesting. This paragraph explicitly states "locals can be any mapping > object," but that seems to be false: > > > class Namespace(dict): > def __getitem__(self, key): > print("getitem", key) > def __setitem__(self, key, value): > print("setitem", key, value) > > def fun(): > x # should call locals.__getitem__
No, x is a global here. > y = 1 # should call locals.__setitem__ > > exec(fun.__code__, {}, Namespace()) > > > Neither __getitem__ nor __setitem__ seem to be called on the local > variables. Accessing fun.__code__ is clever, but unfortunately the compiler produces different bytecodes for loading/storing variables inside a function. Compare: >>> import dis >>> def fun(x=2): ... x ... y = 1 ... >>> dis.dis(fun.__code__) 2 0 LOAD_FAST 0 (x) 3 POP_TOP 3 4 LOAD_CONST 1 (1) 7 STORE_FAST 1 (y) 10 LOAD_CONST 0 (None) 13 RETURN_VALUE >>> dis.dis(compile("x\ny=2", "<nofile>", "exec")) 1 0 LOAD_NAME 0 (x) 3 POP_TOP 2 4 LOAD_CONST 0 (2) 7 STORE_NAME 1 (y) 10 LOAD_CONST 1 (None) 13 RETURN_VALUE Only the latter works as advertised: >>> exec("x\ny=1", {}, Namespace()) getitem x setitem y 1 -- https://mail.python.org/mailman/listinfo/python-list