本节内容
- 迭代器&生成器
- 装饰器
- Json & pickle 数据序列化
一、生成器
1、列表生成式
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2、生成器
只有在调用时才会生成相应的数据,只有一个方法:__next__()方法。next(),也就是又next方法的
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
1 >>> L = [x * x for x in range(10)] 2 3 >>> L 4 5 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 6 7 >>> g = (x * x for x in range(10)) 8 9 >>> g 10 11 <generator object <genexpr> at 0x1022ef630>
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
1 >>> next(g) 2 3 >>> next(g) 4 5 >>> next(g) 6 7 >>> next(g) 8 9 >>> next(g) 10 11 >>> next(g) 12 13 >>> next(g) 14 15 >>> next(g) 16 17 >>> next(g) 18 19 >>> next(g) 20 21 >>> next(g) 22 23 Traceback (most recent call last): 24 25 File "<stdin>", line 1, in <module> 26 27 StopIteration
如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
普通函数:
1 1 def fib(max): 2 2 n,a,b = 0,0,1 3 3 while n<max: 4 4 print(b) 5 5 #yield b 6 6 a,b=b,a+b 7 7 n = n+1 8 8 return 'done' 9 9 t = fib(11) 10 10 print(t) 11 11 输出结果: 12 12 1 13 13 1 14 14 2 15 15 3 16 16 5 17 17 8 18 18 13 19 19 21 20 20 34 21 21 55 22 22 89 23 23 done 24 25 上面函数变成生成器,只需要把print(b)改为yield b就可以了: 26 27 28 def fib(max): 29 30 n,a,b = 0,0,1 31 32 while n<max: 33 34 #print(b) 35 36 yield b 37 38 a,b=b,a+b 39 40 n = n+1 41 42 return 'done' 43 44 t = fib(11) 45 46 print(t) 47 48 49 50 输出结果: 51 52 <generator object fib at 0x00000000010F59E8>