[Python-ideas] Deferred evaluation [was Re: Draft PEP on string interpolation]

Steven D'Aprano steve at pearwood.info
Mon Aug 24 14:00:34 CEST 2015


On Mon, Aug 24, 2015 at 08:14:21PM +1000, Nick Coghlan wrote:

> This idea doesn't necessarily need deferred interpolation, so I'll use
> the current PEP 498 f-string prefix and substitution expression
> syntax. Consider the following function definition:
> 
>     def defer(expr):
>         return eval("lambda: (" + expr + ")")
> 
> We can use this today as a strange way of writing a lambda expression:
> 
>     >>> f = defer("42")
>     >>> f
>     <function <lambda> at 0x7f1c0314eae8>
>     >>> f()
>     42
> 
> There's no reason to do that, of course - you'd just use an actual
> lambda expression instead.

There's a problem with the idea of using eval to defer objects -- it 
relies on your object having an eval'able representation. Try to defer() 
the following list L:

L = []
L.append(L)

But putting that aside...

> However, f-strings will make it possible for folks to write code like this:
> 
>     callables = [defer(f"{i}") for i in range(10)]

How is that different from this?

    callables = [defer(str(i)) for i in range(10)]

If they are not the same, then what would this return?

[func() for func in callables]

I expect it to give [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]. Am I wrong?


> "{i}" in that example isn't a one-element set, it's a substitution
> expression that interpolates "str(i)" into the formatted string, 

I understand that 
f-strings are evaluated at the time of, um, their evaluation, so this 
would be equivalent to:

    callables = [defer("0"), defer("1"), defer("2", ... defer("9")]


> which
> is then evaluated by "defer" as if the template contained the literal
> value of "i" at the time of interpolation, rather than being a lazy
> reference to a closure variable.

I'm completely lost. How would you get a closure variable here?

I mean, I know how to get a closure in general terms, e.g.:

[(lambda : i) for i in range(10)]

but I'm not seeing where you would get a closure *specifically* in 
this situation with your defer function.



-- 
Steve


More information about the Python-ideas mailing list