How can I limit iterations of a loop in Python?
How can I limit iterations of a loop in Python?
for index, item in enumerate(items):
print(item)
if index == limit:
break
Is there a shorter, idiomatic way to write the above? How?
Including the index
zip
stops on the shortest iterable of its arguments. (In contrast with the behavior of zip_longest
, which uses the longest iterable.)
range
can provide a limited iterable that we can pass to zip along with our primary iterable.
So we can pass a range
object (with its stop
argument) to zip
and use it like a limited enumerate.
zip(range(limit), items)
Using Python 3, zip
and range
return iterables, which pipeline the data instead of materializing the data in lists for intermediate steps.
for index, item in zip(range(limit), items):
print(index, item)
To get the same behavior in Python 2, just substitute xrange
for range
and itertools.izip
for zip
.
from itertools import izip
for index, item in izip(xrange(limit), items):
print(item)
If not requiring the index, itertools.islice
You can use itertools.islice
:
for item in itertools.islice(items, 0, stop):
print(item)
which doesn't require assigning to the index.
Composing enumerate(islice(items, stop))
to get the index
As Pablo Ruiz Ruiz points out, we can also compose islice with enumerate.
for index, item in enumerate(islice(items, limit)):
print(index, item)
Why isn't this built into
enumerate
?
Here's enumerate implemented in pure Python (with possible modifications to get the desired behavior in comments):
def enumerate(collection, start=0): # could add stop=None
i = start
it = iter(collection)
while 1: # could modify to `while i != stop:`
yield (i, next(it))
i += 1
The above would be less performant for those using enumerate already, because it would have to check whether it is time to stop every iteration. We can just check and use the old enumerate if don't get a stop argument:
_enumerate = enumerate
def enumerate(collection, start=0, stop=None):
if stop is not None:
return zip(range(start, stop), collection)
return _enumerate(collection, start)
This extra check would have a slight negligible performance impact.
As to why enumerate does not have a stop argument, this was originally proposed (see PEP 279):
This function was originally proposed with optional start
and stop arguments. GvR [Guido van Rossum] pointed out that the function call
enumerate(seqn, 4, 6)
had an alternate, plausible interpretation as
a slice that would return the fourth and fifth elements of the
sequence. To avoid the ambiguity, the optional arguments were
dropped even though it meant losing flexibility as a loop counter.
That flexibility was most important for the common case of
counting from one, as in:for linenum, line in enumerate(source,1): print linenum, line
So apparently start
was kept because it was very valuable, and stop
was dropped because it had fewer use-cases and contributed to confusion on the usage of the new function.
Avoid slicing with subscript notation
Another answer says:
Why not simply use
for item in items[:limit]: # or limit+1, depends
Here's a few downsides:
- It only works for iterables that accept slicing, thus it is more limited.
- If they do accept slicing, it usually creates a new data structure in memory, instead of iterating over the reference data structure, thus it wastes memory (All builtin objects make copies when sliced, but, for example, numpy arrays make a view when sliced).
- Unsliceable iterables would require the other kind of handling. If you switch to a lazy evaluation model, you'll have to change the code with slicing as well.
You should only use slicing with subscript notation when you understand the limitations and whether it makes a copy or a view.
Conclusion
I would presume that now the Python community knows the usage of enumerate, the confusion costs would be outweighed by the value of the argument.
Until that time, you can use:
for index, element in zip(range(limit), items):
...
or
for index, item in enumerate(islice(items, limit)):
...
or, if you don't need the index at all:
for element in islice(items, 0, limit):
...
And avoid slicing with subscript notation, unless you understand the limitations.
How to limit number of iterations from for loop
Use list slicing like [:5]
.
for event in jsonRequestSchedule['events'][:5]:
eventUrl = f"http://{dserviceIP}:{apiPort}/test/buses/{bus}/events/{event['id']}?session={sessionID}"
Python for loop looping time limit
import time
t_sleep = 0.2
for x in range(10):
print(x)
time.sleep(t_sleep)
this code would sleep for 0.2 secs for every iteration
How to set the maximum number of iterations in a loop?
You can keep a counter and a loop that enables you to iterate as many times:
while r.status_code != 200 and count < 3:
Like:
import requests, time
session = requests.Session()
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'}
count = 1
r = session.get('https://www.larousse.fr/conjugaison/anglais/abnegate/11338', headers = headers)
while r.status_code != 200 and count < 3:
time.sleep(2)
r = session.get(link, headers = headers)
count += 1
How to limit loop to specified number of iterations?
As you are calling the below-mentioned lines inside nested loop hence it will be called EPOCHS*DATASET_COUNTER times.
model.fit({'input' : train_data_X}, {'targets' : train_data_Y}, n_epoch = 1, validation_set=({'input': test_data_X}, {'targets': test_data_Y}), snapshot_step = 1000, show_metric=True, run_id=MODEL_NAME)
If you wish to run it only hundred times, please accumulate all your dataset in one and then call it outside the second loop (DATASET-COUNTER) and directly inside the first loop (EPOCH one).
Limit loop to N iterations per minute
It should be noted that this is not "hard real time" code. this will be off slightly because of OS scheduling and the like. That being said, unless you know that you need hard real time, this should suffice.
import time
limit = 5
starttime = time.time()
for i, item in enumerate(recvData):
if not i + 1 % limit:
sleeptime =starttime + 60 - time.time()
if sleeptime > 0:
time.sleep(sleeptime)
starttime = time.time()
#processing code
How to limit for loop to print first few element from list in python?
You can use slicing:
for i in x[:5]:
print i
This will get the first five elements of a list, which you then iterate through and print each item.
It's also not recommended to do for x in x:
, as you have just overwritten the list itself.
Finally, semi-colons aren't needed in python :).
Related Topics
How to Copy/Repeat an Array N Times into a New Array
Convert Tensorflow String to Python String
Cast String to Float Is Not Supported in Linear Model
Collect_List by Preserving Order Based on Another Variable
Using Continue in a Try and Except Inside While-Loop
In Python, How to Check If a String Only Contains Certain Characters
Write a Dictionary With Multiple Values to Store Data in Columns in the CSV File
Check Type: How to Check If Something Is a Rdd or a Dataframe
How to Print Numbers in a List That Are Less Than a Variable. Python
Unable to Install Psycopg2 (Pip Install Psycopg2)
Python - Get Last Element After Str.Split()
Get Current Url from Browser Using Python
Missing 1 Required Positional Argument - Issue
Increment Values in a List of Lists Starting from 1
Python - How to Fix "Valueerror: Not Enough Values to Unpack (Expected 2, Got 1)"