On Sat, Dec 4, 2021 at 2:34 PM Steven D'Aprano <st...@pearwood.info> wrote:
>
> On Fri, Dec 03, 2021 at 10:40:42AM +1100, Chris Angelico wrote:
>
> > Here's what you get:
> >
> > >>> def f(lst=>[], n=>len(lst)): ...
> > ...
> > >>> f.__defaults_extra__
> > ('[]', 'len(lst)')
> >
> > String representation, but exactly what the default is.
>
> Excellent. And you've just proven that we can evaluate the defaults.
>
>     >>> a = '[]'          # f.__defaults_extra__[0]
>     >>> b = 'len(lst)'    # f.__defaults_extra__[1]
>     >>> lst = eval(a, globals())
>     >>> n = eval(b, globals(), dict(lst=lst))
>     >>> print(lst, n)
>     [] 0
>
> Worst case scenario, we can eval the string representation, and that
> should work for the great majority of cases that don't involve
> nonlocals.

Yes, those awkward cases that involve nonlocals. A pity about those.

But hey, if that's not a problem to you, then sure, go ahead, just
eval it. The string is there for you to use.

> But if the defaults are proper code objects, complete with a closure to
> capture their nonlocal environment, then we should be able to do even
> better and capture nonlocals as well.
>
> Could there be odd corner cases that don't quite work? Say, like a
> comprehension inside a class body?
>
> https://github.com/satwikkansal/wtfpython#-name-resolution-ignoring-class-scope
>
> Oh well. Let's not make the perfect the enemy of the good.

Lots and lots and lots of potential problems. Consider:

def f():
    a = 1
    def f(b, x=>a+b):
        def g(): return x, a, b

Both a and b are closure variables - one because it comes from an
outer scope, one because it's used in an inner scope. So to evaluate
a+b, you have to look up an existing closure cell, AND construct a new
closure cell.

The only way to do that is for the compiled code of a+b to exist
entirely within the context of f's code object. Which means that there
isn't really anything to usefully pull out and evaluate, since it
can't be executed until you've set up a stack frame to call f, and
once you've done that, you're basically just...  calling f anyway.

If you still dispute that it's impossible, you're absolutely welcome
to write your own reference implementation. I've argued this point
with as much detail as I can, and short of pointing stuff out in the
code, I can't do anything more. If you want to keep on saying "but of
COURSE it's possible", then go ahead, prove it to me.

ChrisA
_______________________________________________
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/MFWXQ6FBQONK4GUXEAPNO7VFEL2NEFPB/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to