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/

Reply via email to