Python iterator and generator example details
- 2020-06-01 10:15:14
- OfStack
Python iterator and generator example details
1. How to implement iterable objects and iterator objects
1. Get the iterator object from the iterable object
For example, l is an iterable object and iter(l) is an iterator object
In [1]: l = [1,2,3,4]
In [2]: l.__iter__
Out[2]: <method-wrapper '__iter__' of list object at 0x000000000426C7C8>
In [3]: t = iter(l)
In [4]: t.next()
Out[4]: 1
In [5]: t.next()
Out[5]: 2
In [6]: t.next()
Out[6]: 3
In [7]: t.next()
Out[7]: 4
In [8]: t.next()
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-8-3660e2a3d509> in <module>()
----> 1 t.next()
StopIteration:
for x in l :
print x
for The work flow of the cycle is first iter(l) get 1 a t And call it again and again t.nex(), To the end of the capture StopIteration , the iteration ends
The following method of directly calling a function can be adopted as an iterator if it will be more demanding on network IO when the data volume is large
def getWeather(city):
r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city='+city)
data = r.json()['data']['forecast'][0]
return '%s:%s,%s' %(city, data['low'], data['high'])
print getWeather(u' Beijing ')
The return value:
Beijing : The low temperature 13 ℃ , The high temperature 28 ℃
Implement 1 iterator object WeatherIterator,next method returns 1 city temperature at a time
Implement 1 iterable object WeatherIterable, and the iter method returns 1 iterator object
# -*- coding:utf-8 -*-
import requests
from collections import Iterable, Iterator
class WeatherIterator(Iterator):
def __init__(self, cities):
self.cities = cities
self.index = 0
def getWeather(self,city):
r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city='+city)
data = r.json()['data']['forecast'][0]
return '%s:%s,%s' %(city, data['low'], data['high'])
def next(self):
if self.index == len(self.cities):
raise StopIteration
city = self.cities[self.index]
self.index += 1
return self.getWeather(city)
class WeatherIterable(Iterable):
def __init__(self, cities):
self.cities = cities
def __iter__(self):
return WeatherIterator(self.cities)
for x in WeatherIterable([u' Beijing ',u' Shanghai ',u' Guangzhou ',u' shenzhen ']):
print x.encode('utf-8')
Output:
Beijing : The low temperature 13 ℃ , The high temperature 28 ℃
Shanghai : The low temperature 14 ℃ , The high temperature 22 ℃
Guangzhou : The low temperature 17 ℃ , The high temperature 23 ℃
shenzhen : The low temperature 18 ℃ , The high temperature 24 ℃
2. Implement iterable objects using generator functions
1. Implement a class of iterable objects, which can iterate all primes in a given range
A prime number is defined as a number of natural Numbers greater than 1 that have no factors other than 1 and itself.
A function with yield is an generator, which, unlike normal functions, generates an generator that looks like a function call, but does not execute any function code until it is called next() (which is automatically called next() in the for loop). Although the execution process is still executed as the function's process, each time an yield statement is executed, an iteration value is returned, and execution continues from the next statement of yield at the next execution. It looks as if a function was interrupted several times during normal execution by yield, each interrupt returning the current iteration value via yield.
class PrimeNumbers:
def __init__(self, start, end):
self.start = start
self.end = end
def isPrimeNum(self, k):
if k < 2:
return False
for i in xrange(2, k):
if k % i == 0:
return False
return True
def __iter__(self):
for k in xrange(self.start, self.end + 1):
if self.isPrimeNum(k):
yield k
for x in PrimeNumbers(1, 10):
print x
Output:
2
3
5
7
3. Realize reverse iteration
1. Iterate in reverse
For example, implement a floating point number generator FloatRange(similar to xrange), and generate a series of 1 consecutive floating point Numbers according to a given range (start, end) and step value (step). For example, iterative FloatRange (3.0,4.0,0.2) can produce a sequence:
Positive: 3.0 - > 3.2 - > 3.4 - > 3.6 - > 3.8 - > 4.0
Reverse: 4.0 - > 3.8 - > 3.6 - > 3.4 - > 3.2 - > 3.0
class FloatRange:
def __init__(self, start, end, step=0.1):
self.start = start
self.end = end
self.step = step
def __iter__(self):
t = self.start
while round(t,14) <= round(self.end, 14):
yield t
t = t + self.step
def __reversed__(self):
t = self.end
while round(t, 14) >= round(self.start, 14):
yield t
t = t - self.step
for x in reversed(FloatRange(3.0, 4.0, 0.2)):
print x
Output:
4.0
3.8
3.6
3.4
3.2
3.0
for x in FloatRange(3.0, 4.0, 0.2):
print x
Output:
3.0
3.2
3.4
3.6
3.8
4.0
The above code USES the round function because floating point comparisons have accuracy problems, so a 4 round 5 is required
2. Slice the iterator
For example, if you have a text file and want to read a certain range of contents, such as contents between 100 and 300 lines, python's Chinese version of this file is an iterable object, can you use a list-like slicer to get a generator of the contents of a 100-300 line file
Using itertools.islice in the standard library, it returns a generator that slices an iterated object
f = open('/var/log/dmesg')
from itertools import islice
# On file content 100 to 300 Slice between the rows and return a generator object. The default diameter is 1
islice(f, 100, 300)
# before 500 line
islice(f, 500)
# 100 The line ends at the end
islice(f, 100, None)
ps: Every time I use islice To reapply an object, it consumes the original iteration object
4. Iterate over multiple objects
1. Iterate over multiple iterable objects in one for statement
1. The Chinese, math and English test scores of a certain class are stored in three lists, and the three lists are iterated at the same time to calculate the total scores of the three students (in parallel).
2. There are 4 classes in a certain grade. The English scores of each class in a certain exam are stored in 4 lists.
Solutions:
Parallelism: USES the built-in function zip, which merges multiple iterable objects, returning one tuple per iteration
from random import randint
chinese = [randint(60,100) for _ in xrange(40)]
math = [randint(60,100) for _ in xrange(40)]
english = [randint(60,100) for _ in xrange(40)]
total = []
for c,m,e in zip(chinese, math,english):
total.append(c+m+e)
print total
Output:
[204, 227, 238, 201, 227, 205, 251, 274, 210, 242, 220, 239, 237, 207, 230, 267, 263, 240, 247, 249, 255, 268, 209, 270, 259, 251, 245, 262, 234, 221, 236, 250, 251, 249, 242, 255, 232, 272, 237, 253]
Serial: USES itertools.chain from the standard library to connect multiple iterable objects
from random import randint
from itertools import chain
class1 = [randint(60,100) for _ in xrange(40)]
class2 = [randint(60,100) for _ in xrange(42)]
class3 = [randint(60,100) for _ in xrange(39)]
class4 = [randint(60,100) for _ in xrange(43)]
count = 0
for s in chain(class1, class2, class3, class4):
if s > 90:
count = count + 1
print count
Output:
38
Thank you for reading, I hope to help you, thank you for your support of this site!