Nils Bruin
unread,Jan 17, 2011, 2:39:02 PM1/17/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to sage-flame
Another case where Python 2.*'s leaking of iteration parameters leads
to really counterintuitive results:
This more or less does the expected thing:
>>> [ (a,b) for a in range(10) for b in range(10) if a==b ]
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8,
8), (9, 9)]
Although there's a small catch. Even though the for ... if ...
construct binds variables that are used to the left of it, and hence
in the above you might expect "a" to be the "inner variable", it is
not:
>>> [ (a,b) for a in range(3) for b in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2,
2)]
as it turns out, "if"s can be freely intermingled with "for" clauses,
so we can also execute
>>> b
2
>>> [ (a,b) for a in range(10) if a==b for b in range(10) ]
[(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2,
8), (2, 9), (9, 0), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6),
(9, 7), (9, 8), (9, 9)]
>>> b
9
This problem happily goes away in Python 3, where the semantics are
the same as (and this already works in Python 2.*):
>>> list( (a,b) for a in range(10) for b in range(10) if a==b )
>>> list( (a,b) for a in range(3) for b in range(3) )
>>> list( (a,b) for a in range(10) if a==b for b in range(10) )
where the last happily produces an error, even if b is globally bound
already. That is actually slightly better than the still slightly
confusing
>>> b=2
>>> list(list ( (a,b) for b in range(10)) for a in range(10) if a==b)
[[(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2,
8), (2, 9)]]
(which is recognizable as bad programming style)