课程目标
- 列表生成式
- 生成器
- 迭代器
列表生成式
• Python内置的非常简单却强大的可以用来创建list的生成式
• 快速的把字典内容转变成list
>>> d = {
'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']
生成器
• 循环的过程中不断推算出后续的元素呢?这样就不必创建完整
的list,这种一边循环一边计算的机制,称为生成器:
generator
• 两种定义
- (列表生成式)
- 带yield的generator function
L = [x * x for x in range(10)]
print(L)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g = (x * x for x in range(10))
print(L)
<generator object at 0x1034dc667>
迭代器
• for循环可以应用下列类型:
- 集合数据类型,list,tuple,dict,set,str等
- generator ,生成器和带yield的generator function等 • 直接可作用于for循环的叫可迭代对象:Iterable
• 直接可作用于next方法的叫可以生成器对象:Iterator
• 生成器可以同时作用于for循环和next()函数,不断调用,
直到抛出StopIteration错误
d = {
'x': 'A', 'y': 'B', 'z': 'C' }
print([k+'=' + v for k,v in d.items()])
# 生成list,【1,2,3....10】
print(list(range(1,11)))
print([x*x for x in range(1,11)])
#'abc' ,'123' 输出a1a2a3,b1b2b3,c1c2c3
print([m+n for m in 'abc' for n in '123'])
# 把a.b.c的点进行筛除
print([m+n for m in 'a.b.c' for n in '123' if m!= '.'])
# 生成器
g = (x * x for x in range(10))
print(g)
#next 不知道有多少个元素
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
#yield
#斐波那契数列 1,1,2,3,5,8 后一个数等于前两个数的和
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a+b
n = n + 1
return 'done'
fib(6)
#输出关键字换成yield
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a+b
n = n + 1
return 'done'
g = fib(6)
print(next(g))
print(next(g))
print(next(g))
while True:
try:
x = next(g)
print(x)
except StopIteration as e:
print('没有数据了',e.value)
break
'''
迭代器
'''
#判断一个对象是否可迭代
# from collections import Iterable
# print(isinstance([],Iterable))
# print(isinstance({},Iterable))
# print(isinstance('abc',Iterable))
#判断一个对象是否是生成器 Iterator
# from collections import Iterator
# print(isinstance([],Iterator))
# print(isinstance({},Iterator))
# print(isinstance('abc',Iterator))
from collections.abc import Iterator
print(isinstance(iter([]),Iterator))
print(isinstance(iter({
}),Iterator))
print(isinstance(iter('abc'),Iterator))
# print(isinstance(iter(123),Iterator))
iter([])
``
作业
# 输出:
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]
n = 0
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 10:
break
if results == [
[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1],
]:
print('测试通过!')
else:
print('测试失败!')
想了很久都没想出来,看了一下别人的写法是:
```python
def triangles():
L=[1]
while True:
yield L
#这是一个生成器
L=[L[0]]+[L[t]+L[t+1] for t in range(len(L)-1)]+[L[-1]]
小结
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行