2 迭代器与生成器
程序员文章站
2024-02-21 14:23:52
...
iterable 可迭代对象
直接作用于for循环的对象统称为可迭代对象
如(一类是集合数据类型如list, tuple, dict, set, str等; 另一类是generator,包括生成器和带yield的generator function)
iterator 迭代器
顾名思义,迭代器就是用于迭代操作(for循环)的对象,它像列表一样可以迭代获取其中每一个元素,
任何实现了__next__方法(python2是next())的对象都可以称为迭代器。
即可以被next()函数调用并不断返回下一个值直到没有数据抛出StopIteration错误
python的Iterator对象表示的是一个数据流,可以把这个数据流看做成一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据是才会计算
# 实现迭代器
# 实现了__iter__方法的对象是可迭代的,实现了__next__()(python2中next())方法的对象是迭代器
# __iter__() 返回可迭代对象; __next__() 则返回每次调用 next() 或迭代时的元素;
# --------------------------------------------
class Container:
def __init__(self, start = 0, end = 0):
self.start = start
self.end = end
def __iter__(self):
print("I made this Iterator!")
return self
def __next__(self):
print("Calling __next__ method!")
if self.start < self.end:
i = self.start
self.start += 1
return i
else:
raise StopIteration()
c = Container(0, 5)
for i in c:
print(i)
# -----------输出-------------
I made this Iterator!
Calling __next__ method!
0
Calling __next__ method!
1
Calling __next__ method!
2
Calling __next__ method!
3
Calling __next__ method!
4
Calling __next__ method!
# ---------------------第二种方法-----------------
# 通过iter()函数将list, dict, str等iterable 变成 iterator
from collections import Iterator
isinstance(iter([1,2,3]), Iterator) ---> True
generator 生成器
一遍循环以便计算的机制,称为生成器
生成器都是iterator对象
生成器通过 yield 语句快速生成迭代器,省略了复杂的 __iter__() & __next__() 方式:
# 实现生成器
# 第一种方法 把一个列表生成式的[]改成()
g = (x for x in range(1, 3))
>>> <generator object <genexpr> at 0x0000020029E7FE60>
next(g)
>>> 1
next(g)
>>> 1
next(g)
>>> StopIteration:
# ---------使用在函数中yield语句
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n += 1
return 'done'
a = fib(10) # 返回的是一个生成器对象 通过next(a)调用
a
<generator object fib at 0x0000020029E7FE08>
python进阶笔记
import requests
from collections import Iterator, Iterable
class WeatherIterator(Iterator): # Iterator迭代器对象 重写next()
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): # Iterable可迭代对象 重写__iter__
def __init__(self, cities):
self.cities = cities
def __iter__(self):
print self.__class__.__name__
return WeatherIterator(self.cities)
# [u"北京", u"上海", u"广州", "长春"]
for x in WeatherIterable([u"北京", u"上海", u"广州", u"长春"]):
print x
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, 100):
print x
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 t <= self.end:
yield t
t += self.step
def __reversed__(self):
t = self.end
while t >= self.start:
yield t
t -= self.step
for x in reversed(FloatRange(1.0, 4.0, 0.5)):
print x
from itertools import islice
l = [x for x in xrange(20)]
t = iter(l)
# islice(t, 10) 到10
# islice(t, 10, None) 10到结尾
for x in islice(t, 5, 10): # islice会消耗迭代对象 接着t从10开始
print x
# -----输出--------
5
6
7
8
9
#-----接着运行------
for x in t:
print x
# -----输出--------
10
11
12
13
14
15
16
17
18
19
# -------使用zip函数--并行-----------
from random import randint
math = [randint(60, 100) for _ in xrange(40)]
english = [randint(60, 100) for _ in xrange(40)]
chinese = [randint(60, 100) for _ in xrange(40)]
total = []
for c, m, e in zip(chinese, math, english):
total.append(c + m + e)
print total
# -------------使用chain---串行--------
from random import randint
from itertools import chain
e1 = [randint(60, 100) for _ in xrange(39)]
e2 = [randint(60, 100) for _ in xrange(41)]
e3 = [randint(60, 100) for _ in xrange(40)]
e4 = [randint(60, 100) for _ in xrange(42)]
count = 0
for s in chain(e1, e2, e3, e4):
if s > 90:
count += 1
print count
上一篇: python-8-如何进行反向迭代以及如何实现反向迭代?
下一篇: 编程练习——杨辉三角
推荐阅读
-
2 迭代器与生成器
-
PHP设计模式漫谈之迭代器模式(2)_PHP教程
-
Python中 迭代( iteration )、迭代对象( iterable )、迭代器( iterator)、生成器(generator) 的关系详细讲解
-
python生成器generator和迭代器Iterator测试
-
python 生成器generator和迭代器Iterator
-
Python的迭代器(iterator)和生成器(generator)
-
Python学习:生成器(generator)和迭代器(iterator)
-
Python 迭代器(iterator)和生成器(generator)
-
Python中的生成器(generator)和迭代器(Iterator)
-
ES的迭代器Iterator和生成器Generator