This question already has answers here:
More Pythonic Way to Run a Process X Times [closed]
(5 answers)
Closed 7 months ago.
In Python you have two fine ways to repeat some action more than once. One of them is while loop and the other - for loop. So let's have a look on two simple pieces of code:
for i in range(n):
do_sth()
And the other:
i = 0
while i < n:
do_sth()
i += 1
My question is which of them is better. Of course, the first one, which is very common in documentation examples and various pieces of code you could find around the Internet, is much more elegant and shorter, but on the other hand it creates a completely useless list of integers just to loop over them. Isn't it a waste of memory, especially as far as big numbers of iterations are concerned?
So what do you think, which way is better?
but on the other hand it creates a completely useless list of integers just to loop over them. Isn't it a waste of memory, especially as far as big numbers of iterations are concerned?
That is what xrange(n) is for. It avoids creating a list of numbers, and instead just provides an iterator object.
In Python 3, xrange() was renamed to range() - if you want a list, you have to specifically request it via list(range(n)).
This is lighter weight than xrange (and the while loop) since it doesn't even need to create the int objects. It also works equally well in Python2 and Python3
from itertools import repeat
for i in repeat(None, 10):
do_sth()
python3 & python2
just use range():
for _ in range(n):
# do something n times exactly
The fundamental difference in most programming languages is that unless the unexpected happens a for loop will always repeat n times or until a break statement, (which may be conditional), is met then finish with a while loop it may repeat 0 times, 1, more or even forever, depending on a given condition which must be true at the start of each loop for it to execute and always false on exiting the loop, (for completeness a do ... while loop, (or repeat until), for languages that have it, always executes at least once and does not guarantee the condition on the first execution).
It is worth noting that in Python a for or while statement can have break, continue and else statements where:
break - terminates the loop
continue - moves on to the next time around the loop without executing following code this time around
else - is executed if the loop completed without any break statements being executed.
N.B. In the now unsupported Python 2 range produced a list of integers but you could use xrange to use an iterator. In Python 3 range returns an iterator.
So the answer to your question is 'it all depends on what you are trying to do'!
Related
So I am playing around in python and I thought:
"Is there a built in list or function that already has infinite numbers, if not how could I build one?"
I did some research and found...
Nothing
That is why I am here!
If you don't know what I mean it would be this but infinite:
b = [1,2,3,4,5,6,7,8,9]
etc;
If there is please tell me! Thank you!
Edit: Thank you!
You can define your own infinite list using a generator function without any module imports.
def infinite_list():
n = 1
while True:
yield n
n += 1
my_list = infinite_list()
Each time you want the next number call the next method:
next(my_list)
You can also iterate over it but it will, of course, be an infinite loop:
for elem in my_list:
//infinite loop
itertools.count produces an iterator over arbitrary, infinite numbers. It's not a sequence (you can't index it, you can only iterate each instance once), but you can keep going forever.
Actually running it to completion will take infinite time of course, so it's typically paired with something that limits it, e.g. itertools.islice, zip-ing with a finite iterable, etc.
from itertools import count
for i in count(1):
print(i)
its infinite though so it might take a while to run
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.
In C++ we can write an infinite for loop like for(;;). Is here any syntax like this to write an infinite for loop in Python?
Note : I know that if I write for i in range(a_very_big_value) then it may run infinity. I am searching a simple syntax like C++ or any other tricks to write infinite for loop in Python.
Python's for statement is a "for-each" loop (sort of like range-for in C++11 and later), not a C-style "for-computation" loop.
But notice that in C, for (;;) does the same thing as while (1). And Python's while loop is basically the same as C's with a few extra bells and whistles. And, in fact, the idiomatic way to loop forever is:1
while True:
If you really do want to write a for loop that goes forever, you need an iterable of infinite length. You can grab one out of the standard library:2
for _ in itertools.count():
… or write one yourself:
def forever():
while True:
yield None
for _ in forever():
But again, this isn't really that similar to for (;;), because it's a for-each loop.
1. while 1: used to be a common alternative. It's faster in older versions of Python, although not in current ones, and occasionally that mattered.
2. Of course the point of count isn't just going on forever, it's counting up numbers forever. For example, if enumerate didn't exist, you could write it as zip(itertools.count(), it).
Yes, it is possible.
With a while loop:
while True:
...
With a for loop (just for kicks):
from itertools import cycle
for _ in cycle(range(1)):
...
The cycle returns 1 indefinitely.
In either case, it's up to you to implement your loop logic in such a way that you terminate eventually. And lastly, if you want to implement an execute-until-___ loop, you should stick to while True, because that's the idiomatic way of doing it.
I found the answer from here and here
Using itertools.count:
import itertools
for i in itertools.count():
if there_is_a_reason_to_break(i):
break
In Python2 xrange() is limited to sys.maxint, which may be enough for most practical purposes:
import sys
for i in xrange(sys.maxint):
if there_is_a_reason_to_break(i):
break
In Python3, range() can go much higher, though not to infinity:
import sys
for i in range(sys.maxsize**10): # you could go even higher if you really want
if there_is_a_reason_to_break(i):
break
So it's probably best to use count()
It is also possible to achieve this by mutating the list you're iterating on, for example:
l = [1]
for x in l:
l.append(x + 1)
print(x)
Yes, here you are:
for i in __import__("itertools").count():
pass
The infinite iterator part was taken from this answer. If you really think about it though, a while loop looks way better.
while True:
pass
You can use:
while True:
# Do stuff here
for _ in iter(str, "forever"):
... pass
This may help. Because the iter() function creates an iterator that will call str() with no arguments for each call to its next() method[ This returns an empty string ]; if the value returned by str() is equal to the string "forever"(WHICH WILL NEVER HAPPEN AS "" != "forever"), StopIteration will be raised thus breaking the loop, otherwise the loop will continue running and this is the case for our loop.
REF: https://docs.python.org/3/library/functions.html?highlight=iter#iter
This code was written in Python 3. I am trying to find the 10001st prime number.
#10001st prime number
mylist=[]
def prime_index(n):
for i in range(99**99):
for x in range(2, int(i**1/2)):
if i % x == 0:
return False
return True
mylist.append(i)
n=int(n+1)
print(mylist[n])
break
prime_index(10001)
When I run, it says "list index out of range", referring to print(mylist[n]).
However I have been adding primes to the list along the way in the mylist.append(i). So can someone tell me what is the problem here because I do not understand what is going on. Is 99**99 too small? Or more subtle problem with code?
99**99 is not too small; if you actually print it, you're well beyond what you need (if you tried to run it out, you'd never finish, it's 657 bits of work). But your loop makes no sense; your inner loop will return either True or False immediately if it executes even once.
"Luckily" for you, it never executes even once. The first outer loop sets i to 0 the first time, so the inner loop doesn't run at all (side-note, you probably want i ** (1/2), not i ** 1 / 2; exponentiation has higher precedence than division). Because it doesn't run, you end up indexing into an empty list (and asking for index 10001 no less).
There are far too many problems in this code to address them all; look for other trial division prime finding code to get an idea of what it should look like.
The problem is that you try to print out the 10001st element as soon as you find (or not) the first prime. Also, note that you return from the routine without finding any prime number -- if you were to get that far. There is no way to reach the append statement.
You got to the print statement only because your first iteration has i = 0, so you don't enter the for loop at all.
Please follow the posting guidelines: take the time to research how to generate prime numbers. It can be much faster than you're doing, and will give you a nice, succinct bit of code to put into your program.