目录
列表生成式
生成器
1. 定义
2. 作用
3. 返回值
迭代器
1. 特点
2. 常见的迭代器
3. 可迭代对象
列表生成式
列表生成式即 List Comprehensions, 是 Python 内置的非常简单却强大的可以用来创建 list 的生成式.
例如:
- >>> [x * x for x in range(1, 11)]
- [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
生成器
1. 定义
一个函数调用时返回一个迭代器, 那这个函数就叫做生成器(generator), 如果函数中包含 yield 语法, 那这个函数就会变成生成器
2. 作用
这个 yield 的主要效果呢, 就是可以使函数中断, 并保存中断状态, 中断后, 代码可以继续往下执行, 过一段时间还可以再重新调用这个函数, 从上次 yield 的下一句开始执行.
另外, 还可通过 yield 实现在单线程的情况下实现并发运算的效果
例如 1 : 保存中断状态
- def cash_out(amount):
- while amount> 0:
- amount -= 1
- yield 1
- return "done"
- ATM = cash_out(5)
- try:
- print("取到钱 %s 万" % ATM.__next__())
- print("花掉花掉!")
- print("取到钱 %s 万" % ATM.__next__())
- print("取到钱 %s 万" % ATM.__next__())
- print("花掉花掉!")
- print("取到钱 %s 万" % ATM.__next__())
- print("取到钱 %s 万" % ATM.__next__())
- print("取到钱 %s 万" % ATM.__next__()) # 到这时钱就取没了, 再取就报错了
- print("取到钱 %s 万" % ATM.__next__())
- except StopIteration as e:
- print("%s" %e.value)
- # 输出结果
取到钱 1 万
花掉花掉!
取到钱 1 万
取到钱 1 万
花掉花掉!
取到钱 1 万
取到钱 1 万
done
例如 2: 单线程进行并发运算
- import time
- def consumer(name):
- print("%s 准备吃包子啦!" % name)
- while True:
- baozi = yield
- print("包子 [%s] 来了, 被 [%s] 吃了!" % (baozi, name))
- def producer(name):
- c = consumer('A')
- c2 = consumer('B')
- c.__next__()
- c2.__next__()
- print("老子开始准备做包子啦!")
- for i in range(10):
- time.sleep(1)
- print("做了 2 个包子!")
- c.send(i)
- c2.send(i)
- producer("alex")
3. 返回值
yield 是生成器返回值
return 返回值是 StopIterator 错误抛出的值
迭代器
1. 特点
访问者不需要关心迭代器内部的结构, 仅需通过 next()方法不断去取下一个内容
不能随机访问集合中的某个值 , 只能从头到尾依次访问
访问到一半时不能往回退
便于循环比较大的数据集合, 节省内存
- >>> a = iter([1,2,3,4,5])
- >>> a
- <list_iterator object at 0x101402630>
- >>> a.__next__()
- 1
- >>> a.__next__()
- 2
- >>> a.__next__()
- 3
- >>> a.__next__()
- 4
- >>> a.__next__()
- 5
- >>> a.__next__()
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- StopIteration
2. 常见的迭代器
- py3
- #range 使用了迭代器, 每次需要获取才调用函数
- >>> range(10)
- range(0, 10)
- # 文件读取的时候, read()和 readlines()将所有内容都读取到列表, 会占用大量内存
- # 使用迭代器, 一行行的读和操作, 性能更优
- f = open("1.txt")
- for i in f:
- print(i)
- py2
- >>> range(10)
- [0,1,2,3,4,5,6,7,8,9]
- >>> xrange(10)
- range(0, 10)
3. 可迭代对象
一类是集合数据类型, 如 list,tuple,dict,set,str 等;
一类是 generator, 包括生成器和带 yield 的 generator function.
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable.
- >>> from collections import Iterable
- >>> isinstance([], Iterable)
- True
- >>> isinstance({
- }, Iterable)
- True
- >>> isinstance('abc', Iterable)
- True
- >>> isinstance((x for x in range(10)), Iterable)
- True
- >>> isinstance(100, Iterable)
- False
为什么 list,dict,str 等数据类型不是 Iterator?
这是因为 Python 的 Iterator 对象表示的是一个数据流, Iterator 对象可以被 next()函数调用并不断返回下一个数据, 直到没有数据时抛出 StopIteration 错误. 可以把这个数据流看做是一个有序序列, 但我们却不能提前知道序列的长度, 只能不断通过 next()函数实现按需计算下一个数据, 所以 Iterator 的计算是惰性的, 只有在需要返回下一个数据时它才会计算.
Iterator 甚至可以表示一个无限大的数据流, 例如全体自然数. 而使用 list 是永远不可能存储全体自然数的.
把 list,dict,str 等 Iterable 变成 Iterator 可以使用 iter()函数:
- #list dict string 不是迭代器
- >>> from collections import Iterator
- >>> isinstance((x for x in range(10)), Iterator)
- True
- >>> isinstance([], Iterator)
- False
- >>> isinstance({
- }, Iterator)
- False
- >>> isinstance('abc', Iterator)
- False
- #list dict string 可以转换为迭代器
- >>> isinstance(iter([]), Iterator)
- True
- >>> isinstance(iter('abc'), Iterator)
- True
来源: http://www.bubuko.com/infodetail-3115693.html