首页 > 编程 > Python > 正文

python迭代器、生成器、yield和xrange

2019-11-08 01:02:12
字体:
来源:转载
供稿:网友

1,迭代器:

支持next和__iter__方法的类,

其中next需要抛出StopIteration异常或返回迭代值,

__iter__需要返回迭代器自己,

也可以实现send函数,但要保证send函数调用next。

class MyIterator(object):    def __init__(self, step):       self.step = step     def next(self):        """Returns the next element."""        if self.step == 0:            raise StopIteration # 不抛出这个异常,for循环就不能捕获而已,那么for循环不能停止        self.step -= 1          # 没有return 就返回None        return self.step    def send(self,data):        return self.next()    def __iter__(self):        return self # Returns the iterator itselffor el in MyIterator(4):    PRint el

2,xrange:

xrange比迭代器高一个档次。a = xrange(5)返回一个xrange实例对象。

xrange实例对象只支持__iter__方法,不支持next。

xrange实例对象的__iter__方法返回一个迭代器。

所以迭代器是一次性用品,而xrange可以一直返回初始状态一样的迭代器,可以重复使用。

for循环,首先调用对象的__iter__方法得到迭代器,然后调用迭代器的next方法。

a = xrange(5) # xrange实例对象b = a.__iter__() # 迭代器对象c = a.__iter__() # 迭代器对象,xrange实例对象可以多次返回相同初始状态的迭代器print list(b)print list(b) # 为空,迭代器只能用一次print a[2],a[0] # xrange实例对象还支持切片来索引数据print list(a)print list(a) # 多次使用

3,yield和生成器:

yield:使用协程进行用户态上下文切换的技术。

生成器:使用yield技术,返回支持迭代器的next、__iter__和send接口的对象。

生成器是一直执行代码,直到遇到yeild,就返回结果值和接受输入值,

可以有多个yeild,不一定非得是循环,

只要没有yeild可以执行时,就抛出stopiterantion。

for只不过是有处理stopiterantion异常的代码而已。

a.next()和a.send(None) 作用是一样的,但第一次调用生成器时,请一定使用next()语句或是send(None)。

4,简单的例子:

from collections import Iterableisinstance('abc', Iterable) # str是否可迭代isinstance(123, Iterable) # 整数是否可迭代L = [x * x for x in range(10)] # 列表解析式print Lg = (x * x for x in range(10)) # 返回一个生成器print gdef fib(max):    '斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易'    n, a, b = 0, 0, 1    while n < max:        yield b        a, b = b, a + b        n = n + 1for i in fib(20):    print ifrom itertools import groupbydef compress(data):     return (  (len(list(group)), name) for name, group in groupby(data) )   # 返回一个生成器def decompress(data):    return (car * size for size, car in data) # 返回一个生成器list(compress('get uuuuuuuuuuuuuuuuuup'))compressed = compress('get uuuuuuuuuuuuuuuuuup')''.join(decompress(compressed))

5,两种方法实现计数器:闭包和生成器:

import numpy as npimport pandas as pdkey_small = ['one','two','one','two','one']df_small = pd.DataFrame(np.random.randn(5,3),index=['joe','steve','wes','jim','travis'],columns=['a','b','c'])gb_small = df_small.groupby(key_small)def f_wrapper():    '闭包计数器'    count = [0]    def f(obj):        count[0] += 1        print '/nSTART',count[0],'/n',obj,'/nEND',count[0],'/n'    return ff = f_wrapper()gb_small.agg(f)print '-----------------------------------------------------------'def f_counter():    '生成器计数器'    count = 0    while True:        a = yield count        count += 1        if count > 100:            breakcounter = f_counter() # '记住:当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。一定要调用,才能生成' def f(obj):    count = counter.next()    print '/nSTART',count,'/n',obj,'/nEND',count,'/n'            gb_small.agg(f)(如果有什么说的不对的地方,欢迎大家多多批评指正。)


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表