every time I am debugging a code that contains a for-loop e.g.
# When I debug this code
for i in range(3):
print(i)
I come to want to fix a variable and execute the code, such as
# I want to do this
i = 2
# for i in range(3):
print(i)
However, the above code results in an error because there is an unexpected indent. So I always have to unindent the lines inside the for-loop, which is repetitive work:
# But I have to do this
i = 2
# for i in range(3):
print(i)
Question
Are there any ways to leave the indentation unchanged while commenting out the for line?
Replace the for loop with a block statement that executes the contents unconditionally:
i = 2
# for i in range(3):
if 1: # Or if you prefer, if True:
print(i)
Now the indent is expected, but since if 1:/if True: execute unconditionally (in Python 3, on the CPython reference interpreter, both of them optimize out the if completely; it executes without any sort of test), it behaves identically to the manually dedented version.
Alternatively, without adding an i = 2 at all, you can make the for loop loop over a single constant value:
for i in [2]: # range(3): Old code
print(i)
to get the same effect. for i in (2,): (parens optional) would also work, but that trailing comma that one-tuples require messes a lot of people up, and as it happens, loops over lists of constant literals are optimized to loops over tuples of constant literals anyway, so no performance loss is incurred.
You can make the for loop iterate over a single-item tuple instead:
for i in 2,:
# for i in range(3):
print(i)
Related
who can say me:
What is the difference between writing code inside else or just after the loops?
for x in range(6):
print('hello')
print('bye')
or
for x in range(6):
print('hello')
else:
print('bye')
From for/else documentation:
The else clause executes after the loop completes normally. This means that the loop did not encounter a break statement.
This means that in your specific example there is no difference in using else or not.
In the second example you're using conditional statement, Whereas in the first scenario after the loop completes, It automatically executes the next line.
Basically your post is an example of getting same result with alternative solutions.
Though your first solution can be considered as valid practice comparing with second one.
Although I would suggest you to read this article before posting any questions on stack overflow.
I'm debugging some code in PyCharm by stepping through line-by-line. The code involves a long for-loop, but for debugging purposes, I don't need to iterate through the whole thing. Instead, I'd like to break out after a few iterations. I'm trying to figure out how to do so without modifying my code to have special debugging instructions.
Example for loop
indices = range(10000, 0, -1)
for i, val in enumerate(indices):
print(val) # I can tell that it's working after a few iterations
The first thing I tried was typing break in the debugging console when paused at the print(val) line. This resulted in a syntax error
SyntaxError: 'break' outside loop
I also thought about using the debugging console line to modify the variable that I am enumerating over. For example, entering
indices = []
This has no effect on the iterator. Apparently, the iterator has an independent copy of the variable.
In another language, Java for example, I would take advantage of the termination condition, but python loops don't have a termination condition. I could rewrite my for-loop as a while-loop so that it would have an explicit termination condition, but that would obfuscate the code.
The other option would be to add special debugging instructions. For example,
mode = 'debug'
indices = range(10000, 0, -1)
for i, val in enumerate(indices):
print(val) # I can tell that it's working after a few iterations
if mode == 'debug' and i % 10:
break
I dislike doing this because inevitably, one of these special instructions gets left in after debugging is finished and mucks everything up.
Do I have any other options to break out of the loop from the debug console or without modifying the code?
I dislike doing this because inevitably, one of these special instructions gets left in after debugging is finished and mucks everything up.
Python for loops just aren't designed to be changed during execution, besides hard coding break, return or throwing StopIteration. (You are debugging, so either change the range in the loops expression list, or let it run through). The reason being the advantages of straightforward simplicity outweigh exposing the for loop counter - see PEP 212.
def function():
while True:
...omission...(this function is repeated permanently)
i =0
while i < 4:
driver.execute_script("""window.open("URL")""")
driver.switch_to.window(driver.window_handles[-1])
time.sleep(1)
function()
time.sleep(1)
i += 1 #open new tab and run function.
it doesn't work because while true loop is repeated permanently. Is there any ways to run multiple functions together?
https://imgur.com/a/4SIVekS This picture shows what I want
According to your picture, what you want is to launch the function a set number of times (4?), and run those in parrallel.
On a single core, as is the normal behavior, straight up parallel processing is impossible. You need to access other cores and manage a decentralized processing. while is useless there. I'm worried the level of difficulty is over your current skills, but here we go.
The overall flow that you (probably, depends on the actual memory safety of your functions) need is:
- to create a thread pool with the set number of threads for the number of runs you want.
- indicate the function you need to run
- start them, making sure the start itself is non-blocking.
- ensure one functions's processing doesn't impact another's results. race conditions are a common problem.
- gather results, again, in a non-blocking way.
You can use several methods. I highly recommend you read up a lot on the following documentations.
Threading:
https://docs.python.org/3/library/threading.html
Multiprocessing:
https://docs.python.org/3/library/multiprocessing.html
I don't understand your question because I don't understand what your function is supposed to do.
while True:
will always create an infinite loop. "while" is a command that tells python to loop through the following block so long as the expression following it evaluates to True. True always evaluates to True.
It seems like you want to use a conditional, like you do in "while x < 4".
x < 4
...is an expression that evaluates to true when x is less than 4, and false if x is not less than 4. Everything below the line:
while x < 4:
will then run if x is less than 4, and when it's done running that code, it will go back and evaluate if x is less than 4 again, and if it is, run the code again. To include another while loop inside of that loop, that new loop also needs an expression to evaluate. If you want to evaluate the same expression, write it out:
while x < 4:
# do something
while x < 4:
#do more things
# do even more things
# change x at some point, or else you're in an infinite loop.
However, there's no reason to do that specifically, because you're already doing it. All of the code is only running when x < 4, so checking that condition again right there is redundant, and doing it in another loop doesn't make sense. If the inside loop is also incrementing x, then the outside loop won't loop and doesn't need to increment x.
Also, if you want a function to check a condition based on a variable outside the function, you'll want to pass things to that function.
I was experimenting with various ways of creating an infinite loop in Python (other than the usual while True), and came up with this idea:
x = {0: None}
for i in x:
del x[i]
x[i+1] = None # Value doesn't matter, so I set it to None
print(i)
On paper, I traced out the way this would infinitely loop:
I loop through the key's value in the dictionary
I delete that entry.
The current counter position in the loop + 1 will be the new key with value None which updates the dictionary.
I output the current counter.
This, in my head, should output the natural numbers in a sort of infinite loop fashion:
0
1
2
3
4
5
.
.
.
I thought this idea was clever, however when I run it on Python 3.6, it outputs:
0
1
2
3
4
Yes, it somehow stopped after 5 iterations. Clearly, there is no base condition or sentinel value in the code block of the loop, so why is Python only running this code 5 times?
There is no guarantee that you will iterate over all your dict entries if you mutate it in your loop. From the docs:
Iterating views while adding or deleting entries in the dictionary may
raise a RuntimeError or fail to iterate over all entries.
You could create an "enumerated" infinite loop similar to your initial attempt using itertools.count(). For example:
from itertools import count
for i in count():
print(i)
# don't run this without some mechanism to break the loop, i.e.
# if i == 10:
# break
# OUTPUT
# 0
# 1
# 2
# ...and so on
In this case, like #benvc wrote, this is not guaranteed to work. But in case you wonder why does it work in C-Python:
The C-Python implementation destroys the dict object after some inserts and copies it to a new space in memory. It does not care about deletions. So when this happens, the loop notices it and breaking with an exception.
Check out this link if you want to read more about this, and many other interesting python internals here.
https://github.com/satwikkansal/wtfpython#-modifying-a-dictionary-while-iterating-over-it
I just tested your code in python2 and python3
python3 output
0,1,2,3,4
python2
0,1,2,3,4,5,6,7
One thing comes to mind that could be going on. Either there is only a certain amount of memory being allocated in your dictionary when you create the first key value and when you delete the key value we do not allocate any memory or deallocate the memory you are just removing the value. Once all the allocated memory is used it exits. Because if you run without that del you will get this error
RuntimeError: dictionary changed size during iteration
So python creates enough memory for that key value and a few more and once it is used up theres no more memory allocated for your dictionary.
As many pointed out, modifying a datastructure during iteration with a for loop is not a good idea. The while loop though does allow that as it re-evaluates its loop condition at each iteration (I'm impressed nobody suggested that as alternative yet). One just has to find the right loop condition. Your script would have to become:
x = {0: None}
while x:
i, _ = x.popitem()
print(i)
# to avoid infinite loop while testing
# if i == 10:
# break
x[i+1] = None
In Python, a dictionary is falsy when it is empty (see docs), so the loop will only stop if at the beginning of an iteration x is empty.
Since the dictionary only has one key-value pair, popitem() should be enough to get that pair and remove it from the dictionary. As the next integer is added right after the dictionary is emptied, the loop condition will never be false when evaluated thereby resulting in an infinite loop.
This question already has answers here:
Is there a difference between "pass" and "continue" in a for loop in Python?
(13 answers)
Closed 5 years ago.
My test shows that both pass and continue can be used equivalently to construct a empty for-loop for test purpose. Are there any difference between them?
The pass keyword is a "no-operation" keyword. It does exactly nothing. It's often used as a placeholder for code which will be added later:
if response == "yes":
pass # add "yes" code later.
The continue keyword, on the other hand, is used to restart a loop at the control point, such as with:
for i in range(10):
if i % 2 == 0:
continue
print(i)
That loop will only output the odd numbers since continue returns to the loop control statement (for) for iterations where i is even.
Contrast that with the exact same code, but using pass in place of continue:
for i in range(10):
if i % 2 == 0:
pass
print(i)
That loop prints all the numbers in the range, since pass does not return to the loop control statement for even (or any) values of i. It simply drops through to the print statement.
In terms of an empty for loop, you're correct that they're functionally identical. You can use either of:
for i in range(10):
pass
for i in range(10):
continue
pass does nothing (no operation), while continue make control flow to continue to next cycle of the loop.
If the loop contains only a single statement, a pass or continue won't make any difference. But if there are multiple statements, then it matters:
for item in my_list:
pass
print(item) #This will be executed
for item in my_list:
continue
print(item) #won't be executed
Basically, the pass statement do nothing, while the continue statement will restart the loop.
But in your case:
for item in my_list:
pass
#Since there's nothing after pass, the loop is finished.
for item in my_list:
continue
#You're restarting the loop
There difference is not very visible.
Hope this helps!
continue means "skip to the end of the loop body". If it's a while loop, the loop continues on to the loop test; if it's a for loop, the loop continues on to the next element of whatever it's iterating over.
pass does absolutely nothing. It exists because you have to have something in the body of an empty block statement, and pass is more readable than executing 1 or None as a statement for that purpose.
This will lead to an infinite loop if you use continue:
i = 0
while i<1:
continue
i = i + 1
print i
because continue only goes to the next iteration. But pass will work for this case.
pass and continue both work, but may create infinite loops.
For example, the following code will create infinite loop.
i = 0
while i<100:
continue # replacing continue with pass still creates an infinite loop.
If you want to avoid this (perhaps you intend to modify i withe loop, but you haven't written the code yet), use break.