生成式、生成器、迭代器、json、pickl

1. 列表生成式

什么是列表生成式?

列表生成式,是Python内置的一种极其强大的生成list的表达式。现有列表

data = [1,2,3,4,5,6] 我们需要将列表中的数据都加1,之后再把列表打印出来,其中可以用
enumerate实现,如下;
for index,i in enumerate(data)
    data[index] +=1
print(data)
res:[2, 3, 4, 5, 6, 7]这是不是看起来繁琐,还有一种版本可以更简洁
data= [i+1 for i in range(7)]
res:[2, 3, 4, 5, 6, 7]
这种看起来是不是简洁一些,这就是列表生成式。

2. 列表生成器

什么是列表生成器?边运算边生成,省空间,省内存

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,有时我们仅仅需要访问前面几个元素,而后面绝大多数元素占用的空间都白白浪费了。

so,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

1 data = [1,2,3,4,5,6]
2 # for index,i in enumerate(data):
3 #     data[index]+=1
4 # print(data)
5 
6 data = (i+1 if i >4 else i for i in data)
7 
8 print(data)#目前打印出data它是一个生成器
9 res:<generator object <genexpr> at 0x1013817d8>
View Code

有人要问,怎么才能打印出genrator中的元素呢?可以通过next()函数获得generator的下一个返回值

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4

 generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。请看如下代码:

 1 data = [1,2,3,4,5,6]
 2 # for index,i in enumerate(data):
 3 #     data[index]+=1
 4 # print(data)
 5 
 6 data = (i+1 if i >4 else i for i in data)
 7 print(next(data))
 8 print(next(data))
 9 print(next(data))
10 print(next(data))
11 print(next(data))
12 print(next(data))
13 print(next(data))
14 
15 res:/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/zhangyalei/untitled/The_Five/生成器.py
16 Traceback (most recent call last):
17 1
18   File "/Users/zhangyalei/untitled/The_Five/生成器.py", line 66, in <module>
19 2
20 3
21     print(next(data))
22 4
23 StopIteration
24 6
25 7
26 
27 Process finished with exit code 1
View Code

下面练习一下著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到

1, 1, 2, 3, 5, 8, 13, 21, 34,55,89,...

 def fb(num):

    conut = 0
a,b = 0,1
while conut < num:
tmp = a
a = b
b = a +tmp
print(a)
conut +=1
print("done...")
fb(10)#以下是结果

1
1
2
3
5
8
13
21
34
55
done...这就实现啦比较复杂的运算。现在我们把这变成一个生成器看下面代码

 1 def fb(num):
 2     conut = 0
 3     a,b = 0,1
 4     while conut < num:
 5         tmp = a
 6         a = b
 7         b = a +tmp
 8         #print(a)
 9         conut +=1
10         yield a#在没有加yield之前时这是一个函数,在加之后就是一个生成器了,在yield下面可以加return a ,return 是表明一个函数结束,but 加yield表示返回a不结束,返回给谁,谁在外面调用它就返回给谁;
11     print("done...")
12 fb(10)#生成了一个生成器对象,就是代表推导式准备好了,随时可以处理数据的意思
13 
14 l = fb(10)
15 #现在可以通过__next__()方法一直往下查,如下
16 l.__next__()
17 l.__next__()
18 print(l.__next__())#这是一个完整的生成器,
View Code

此时yield有两个好处;其中一个在上处体现,还有一个yield实现啦函数的中断,并且保存啦函数的中间执行状态

3.迭代器

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象

  在判断一组数据类型是否Iterable需要用到isinstance函数如下;

from collections import Iterable

>>> isinstance([],Iterable)

True

>>> isinstance({},Iterable)

True

>>> 

>>> isinstance('sb',Iterable)

True

>>> 

>>> 

>>> isinstance((s for s in range(10)),Iterable)

True

>>> 

>>> 

>>> isinstance(100,Iterable)

False

最后定义:可以被__next__()函数调用并且不断返回下一值的对象称为迭代器、Iterator

总结:可以用for循环的对象都是iterbale类型,可用__next__()函数的对象都是Iterator类型,集合数据类型,dict,list,str都是iterable对象,不是iterator,若想变成Iterator可以通过iter()函数变成Iterator。

4.json

#json现在有字典data
data ={
'name':'zhangyalei',
'age': 24,
'sex':'M',
'phone':13733208119
}
#现在想把它写到硬盘上所以现在创建一个文件data.txt
with open('data.txt','w') as F:
F.write(data)
F.close()
Now Error:TypeError: write() argument must be str, not dict硬盘只识别二进制,所以不认识str
we could try:
with open('data.txt','w') as F:
F.write(str(data))
F.close()
现在成功啦,在data.txt中有上面的那个字典信息啦,我们再打开

with open('data.txt','r') as f:
  data = f.read()
print(data['age'])
抛出异常:TypeError: string indices must be integers现在我们通过eval将data.txt转成dict
with open('data.txt','r') as f:
  data = eval(f.read())
print(data['age'])#Res 24;没有问题 把一个内存对象转换成字符串形式,就叫序列化;把一个字符串转换成内存对象就叫反序列化 为什么 要这么做? 序列化的作用是将内存中的数据持久化对象。


posted @ 2016-11-08 21:03  MiaoBrother  阅读(197)  评论(0)    收藏  举报