python迭代器,生成器,列表生产式
Posted akiz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python迭代器,生成器,列表生产式相关的知识,希望对你有一定的参考价值。
列表生成式
列表生成式即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
以上是关于python迭代器,生成器,列表生产式的主要内容,如果未能解决你的问题,请参考以下文章
5.1.24 Python之列表生成式生成器可迭代对象与迭代器
python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)