本节内容

  1. 迭代器&生成器
  2. 装饰器
  3. 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> 

创建Lg的区别仅在于最外层的[]()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>

相关文章: