# Python迭代器与生成器

2017/05/02 14:27

## 一、如何实现可迭代对象和迭代器对象

### 1.由可迭代对象得到迭代器对象

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 循环的工作流程，就是先有iter(l)得到一个t，然后不停的调用t.nex(),到最后捕获到StopIteration，就结束迭代

# 下面这种直接调用函数的方法如果数据量大的时候会对网络IO要求比较高，可以采用迭代器的方法

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'北京')



# -*- 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'北京',u'上海',u'广州',u'深圳']):
print x.encode('utf-8')



## 二、使用生成器函数实现可迭代对象

### 1.实现一个可迭代对象的类，它能迭代出给定范围内所有素数

class PrimeNumbers:
def __init__(self, start, end):
self.start = start
self.end = end

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):
yield k

print x

2
3
5
7


## 三、实现反向迭代

### 1.反向进行迭代

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

4.0
3.8
3.6
3.4
3.2
3.0

for x in FloatRange(3.0, 4.0, 0.2):
print x

3.0
3.2
3.4
3.6
3.8
4.0



### 2.对迭代器进行切片操作

f = open('/var/log/dmesg')

from itertools import islice

# 对文件内容100到300行之间进行切片，返回的是个生成器对象，默认歩径是1
islice(f, 100, 300)

# 前500行内容
islice(f, 500)

# 100行到末尾结束内容
islice(f, 100, None)

ps: 每次使用islice要重新申请对象，它会消耗原来的迭代对象


##四、 迭代多个对象

### 1.在一个for语句中迭代多个可迭代对象

1、某班学生考试成绩语文、数学、英语分别存储在3个列表中，同时迭代三个列表，计算三个学生的总分（并行）

2、某年级四个班，某次考试每班英语成绩分别存储在4个列表中，依次迭代每个列表，统计全学年英语成绩高于90分人数（串行）

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

[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]


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

38


0 评论
33 收藏
0