Re:Anti-Patterns in Python Programming
by mbell on Wednesday July 09, 2014 @01:46PM
(#8011099)
The other scoping issue in python that always struck me as strange is that loop variables aren't scoped to the loop, they continue to exist after the loop completes. I can see the logic for this feature even if I don't agree with it, but what I really don't get is that the loop variables are not defined if you iterate over something that is empty:
I would expect i == None. That oddity makes it dangerous to use the feature unless you're really careful (e.g. using a for - else construct).
[ Parent
| on HN ]
Then there's for-else:
In [1]: for i in []:
...: pass
...: else:
...: print 'Else!'
...:
Else!
In [2]: for i in []:
...: break
...: else:
...: print 'Else!'
...:
Else!
In [3]: for i in range(2):
...: break
...: else:
...: print 'Else!'
...:
In [4]: for i in range(2):
...: pass
...: else:
...: print 'Else!'
...:
Else!
The syntax could be interpreted as: if len(l) == 0:
print "Else!"
else:
for i in l:
pass
The "catch cases where a `break` is triggered" case isn't common enough for this syntax feature to be encountered very often, leading to confusion when people come across it (though at least it's not a bug where a common use-case has weird behavior to new-comers).
Re:Anti-Patterns in Python Programming
by dragonwriter on Wednesday July 09, 2014 @07:12PM
(#8012731)
> but what I really don't get is that the loop variables are not defined if you iterate over something that is empty
if you conceptualize how a for-loop has to work as a while-loop using Python's iterator protocol (which is the only way the iterator protocol itself makes sense), it seems pretty intuitive.
That is, this:
for item in items:
...1
else:
...2
becomes, approximately: try:
while True:
__hidden_iter = items.iter()
try:
item = __hidden_iter.next()
except StopIteration:
raise __NormalLoopExit
...1
except __NormalLoopExit:
...2
If you have an empty loop, the first assignment doesn't complete (instead raising StopIteration in evaluating the right side, which raises the notional exception __NormalLoopExit, which invokes the else: clause, if any) so the variable never gets around to being created.