生成器与迭代器

生成器与迭代器

一、生成器

1.列表推导式

列表推导式是Python内置的非常简单且强大的可以用来轻松创建列表的方法。它可以使用非常简单的语句利用其他列表创建新的列表。

例如,创建1到10的所有偶数的平方的列表:

list = [i*i for i in range(1,11) if i%2==0]
print(list)   #结果为:[4, 16, 36, 64, 100]

列表推导式的书写规则是,生成的元素放在语句前面,紧跟着的是for循环。

2.生成器表达式

列表一旦被创建,其包含的元素就实实在在地存在内存中,占据着内存空间,列表存放的是元素本身,而生成器存放的是算法,通过next()调用算法实时生成元素,因此生成器所占的内存空间很小。

将列表推导式的方括号[ ]改为小括号( )即可创建一个生成器,即:

list = [i*i for i in range(1,11) if i%2==0]     #列表表达式
print(list)      #打印列表表达式生成的新列表
list = (i*i for i in range(1,11) if i%2==0)     #生成器表达式
print(list)       #打印生成器
print(list.__next__())    #跟下面next()用法一样
print(next(list))             #生成元素

执行的结果为:

[4, 16, 36, 64, 100]
<generator object <genexpr> at 0x0000000000432CF0>
4
16

可以看到,列表list一旦被创建,内存中就存放所有元素,而生成器list的元素内容将随着next()函数的调用实时生成,直到最后没有元素可生成,抛出StopIteration错误。

3.生成器函数

生成器函数跟常规定义函数类型,只不过使用yield关键字返回结果而不是return关键字。即:

def test():
    yield 1  #相当于return
    yield 2
g = test()
print(g)
print(g.__next__())
print(g.__next__())

执行结果如下:

<generator object test at 0x0000000002432CF0>
1
2

生成器函数相比于普通函数的区别:

  • 生成器代码更简洁
  • 生成器内存占用极少
  • 运行方式不同

生成器函数总结:

  • 语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值。
  • 自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(for循环、sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生Stopiteration异常。
  • 状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行。

生成器注意事项:生成器只能遍历一次。

二、迭代器

能够用于for循环的对象均被称为可迭代对象。

(字符串、列表、元组、字典、集合、文件对象)这些都不是可迭代对象,只不过在for循环模式,调用他们内部的__iter__()方法,把他们变成了可迭代对象。即:

x='hello'
iter_test = x.__iter__()
print(iter_test)
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())

执行结果如下:

<str_iterator object at 0x0000000002191358>
h
e
l

在所有可以用于for循环的对象中,生成器还可以被next()函数不断调用并生成下一个值,直到抛出StopIteration错误表示无法继续为止。

像生成器这种可以被next()函数调用并不断生成下一个值的对象被称为迭代器。

posted @ 2019-07-15 16:56  流浪代码  阅读(155)  评论(0编辑  收藏  举报