[Tim]
>> """
>> An assignment expression binds the target, except in a function F
>> synthesized to implement a list comprehension or generator expression
>> (see XXX). In the latter case[1], the target is bound in the block
>> containing F, and errors may be detected: If the target also appears
On 13 May 2018 at 20:00, Tim Peters wrote:
> [Tim]
> >> - If the target is not local to any function enclosing F, and is not
> >> declared `global` in the block containing F, then the target is bound
> >> in the block containing F.
>
> [also Tim]
> > FYI, that's still not
[Tim]
>> - If the target is not local to any function enclosing F, and is not
>> declared `global` in the block containing F, then the target is bound
>> in the block containing F.
[also Tim]
> FYI, that's still not right, ...
> I suspect that the above should be reworded to the simpler:
>
> - If
[Tim]
> ...
> - If the target is not local to any function enclosing F, and is not
> declared `global` in the block containing F, then the target is bound
> in the block containing F.
FYI, that's still not right, but I've been distracted by trying to
convince myself that the manual actually
[Tim[
>> ... If a comprehension C is in class scope S, apparently the
>> class locals are _not_ in C's environment. Since C doesn't
>>> even have read access to S's locals, it seems to me bizarre
>> that ":=" could _create_ a local in S.
[Ethan Furman ]
> Python 3.7.0b3+
On Sun, May 13, 2018 at 5:17 PM, Ethan Furman wrote:
> On 05/12/2018 11:41 PM, Tim Peters wrote:
>>
>> [Tim, suggests changes to the Reference Manual's 4.2.1]
>>>
>>> """
>>> An assignment expression binds the target, except in a function F
>>> synthesized to implement a list
On 05/12/2018 11:41 PM, Tim Peters wrote:
[Tim, suggests changes to the Reference Manual's 4.2.1]
"""
An assignment expression binds the target, except in a function F
synthesized to implement a list comprehension or generator expression
(see XXX). In the latter case, if the target is not in
[Tim, suggests changes to the Reference Manual's 4.2.1]
> """
> An assignment expression binds the target, except in a function F
> synthesized to implement a list comprehension or generator expression
> (see XXX). In the latter case, if the target is not in F's
> environment (see section 4.2.2)
[Nick]
>> That's all well and good, but it is *completely insufficient for the
>> language specification*.
> I haven't been trying to write reference docs here, but so far as
> supplying a rigorous specification goes, I maintain the above gets
> "pretty close". It needs more words, and certainly
Ah, fudge - I pasted in the wrong "high-level" code. Sorry! The code
that's actually being emulated is not
> list(i + sum((i := i+1) + i for j in range(i))
> for i in range(5))
but
list(i + sum((i := i+1) for j in range(i)) + i
for i in range(5))
> ...
I have piles of
[Tim]
> ...
> But an assignment expression target name always has the
> same scope within a comprehension. [which is a consequence
> of the rules - not a rule of its own]
Something related to ponder: what's the meaning of the following
_without_ the proposed scope change? So the Golden Binding
There's a lot of things in Brendan's email which I disagree with but
will skip to avoid dragging this out even further. But there's one point
in particular which I think is important to comment on.
On Thu, May 10, 2018 at 11:23:00AM -0700, Brendan Barnwell wrote:
> One of the great things
[Tim[
>> ...
>> ":=" target names in a genexp/listcmp are treated exactly the same as
>> any other non-for-target name: they resolve to the same scope as they
>> resolve to in the block that contains them. The only twist is that if
>> such a name `x` isn't otherwise known in the block, then `x`
(Note: this is an off-topic side thread, unrelated to assignment
expressions. Inline comment below.)
On Fri, May 11, 2018 at 9:08 AM, Chris Angelico wrote:
> On Fri, May 11, 2018 at 9:15 PM, Nick Coghlan wrote:
> > * *maybe* discover that even the above
On Fri, May 11, 2018 at 9:15 PM, Nick Coghlan wrote:
> * *maybe* discover that even the above expansion isn't quite accurate, and
> that the underlying semantic equivalent is actually this (one way to
> discover this by accident is to have a name error in the outermost
On 11 May 2018 at 07:15, Nick Coghlan wrote:
> * *maybe* discover that even the above expansion isn't quite accurate, and
> that the underlying semantic equivalent is actually this (one way to
> discover this by accident is to have a name error in the outermost iterable
>
On 10 May 2018 at 23:47, Tim Peters wrote:
> ...
>
> [Guido]
> >> You should really read Tim's initial post in this thread, where he
> >> explains his motivation.
>
> [Nick]
> > I did, and then I talked him out of it by pointing out how confusing it
> > would be to have the
[Tim]
>> Since this is all about scope, while I'm not 100% sure of what Guido
>> meant, I assumed he was saying "p can only have one scope in the
>> synthetic function: local or non-local, not both, and local is what I
>> propose". For example, let's flesh out his example a bit more:
>>
>> p
>[Tim]
> Since this is all about scope, while I'm not 100% sure of what Guido
> meant, I assumed he was saying "p can only have one scope in the
> synthetic function: local or non-local, not both, and local is what I
> propose". For example, let's flesh out his example a bit more:
>
> p = 42
...
[Guido]
>> You should really read Tim's initial post in this thread, where he
>> explains his motivation.
[Nick]
> I did, and then I talked him out of it by pointing out how confusing it
> would be to have the binding semantics of "x := y" be context dependent.
Ya, that was an effective
[Tim]
>> ...
>> So long as I'm the only one looking at real-life use cases, mine is
>> the only evidence I care about ;-) I don't really care about
>> contrived examples, unless they illustrate that a proposal is
>> ill-defined, impossible to implement as intended, or likely to have
>> malignant
On 2018-05-10 11:05, Tim Peters wrote:
So long as I'm the only one looking at real-life use cases, mine is
the only evidence I care about ;-) I don't really care about
contrived examples, unless they illustrate that a proposal is
ill-defined, impossible to implement as intended, or likely to
Just a quickie - I'm out of time for now.
[Guido]
>> That's just one of several "don't do that" situations. *What will happen*
>> is perhaps hard to see at a glance, but it's perfectly well specified. Not
>> all legal code does something useful though, and in this case the obvious
>> advice
[Nick Coghlan ]
> How would you expect this to work in cases where the generator expression
> isn't immediately consumed? If "p" is nonlocal (or global) by default, then
> that opens up the opportunity for it to be rebound between generator steps.
> That gets especially
On 10 May 2018 at 23:22, Guido van Rossum wrote:
> On Thu, May 10, 2018 at 5:17 AM, Nick Coghlan wrote:
>
>> How would you expect this to work in cases where the generator expression
>> isn't immediately consumed? If "p" is nonlocal (or global) by default,
On Thu, May 10, 2018 at 5:17 AM, Nick Coghlan wrote:
> On 9 May 2018 at 03:06, Guido van Rossum wrote:
>
>> So the way I envision it is that *in the absence of a nonlocal or global
>> declaration in the containing scope*, := inside a comprehension or
On 9 May 2018 at 03:06, Guido van Rossum wrote:
> So the way I envision it is that *in the absence of a nonlocal or global
> declaration in the containing scope*, := inside a comprehension or genexpr
> causes the compiler to assign to a local in the containing scope, which is
>
On 9 May 2018 at 03:57, Tim Peters wrote:
> These all match my expectations. Some glosses:
>
> [Guido]
> > We should probably define what happens when you write [p := p for p in
> > range(10)]. I propose that this overwrites the loop control variable
> rather
> > than
...
[Guido]
>> We should probably define what happens when you write [p := p for p in
>> range(10)]. I propose that this overwrites the loop control variable rather
>> than creating a second p in the containing scope -- either way it's probably
>> a typo anyway.
[Jacco van Dorp
My apologies for something unclear in my previous mail - the second
block I quoted (the one without a name) originated from Guido, not
from Tim.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
> [Tim]
> {About binding the for loop variable}
Yeah, that binding is the one I attempted to refer to. So I did
understand you after all.
> We should probably define what happens when you write [p := p for p in
> range(10)]. I propose that this overwrites the loop control variable rather
> than
> Implementation details - even just partial sketches - are always
> "busy". Think of it this way instead: it's _currently_ the case that
> listcomps & genexps run in a scope S that's the same as the scope C
> that contains them, _except_ that names appearing as `for` targets are
> local to S.
[Guido]
>> So the way I envision it is that *in the absence of a nonlocal or global
>> declaration in the containing scope*, := inside a comprehension or genexpr
>> causes the compiler to assign to a local in the containing scope, which is
>> elevated to a cell (if it isn't already). If there is
On Tue, May 08, 2018 at 01:28:59PM -0400, Juancarlo Añez wrote:
> So the way I envision it is that *in the absence of a nonlocal or global
> > declaration in the containing scope*, := inside a comprehension or genexpr
> > causes the compiler to assign to a local in the containing scope, which is
>
These all match my expectations. Some glosses:
[Guido]
> So the way I envision it is that *in the absence of a nonlocal or global
> declaration in the containing scope*, := inside a comprehension or genexpr
> causes the compiler to assign to a local in the containing scope, which is
> elevated
So the way I envision it is that *in the absence of a nonlocal or global
> declaration in the containing scope*, := inside a comprehension or genexpr
> causes the compiler to assign to a local in the containing scope, which is
> elevated to a cell (if it isn't already). If there is an explicit
So the way I envision it is that *in the absence of a nonlocal or global
declaration in the containing scope*, := inside a comprehension or genexpr
causes the compiler to assign to a local in the containing scope, which is
elevated to a cell (if it isn't already). If there is an explicit nonlocal
[Tim]
>> (inside a synthetic function created to
>> implement a listcomp/genexp, names bound by "=" are local; names bound
>> by ":=" are nonlocal; names bound by both are "who cares?"-
>> compiler-time error would be fine by me, or the first person to show a
>> real use case wins).
[Jacco van
> [Tim]
> (inside a synthetic function created to
> implement a listcomp/genexp, names bound by "=" are local; names bound
> by ":=" are nonlocal; names bound by both are "who cares?"-
> compiler-time error would be fine by me, or the first person to show a
> real use case wins).
Wait, you can't
[Tim]
> ... The ":= is treated specially in comprehensions" idea is aimed
> more at them than at people who think invoking a synthetic
> anonymous lambda "is obvious".
It occurs to me that, while suggestive, this is an unhelpful way to
express it. It's not at all that the semantics of ":="
On Mon, May 07, 2018 at 10:38:09AM -0700, Guido van Rossum wrote:
> The only solution that makes sense to me is Steven's (2). (1) is what the
> PEP currently says and what Tim doesn't want; (3) has no precedent
> (function defaults don't really work like this) and just gets my hackles
> all up.
[Terry Reedy ]
> ...
> If I am understanding correctly, this would also let one *intentionally
> 'leak' (export) the last value of the loop variable when wanted.
>
> [math.log(xlast:=x) for x in it if x > 0]
> print(xlast)
Yup! You can do that today by emulating a nonlocal
On 5/7/2018 1:38 PM, Guido van Rossum wrote:
I am convinced by Tim's motivation. I hadn't thought of this use case
before -- I had mostly thought "local scope in a comprehension or
generator expression is the locals of the synthetic function". But Tim's
reasoning feels right.
The only
[Tim]
> While I don't have real use cases beyond that, given that much,
> "consistency" kicks in to suggest that:
>
> def f():
> [x := 42 for x in range(1)]
>
> makes `x` local to `f` despite that x wasn't bound elsewhere in f's body.
>
> def f():
> global x
> [x
[Tim]
>> In a different thread I noted that I sometimes want to write code like
>> this:
>>
>> while any(n % p == 0 for p in small_primes):
>> # divide p out - but what's p?
>>
>> But generator expressions hide the value of `p` that succeeded, so I
>> can't. `any()` and `all()`
[Guido]
> I am convinced by Tim's motivation. I hadn't thought of this use case before
> -- I had mostly thought "local scope in a comprehension or generator
> expression is the locals of the synthetic function". But Tim's reasoning
> feels right.
I'm trying very hard _not_ to reason. That is,
On 2018-05-06 18:32, Tim Peters wrote:
In a different thread I noted that I sometimes want to write code like this:
while any(n % p == 0 for p in small_primes):
# divide p out - but what's p?
But generator expressions hide the value of `p` that succeeded, so I
can't. `any()` and
I am convinced by Tim's motivation. I hadn't thought of this use case
before -- I had mostly thought "local scope in a comprehension or generator
expression is the locals of the synthetic function". But Tim's reasoning
feels right.
The only solution that makes sense to me is Steven's (2). (1) is
On Tue, May 8, 2018 at 12:26 AM, Steven D'Aprano wrote:
> Here's a sketch of how I think locals are currently handled:
>
> 1. When a function is compiled, the compiler does a pass over the
>source and determines which locals are needed.
>
> 2. The compiler builds an array
On Mon, May 07, 2018 at 10:38:51PM +1000, Chris Angelico wrote:
> On Mon, May 7, 2018 at 9:42 PM, Steven D'Aprano wrote:
[...]
> > (3) A compromise: binding assignments are scoped local to the
> > comprehension, but they are initialised from their surrounding scope.
[...]
>
On Mon, May 7, 2018 at 9:42 PM, Steven D'Aprano wrote:
> On Mon, May 07, 2018 at 12:48:53PM +1000, Chris Angelico wrote:
>> On Mon, May 7, 2018 at 12:34 PM, Tim Peters wrote:
>
>> > There's a difference, though: if `y` "leaks", BFD. Who cares? ;-)
>>
On Mon, May 07, 2018 at 12:48:53PM +1000, Chris Angelico wrote:
> On Mon, May 7, 2018 at 12:34 PM, Tim Peters wrote:
> > There's a difference, though: if `y` "leaks", BFD. Who cares? ;-)
> > If `y` remains inaccessible, there's no way around that.
>
> That's Steve
For what it's worth, i'm totally +1 on inline uses of global and nonlocal.
As a related improvement, i'd also like it if "global x = 5" would be
a legal statement. As a noob learning python, I was suprised to find
out I couldn't and had to split it on two lines.(aside from a 9-hour
course of C
[Tim]
>> I have a long history of arguing that magically created lexically
>> nested anonymous functions try too hard to behave exactly like
>> explicitly typed lexically nested functions, but that's the trendy
>> thing to do so I always lose ;-)
[Nick Coghlan ]
> You have the
[Tim]
>> There's a difference, though: if `y` "leaks", BFD. Who cares? ;-)
>> If `y` remains inaccessible, there's no way around that.
[Chris]
> That's Steve D'Aprano's view - why not just let them ALL leak? I don't
> like it though.
I didn't suggest that. I'm not suggesting changing _any_
On 7 May 2018 at 12:51, Nick Coghlan wrote:
> If any other form of comprehension level name binding does eventually get
> accepted, then inline scope declarations could similarly be used to hoist
> values out into the surrounding scope:
>
> rem = None
> while
On Mon, May 7, 2018 at 12:34 PM, Tim Peters wrote:
>> That's a fair point. But there is another equally valid use-case for
>> assignment expressions inside list comps:
>>
>> values = [y + 2 for x in iter if (y := f(x)) > 0]
>>
>> In this case, it's just as obvious that the
On 7 May 2018 at 11:32, Tim Peters wrote:
> I have a long history of arguing that magically created lexically
> nested anonymous functions try too hard to behave exactly like
> explicitly typed lexically nested functions, but that's the trendy
> thing to do so I always lose
[Tim]
>> In a different thread I noted that I sometimes want to write code like
>> this:
>> ...
>>while any(n % (thisp := p) == 0 for p in small_primes):
>>n //= thisp
>> ...
[Ryan Gonzalez ]
> Couldn't you just do:
>
> def first(it):
>return next(it, None)
>
>
On Sun, May 6, 2018 at 7:37 PM, Matt Arcidy wrote:
>> Personally, I'd still like to go back to := creating a statement-local
>> name, one that won't leak out of ANY statement. But the tide was
>> against that one, so I gave up on it.
>
> yes.
>
> I have some probably tangential
> Personally, I'd still like to go back to := creating a statement-local
> name, one that won't leak out of ANY statement. But the tide was
> against that one, so I gave up on it.
yes.
I have some probably tangential to bad arguments but I'm going to make
them anyways, because I think := makes
[Chris Angelico ]
> ...
> You're correct. The genexp is approximately equivalent to:
>
> def genexp():
> for p in small_primes:
> thisp = p
> yield n % thisp == 0
> while any(genexp()):
> n //= thisp
>
> With generator expressions, since they won't
On May 6, 2018 8:41:26 PM Tim Peters wrote:
In a different thread I noted that I sometimes want to write code like this:
while any(n % p == 0 for p in small_primes):
# divide p out - but what's p?
But generator expressions hide the value of `p` that
On Mon, May 7, 2018 at 11:32 AM, Tim Peters wrote:
> In a different thread I noted that I sometimes want to write code like this:
>
> while any(n % p == 0 for p in small_primes):
> # divide p out - but what's p?
>
> But generator expressions hide the value of `p`
In a different thread I noted that I sometimes want to write code like this:
while any(n % p == 0 for p in small_primes):
# divide p out - but what's p?
But generator expressions hide the value of `p` that succeeded, so I
can't. `any()` and `all()` can't address this themselves -
65 matches
Mail list logo