[ python ] 迭代器和生成器

 列表生成式

  列表生成式是 python 内置的很是简单却强大的能够用来建立list的生成式。python

有这样一个需求:
    l1 = [1,2,3,4,5,6,7,8,9]    循环每一个元素加1ide

l1 = [1,2,3,4,5,6,7,8,9]

# 使用列表生成式将列表中的各个元素加1
list_num = [x+1 for x in l1]	# 这里就是一个列表生成式
print(list_num)

 

列表生成式能够用一行语句代替循环生成上面的list函数

 

 迭代器

    迭代器表面上看是一个数据流对象或容器,当使用其中的数据时,每次从数据流中取出一个数据,直到数据被取完,并且数据不会被重复使用。
    从代码的角度来看,迭代器是实现了迭代器协议方法的对象和类。
    迭代器协议方法主要是两个:
        __iter__(): 该方法返回对象自己,它是for语言使用迭代器的要求,只要函数含有__iter__就能够说这个函数是可迭代的;
        __next__(): 该方法用于返回容器中下一个元素或数据。当容器中的数据用尽时,应该引起 StopIteration 异常一个类只要具备这两种方法,就能够称之为 迭代器,也能够说是可迭代的。spa

s1 = 'hello world'
print('__iter__' in dir(s1))
print('__next__' in dir(s1))

# 字符串s1包含 __iter__ 方法且不包含__next__方法,因此字符串 s1 只是一个可迭代的类型,并非一个迭代器

# 执行结果:
# True
# False
s1 = 'hello world'
s2 = s1.__iter__()  # 将可迭代类型转换为 迭代器 使用 __iter__()
print('__iter__' in dir(s2))
print('__next__' in dir(s2))

# 使用 __iter__()方法将 s1 字符串转换为迭代器,迭代器既有__iter__方法,又有 __next__方法
# 执行结果:
# True
# True

 

自定义一个迭代器必须知足:
    类中必需要定义 __iter__ 方法和 __next__方法code

# 自定义一个迭代器:

class My_iterator(object):
    def __init__(self, x, max):
        self.mul, self.x = x, x
        self.xmax = max

    def __iter__(self):
        return self

    def __next__(self):
        if self.x and self.x !=1:
            self.mul = self.mul + self.x
            if self.mul < self.xmax:
                return self.mul
            else:
                raise StopIteration

if __name__ == '__main__':
    myite1 = My_iterator(2, 100)
    for i in myite1:
        print(i)

 

迭代器必定是可迭代的, 可是可迭代的不必定是迭代器对象

 

 生成器

  使用生成器能够生成一个值的序列用于迭代,而且这个值的序列不是一次生成的,而是使用一个,再生成一个,可使得程序节约大量内存。
    生成器对象是经过yield关键字定义的函数对象,所以生成器也是一个函数。生成器用于生成一个值的序列,以便在迭代中使用。blog

 

自定义生成器:内存

def foo():
    print('1111')
    yield 1
    print('22222')
    yield 2

f = foo()
print('type f:', type(f))
print(f.__next__())
print(f.__next__())

# 执行结果:
# type f: <class 'generator'>
# 1111
# 1
# 22222
# 2

 

执行流程以下图:字符串

 

须要注意的是 yield 是生成器中的关键字,生成器在实例化的时候并不会当即执行,而是等待调用其__next__()方法以后才开始运行,当再次调用__next__()方法会在第一次yield返回值的最后开始执行,不断的调用__next__()方法,直到最终返回 StopIteration 异常为止。generator

 

 

 

实例1:移动平均值

# 移动平均值

def foo():
    '''
    sum 计算总和
    count 计算有几个数
    avg 平均数
    :yield: 返回计算出的平均数 
    '''
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg # 接收num,返回avg
        sum += num
        count += 1
        avg = sum / count


f = foo()
next(f)
ret = f.send(10)
print(ret)
ret = f.send(20)
print(ret)
ret = f.send(30)
print(ret)
ret = f.send(40)
print(ret)

# 执行结果:
# 10.0
# 15.0
# 20.0
# 25.0
移动平均值
相关文章
相关标签/搜索