Why is for else allowed in python - python-3.x

I don't understand why this is allowed in python?
>>> for i in []:
... print(i)
... else:
... print('here')
...
here
should this not have else without if syntax error? The else operates every time too (if the for has iterated or not) so its not connected.
>>> for i in 1,2,3:
... print(i)
... else:
... print('here')
...
1
2
3
here

From the docs
* The else clause executes after the loop completes normally. This means that the loop did not encounter a break statement.*
So this is useful if you are doing a for loop but do not know if the element will be found in the loop/ returned true in the loop. So you can add a break statement to exit the loop if the element is found/true, or execute another command if it is not found/true. For example in your loop:
for i in []:
print(i)
else:
print('here')
Output
here
In this case, i was not found in your for loop. However you did not execute a break statement after the for loop. Because of that, the compiler then goes to the else statement to executes the line(s) there since the for loop did not break.
In the second example you have:
for i in 1,2,3:
print(i)
else:
print('here')
Output
1
2
3
here
The for loop did not encounter a break statement, so after the for loop is completed it will then execute the else clause. However it you were to use:
for i in 1,2,3:
print(i)
break
else:
print('here')
Output :
1

else is executed if we don't break from for.
This can be useful in situation and can help us by saving us from the effort of making flags.
Example:
if we want to execute some code if we don't break from for loop, then normally we would have to do
flag = 0
for i in [1,2,3]:
if condition:
flag = 1
break
if flag == 0:
do stuff
we can instead do
for i in [1,2,3]:
if condition:
break
else:
do stuff

You can think about it that: When the break statement is executed in the loop, the code inside the loop following the break statement will be ignored and the loop is finished
if the break statement is not executed, the code following the else statement will be executed after the loop is finished
Mateen Ulhaq and Lance Helsten gave a good example in here Why does python use 'else' after for and while loops?
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("List argument missing terminal flag.")
and
flagfound = False
for i in mylist:
if i == theflag:
flagfound = True
break
process(i)
if not flagfound:
raise ValueError("List argument missing terminal flag.")
I often use else statement to mark the last turn in for/while loop

Related

When breaking out of a nested loop, how do I make it so that the inner loop isn't ignored in Python?

In a nested loop, after breaking out of the inner loop and going to the top loop it skips the parameters of the inner loop. Why and how can I fix this?
for i in range(5):
for j in range(5):
if i == j:
print('Same Number')
break
This code only prints 'Same Number' once. When 1 = 1. I'm not sure why j never changes but i does.
The way you have it written right now, the inner loop will always break on the first iteration (when i = 0). This is why you are only seeing it print once, the outer loop is looping 5 times, however the inner loop only ever gets through the first iteration before hitting break.
See below, the break line should be nested inside the if statement so it only breaks from the inner loop when the two numbers match.
for i in range(5):
for j in range(5):
if i == j:
print('Same Number')
break

not sure why the output is 1 1, instead of 1123?

I took a quiz, the output for this following code is 1 1 instead of 1 1 2 3. And the explanitaion for this answer is that when the code encounter the break(when it reach 2) ,then loops stop.
I understand that the loops stop when it reach 2, but since print() has the same indentation as if() statement, I thought they are excuted seperately,
(but both still under for loop). So when number reaches 2, even if the loop stops, it will still execute the print(), for it is still under for loops. Hence, the result is the 1 1 2 3. And no matter what if() statement is, the result is the same.
numbers = [1, 1, 2, 3]
for number in numbers:
if number % 2 == 0:
break
print(number)
No, the commands are interpreted in order. When the if condition becomes true, the break exits the for loop before the print can execute. The first two loops the break is skipped since 1 % 2 == 0 is false, but 2 % 2 == 0 is true exiting the loop before getting to 3 which would also be true and print... if the loop hadn't already exited.
When the break statement executes the execution pointer goes to the next statement outside the loop, not the statement after the if block containing the break statement, so the print function is not called once break is executed as the execution is then outside the loop.

Why doesn't "break" stop this for loop?

for i in range(999*999):
if ispalindrome(999*999-i)==True and isprime(999*999-i) == False:
factors = listfactors(999*999-i)
for j in range(len(factors)):
if len(str(factors[j])) == 3 and len(str(int((999*999-i)/factors[j])))==3:
print(999*999-i)
quit()
This is my code. I want to check whether these conditions are true and then stop once I've found the first one, but it prints all of the numbers that fit the conditions in the console. My thinking was that it should stop when it's got the first number
EDIT: I tried using quit() instead of break, but this still doesn't work, which I don't understand. I did try it with two break statements, but that didn't work. I wonder whether I got the indentation wrong.
In order to quit a double loop, use a function instead and return from the function. A break only works for the innermost loop.
Exampe:
def whatever():
for i in range(999 * 999):
if ispalindrome(999 * 999 - i) and not isprime(999 * 999 - i):
factors = listfactors(999 * 999 - i)
for j in factors:
if len(str(j)) == 3 and len(str(int((999 * 999 - i) / j))) == 3:
return 999*999-i
print(whatever())
the function break will only go out of 1 level. An easier way to do what you want is to make it a function as stated by Hubert. If you really do not want to use a function, you could create another variable continue and set it to True and check if it is not True at every level and if so break, then set it to False once it finds the answer, this way when it is found it will exit each loop as continue is no longer True.
Hope it helps.
P.S. You should mark a tick by Hubert's answer since it is solving your problem.

Can Python evaluate a while loop after executing the code?

Other languages allow you to something like
Do
loop body
While conditions
This guarantees the loop runs at least once, and allows you to have user input determine the conditions inside the loop without having to initialize them first. Does Python support this type of loop?
Edit:
I'm not looking for a work around. I went with
quitstr = self._search_loop()
while quitstr != 'y':
quitstr = self._search_loop()
I am only asking whether or not Python supports post-execution loop evaluation
I am not sure what you are trying to do.But You can implement a do-while loop like this:
while True:
loop body
if break_condition:
break
or
loop body
while not break_condition:
loop body
An option for this situation is to set the while loop to True and do the condition checking at the end:
should_break = False
while True:
# do the loop body
# AND potentially do something that impacts the
# value of should_break
if X > Y:
should_break = True
if should_break == True:
break # This breaks out of the while loop
As long as should_break remains False, this code will:
Run at least once
Continue to run
But once the X > Y condition becomes True, the while loop will end.

changing the value of iterator of for loop at certain condition in python

Hello friend while learning python it came into my mind that is there any way by which we can directly jump to a particular value of iterator without iterating fro example
a=range(1.10) or (1,2,3,4,5,6,7,8,9)
for i in a
print ("value of i:",i)
if (certain condition)
#this condition will make iterator to directly jump on certain value of
#loop here say if currently i=2 and after this it will directly jump the
#the iteration value of i=8 bypassing the iterations from 3 to 7 and
#saving the cycles of CPU)
There is a solution, however it involves complicating your code somewhat.
It does not require an if function however it does require both while and try loops.
If you wish to change the numbers skipped then you simply change the for _ in range() statement.
This is the code:
a = [1,2,3,4,5,6,7,8,9,10]
at = iter(a)
while True:
try:
a_next = next(at)
print(a_next)
if a_next == 3:
for _ in range(4, 8):
a_next = next(at)
a_next = str(a_next)
print(a_next)
except StopIteration:
break
The iterator interface is based on the next method. Multiple next calls are necessary to advance in the iteration for more that one element. There is no shortcut.
If you iterate over sequences only, you may abandon the interator and write an old-fashioned C-like code that allows you to move the index:
a = [1,2,3,4,5,6,7,8,9,10]
a_len = len(a)
i = 0
while i < a_len:
print(a[i])
if i == 2:
i = 8
continue
i += 1

Resources