Reputation: 61
what is the use of iterator in python ? instead of that we can loop right. Below is my code which calculates the time for both operations *
import time
start1 = time.time()
a=list(range(1,10000000))
myiter=iter(a)
while True:
try:
next(myiter)
except StopIteration:
break
end1 = time.time()
print(end1-start1)
print("-"*40)
start = time.time()
a=list(range(1,10000000))
for i in a:
pass
end = time.time()
print(end-start)
Output :
2.208195924758911
Upvotes: 0
Views: 1535
Reputation: 41
Short Answer
Here is an example of how you can improve your code with iterators:
// WITHOUT ITERATORS
hours_worked = 0
for event in events:
if event.is_billable():
hours_worked += event.duration
// WITH ITERATORS
// create an iterators with the duration of the billable event.
billable_times = (event.duration for event in events if event.is_billable())
hours_worked = sum(billable_times)
With the iterators we have named something that was unnamed before and we can now use the sum function. Naming things make our code more descriptive and more readable.
Learn more here: Python Basics: Iteration, Iterables, Iterators, and Looping
Long Answer
Python doesn't have the same for
loops as other programming languages. You probably know that in JavaScript a "for
loop" is written like this:
let myList = ["apple", "banana", "blueberry"];
for (let i = 0; i < myList.length; i += 1) {
print(myList[i])
}
And like you know this is the Python "for
loop":
myList = [1, 2, 3, 5, 7]
for n in myList:
print(n)
As you can see, in Python there is no index initializing, incrementing and checking. In Python, myList
is called an iterable it's everything you can loop over with a for loop.
Sequences are one type of iterable but with additional features like indexing, length and they can be sliced. For example: Strings, Tuples and Lists are iterables and sequences, but dictionaries are just iterables. (You can't do this with a dictionary myDict[1]
).
In Python, we cannot manually loop over every iterable by using indexes, it only works with sequences.
So how do Python "for
loops" work if they can use indexes? They user the power of Iterators. Iterators are the things that power iterables, you can get one from every iterable, it's what you are doing when with iter(a)
in your code.
You can think of iterators as Pez dispensers that cannot be reloaded. You can take Pez out, but once a Pez is removed it can't be put back, and once the dispenser is empty, it's useless.
Source: Loop better: A deeper look at iteration in Python: Article
So under the hood, in Python, a for loop is working something like this :
def for(iterable, action)
iterator = iter(iterable)
looping_finished = false
while not looping_finished:
try:
item = next(iterator)
except StopIteration:
looping_finished = true
else:
action(item)
But why do we care about iterators? Because in Python it's common to work with an iterator directly.
Here is a basic example of a Python generator
my+1Generator (n+1 for n in numbers)
Generators are iterators, it means that you can do this: next(my+1Generator)
and you can also loop over generators like this:
for n in my+1Generator:
print(n)
If you can loop over it, it's an iterable. So, generators are iterators but also iterables.
And, surprise, it's the same for all iterators. You can actually do this:
numbers = [1, 2, 3]
iterator1 = iter(numbers)
iterator2 = iter(iterator1)
print (iterator1 is iterator2) // Output: "True"
Iterators have no length and can't be indexed. For example: enumerate
, reverse
, zip
and map
are iterators in Python. And the most important things about iterators is their laziness. They delay their work until you ask for the next item.
You can create an iterator yourself. Here is an example:
class add1_all:
def __init__(self, numbers):
self.numbers = iter(numbers)
def __next__(self):
return next(self.numbers) + 1
def __iter__(self):
return self
but usually an iterator is made with a generator function:
def add1_all(numbers):
for n in numbers:
yield n+1
Those two code samples are equivalent and work the same way. yield
allows us to pause the execution of the add1_all
function until the next
function is called on it.
Here is an example of how you can improve your code with iterators:
// WITHOUT ITERATORS
hours_worked = 0
for event in events:
if event.is_billable():
hours_worked += event.duration
// WITH ITERATORS
// create an iterators with the duration of the billable event.
billable_times = (event.duration for event in events if event.is_billable())
hours_worked = sum(billable_times)
Sources:
Upvotes: 1