But then can you use i after the loop? In Python you can use i after the loop, which can be useful (e.g. if you break out)
for i in range(10):
if condition(i):
break
else:
print("didn't break")
print("broke at", i)
It is also easy to "fix": ll = [lambda i=i: print(i) for i in range(5)]
This issue is always going to be an issue for Python because it doesn't have explicit variable declaration. In C++ you have the difference between for (int i = 0;; i++)
// and
int i;
for (i = 0;; i++)
while in Python there's no way to write 'declare i here so it will be scoped outside the loop', which if it existed would make the behaviour you desire a reasonable alternative. Python variables are always scoped to the surrounding function. for i in range(5):
if i % 2 == 0:
q = i
print(q) #=> 0 0 2 2 4
>Could just as easily be an expression that's reevaluated on each call.Not ideal but it is consistent with other parts of the language. This is just one of those things you need to learn and in practice isn't really an issue. The fact it's different from other languages is not a relevant concern at all. 'Being like JS' is not a virtue.
>Sorry, my phrasing was imprecise. It's not doing 'yield []', but an exhausted generator does behave like an empty generator. Maybe they could have made it so the first exhaustion raises StopIterator, and subsequent ones a different exception? Like reading from a closed channel.
Iteration is just calling __next__. It's useful to iterate over things more than once sometimes.
IMO, this:
y = iter(x)
for z in y:
do(z)
if condition(z):
break
for z in y:
do2(z)
is bit nicer than this: flag = False
for z in y:
if flag:
do(z)
if condition(z):
flag = True
else:
do2(z)
>Comparison ChainingIncredibly useful feature. I've never seen anyone write 'a < b == c' so this seems a bit artificial. I'd hardly describe it as a footgun.