El sáb, 25 jun 2022 a las 13:44, Chris Angelico (<ros...@gmail.com>) escribió:
> On Sun, 26 Jun 2022 at 04:41, Brendan Barnwell <brenb...@brenbarn.net> > wrote: > > In contrast, what I would want out of deferred evaluation is > precisely > > the ability to evaluate the deferred expression in the *evaluating* > > scope (not the definition scope) --- or in a custom provided namespace. > > Whether this evaluation is implicit or explicit is less important to > > me than the ability to control the scope in which it occurs. As others > > mentioned in early posts on this thread, this could complicate things > > too much to be feasible, but without it I don't really see the point. > > A custom-provided namespace can already be partly achieved, but > working in the evaluating scope is currently impossible and would > require some major deoptimizations to become possible. > > >>> expr = lambda: x + y > >>> expr.__code__.co_code > b't\x00t\x01\x17\x00S\x00' > >>> ns = {"x": 3, "y": 7} > >>> eval(expr.__code__, ns) > 10 > > This works because the code object doesn't have any locals, so the > name references are encoded as global lookups, and eval() is happy to > use arbitrary globals. I say "partly achieved" because this won't work > if there are any accidental closure variables - you can't isolate the > lambda function from its original context and force everything to be a > global: > > >>> def f(x): > ... return lambda: x + y > ... > >>> expr = f(42) > >>> eval(expr.__code__, ns) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: code object passed to eval() may not contain free variables > > The mere fact that there's a local variable 'x' means that you can't > compile the expression 'x + y'. So maybe there'd need to be some weird > trick with class namespaces, but I'm really not sure what would be > worth doing. > > Note that in Python 3.11 exec (but not eval) gains the ability to pass an explicit closure: >>> def f(x): ... return lambda: print(x + y) ... >>> l = f(1) >>> exec(l.__code__, {"y": 3}, closure=(types.CellType(2),)) 5 This doesn't quite solve the problem being discussed here, but it may help. This was added in https://github.com/python/cpython/pull/92204. We didn't add it to eval() because there was no use case at the time, but it would be easy to add the same support to eval() too.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7IPM4KFLZGTQDMOJW6VKE6YP2U2BTQLB/ Code of Conduct: http://python.org/psf/codeofconduct/