2 迭代器与生成器

来源:互联网 发布:拍拍贷 网络小贷拍照 编辑:程序博客网 时间:2024/05/16 19:53

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!0Calling __next__ method!1Calling __next__ method!2Calling __next__ method!3Calling __next__ method!4Calling __next__ method!# ---------------------第二种方法-----------------# 通过iter()函数将list, dict, str等iterable 变成 iterator from collections import Iteratorisinstance(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)>>> 1next(g)>>> 1next(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 requestsfrom collections import Iterator, Iterableclass 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 kfor 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.stepfor x in reversed(FloatRange(1.0, 4.0, 0.5)):    print x

这里写图片描述

from itertools import islicel = [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# -----输出--------56789#-----接着运行------for x in t:    print x# -----输出--------10111213141516171819

这里写图片描述

# -------使用zip函数--并行-----------from random import randintmath = [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 randintfrom itertools import chaine1 = [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 = 0for s in chain(e1, e2, e3, e4):    if s > 90:        count += 1print count
原创粉丝点击