s14_day03_集合/文件操作/with/字符编码转换/函数/函数参数组/局部变量/高阶函数

'''
以色列,每年看书64本每人
中国人均4本
《追风》这本书讲的在阿富汉
探探算法,根据你的喜好来判断
推荐书
《追风筝的人》
《白鹿原》
《林达看美国〉
'''

当你混得不错的时候

 

一、字符串操作

特性:不可修改 

字符串是不可以修改的,如果进行修改就变成了新的字符串

1).首字母大写

1 name = 'king'
2 print(id(name),name) #56320864 king
3 name1 = name.capitalize() #所有的字符串操作都会变成一个新的字符串
4 print(id(name1),name1)  #首字母大写 57415232 King
5 print(id(name),name) #10904544 king

2).首字母大写

1 name = 'KING xiaofei'
2 names = name.casefold()   #大写全部变小写
3 print(names) #king xiaofei

3).一个字符如果不够少位,然后用什么填充

1 name = 'a'
2 print(name.center(50,"-"))  #字符串a 不够50个用-来填充 ,输出 ------------------------a-------------------------

4).统计字符出现的次数

1 name = 'king xiaofei xiaoxiao'
2 name_count = name.count('xiao') #统计 xiao出现次数
3 print(name_count) #3

5).将字符串转码,python中字符串都是ascii 码,而到了python中默认的所有字符串都是unicode编码

1 name = '小飞哥'
2 print(type(name)) #<class 'str'>
3 str_to_bytes = name.encode('utf-8')  
4 print(str_to_bytes)  #将字符串编码成bytes格式  #b'\xe5\xb0\x8f\xe9\xa3\x9e\xe5\x93\xa5'
5 # 再将字节的转换为字符串
6 print(str_to_bytes.decode('utf-8').encode('gb2312')) #将字符串utf-8转换为gb2312
7 print(name.encode('gb2312')) #直接转换 b'\xd0\xa1\xb7\xc9\xb8\xe7'

6).判断字符串是否以 Li结尾

1 name = 'king aaaLi'
2 ret = name.endswith("Li")
3 print(ret) #True

7).将字符串中带有tab的用多少个空格来替换

1 name = 'Alex\tli\txiexie'
2 # "Alex\tLi".expandtabs(10) #输出'Alex      Li', 将\t转换成多长的空格 
3 ret = name.expandtabs(10)# 将字符串中有\t的转换为10个空格的字符串
4 print(ret) #Alex      li        xiexie 

 8).查找字符在字符串中的位置,返回该字符串的索引,如果不存在返回-1

1 name = 'king xiaofei'
2 ret = name.find('n')
3 print(ret) #2 位置在下标2
4 print(name.find('d')) #-1 这个不存在

二. 字典操作

字典一种key - value 的数据类型,使用就像我们上学用的字典,通过笔划、字母来查对应页的详细内容。
定义一个字典

1 d = {'king':'xiaofei','xixi':'喜喜'}
2 print(d['king']) #xiaofei 椐据键值的方式来取值

字典的常用操作

1 d = {'king':'xiaofei','xixi':'喜喜'}
2 print(d.keys()) #dict_keys(['king', 'xixi'])
3 print(d.items()) #dict_items([('king', 'xiaofei'), ('xixi', '喜喜')])
4 print(d.get('king')) #xiaofei 
5 print(d.get('abc')) #None abc的键值不存在
6 # print(d['abc'])  #KeyError: 'abc' 这个不存在

三. 集合操作

集合是一个无序的,不重复的数据组合,它的主要作用如下:

  • 去重,把一个列表变成集合,就自动去重了
  • 关系测试,测试两组数据之前的交集、差集、并集等关系
假定两个场景,两个班,一个LIUX,一个Python 需要计算是一共多少个人,但里面的人有部分的人是都报了名的假如两个班级需要统计出来两个班的人那些是报两个班的,需要统计出来

1).创建一个数值集合

第一种方式创建:

1 s = set([1,2,3,4,5])
2 print(type(s),s) #<class 'set'> #{1, 2, 3, 4, 5}

第二种方式创建:

1 list_1 = [1, 4, 5, 7, 3, 6, 7, 9]
2 list_2 = set(list_1)
3 print(list_2, type(list_2))
4 # {1, 3, 4, 5, 6, 7, 9} <class 'set'>  集合也是无序的

 2).快速去重

交集

1 list_11 = set([1, 4, 55, 68, 99, 10, 4, 10])
2 list_l2 = set([1, 2, 3, 5, 6, 7, 8, 9, 10])
3 a = list_11.intersection(list_l2)
4 print(a) #{1, 10}
5 print(id(list_11), id(list_l2))  # 59442400 59443720
6 print(id(list_11), list_11)  # 59442400 {1, 99, 4, 68, 10, 55}
7 print(id(a), a)  # 59443000 {1, 10}

并集

1 list_11 = set([1, 4, 55, 68, 99, 10, 4, 10])
2 list_l2 = set([1, 2, 3, 5, 6, 7, 8, 9, 10])
3 b = list_11.union(list_l2)
4 print(b)
5 # {1, 2, 99, 4, 68, 3, 5, 6, 7, 10, 8, 9, 55}

差集,两组数据中没有的 in list_1 but not in list_2

1 c = list_11.difference(list_l2)
2 print(c)
3 # {99, 4, 55, 68} list_l1 里面有,list_l2里面没有的
4 
5 print(list_l2.difference(list_11))  # {2, 3, 5, 6, 7, 8, 9}list_l2里面有的,list_l1里面没有的

子集

1 list_3 = set([1, 2, 3, 5, 9])
2 list_4 = set([1, 2, 5])
3 
4 print(list_4.issubset(list_3))  # list_4 是不是list_3的子集 true

父集

1 list_3 = set([1, 2, 3, 5, 9])
2 list_4 = set([1, 2, 5])
3 # list_3是不是list_4的父集
4 print(list_3.issuperset(list_3))  # true

对称差集(反向差集),相两个里面都有的去掉,取两个里面的孤立的

1 list_1_name = set([1, 2, 3, 5, 9, 10, 11])
2 list_2_name = set([2, 3, 5, 11])
3 print(list_1_name.intersection(list_2_name))
4 # {3, 2, 11, 5}

判断两个是不是没有交集

1 list1 = set([1, 3, 7])
2 list2 = set([5, 6, 8])
3 print(list1.isdisjoint(list2))  # True
4 
5 list1 = set([1, 3, 5, 7])
6 list2 = set([1, 3])
7 print(list1.isdisjoint(list2))  # False 两个存在交集

上面的交集,并集,差集,除了用函数的方式调用,还可以通过符号的方式来

 1 # 交集
 2 list1 = set([1, 3, 5, 7, 9, 11, 22])
 3 list2 = set([0, 2, 66, 4, 77, 9, 22])
 4 
 5 print(list1 & list2)  # {9, 22}
 6 
 7 # 并集
 8 # union
 9 print(list1 | list2)  # {0, 1, 2, 3, 66, 5, 4, 7, 9, 11, 77, 22}
10 
11 # 差集
12 # difference
13 print(list1 - list2)  # {1, 3, 5, 7, 11}
14 
15 # 对称差集(反向差集),相两个里面都有的去掉,取两个里面的孤立的
16 # intersection
17 print(list1 ^ list2)  # {0, 1, 2, 66, 4, 3, 5, 7, 11, 77}

集合中的增删改查

1、 集合的添加

1 t = set() #创建一个空集合
2 print(t, type(t), id(t))  # set() <class 'set'> 44567168 一个集合没有值的时候默认会显示类型
3 # 1)、添加一项
4 t.add('x')  # 添加一项
5 print(t, type(t), id(t))  # {'x'} <class 'set'> 44567168
6 
7 # 2)、添加多项
8 t.update([10, 2, 33, 55])
9 print(t, type(t), id(t))  # {33, 2, 'x', 10, 55} <class 'set'> 44567168

2、集合的删除

1).使用remove()可以删除一项,如果被删除的对象不存在就会报错

1 # 使用remove()可以删除一项,如果被删除的对象不存在就会报错
2 t = set([1, 3, 5, 7, 9, 7])
3 print(t)  # {1, 3, 5, 7, 9} 集合的数据是不会重复的
4 t.remove(5)
5 print(t)  # {1, 3, 7, 9}

2). discard

t = set([1, 3, 5, 7, 9, 7])
print(t.discard('f')) #删除元素f 但这个是不存在的,所以返回一个None

3).pop随机删

1 t = set([1, 3, 5, 7, 9, 7])
2 print(t.pop())  # 1 被删除的对象是1
3 print(t.pop())  # 3 被删除的对象是3

4).查询长度

1 s = set([1,3,5,69,88,105])
2 ret = len(s)
3 print(ret) #6s
4 # set 的长度

判断是不是在里面

# x in s
# 测试 x 是否是 x 的成员

# x not in s
# 测试 x 不是 s 的员成
s = set([1,3,5,69,88,105])
ret = 3 in s
print(ret) #True
print(66 not in s) #True

 

四. 文件操作

# 对文件的操作流程
# 1.打开,得到一个文件的句柄
# 2.操作
# 3.关闭文件

 02_data_yesterday文件内容

 1 Somehow, it seems the love I knew was always the most destructive kind
 2 不知为何,我经历的爱情总是最具毁灭性的的那种
 3 Yesterday when I was young
 4 昨日当我年少轻狂
 5 The taste of life was sweet
 6 生命的滋味是甜的
 7 As rain upon my tongue
 8 就如舌尖上的雨露
 9 I teased at life as if it were a foolish game
10 我戏弄生命 视其为愚蠢的游戏
11 The way the evening breeze
12 就如夜晚的微风
13 May tease the candle flame
14 逗弄蜡烛的火苗
15 The thousand dreams I dreamed
16 我曾千万次梦见
17 The splendid things I planned
18 那些我计划的绚丽蓝图
19 I always built to last on weak and shifting sand
20 但我总是将之建筑在易逝的流沙上
21 I lived by night and shunned the naked light of day
22 我夜夜笙歌 逃避白昼赤裸的阳光
23 And only now I see how the time ran away
24 事到如今我才看清岁月是如何匆匆流逝
25 Yesterday when I was young
26 昨日当我年少轻狂
27 So many lovely songs were waiting to be sung
28 有那么多甜美的曲儿等我歌唱
29 So many wild pleasures lay in store for me
30 有那么多肆意的快乐等我享受
31 And so much pain my eyes refused to see
32 还有那么多痛苦 我的双眼却视而不见
33 I ran so fast that time and youth at last ran out
34 我飞快地奔走 最终时光与青春消逝殆尽
35 I never stopped to think what life was all about
36 我从未停下脚步去思考生命的意义
37 And every conversation that I can now recall
38 如今回想起的所有对话
39 Concerned itself with me and nothing else at all
40 除了和我相关的 什么都记不得了
41 The game of love I played with arrogance and pride
42 我用自负和傲慢玩着爱情的游戏
43 And every flame I lit too quickly, quickly died
44 所有我点燃的火焰都熄灭得太快
45 The friends I made all somehow seemed to slip away
46 所有我交的朋友似乎都不知不觉地离开了
47 And only now I'm left alone to end the play, yeah
48 只剩我一个人在台上来结束这场闹剧
49 Oh, yesterday when I was young
50 噢 昨日当我年少轻狂
51 So many, many songs were waiting to be sung
52 有那么那么多甜美的曲儿等我歌唱
53 So many wild pleasures lay in store for me
54 有那么多肆意的快乐等我享受
55 And so much pain my eyes refused to see
56 还有那么多痛苦 我的双眼却视而不见
57 There are so many songs in me that won't be sung
58 我有太多歌曲永远不会被唱起
59 I feel the bitter taste of tears upon my tongue
60 我尝到了舌尖泪水的苦涩滋味
61 The time has come for me to pay for yesterday
62 终于到了付出代价的时间 为了昨日
63 When I was young
64 当我年少轻狂
View Code
1 data = open('02_data_yesterday').read()
2 # UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 106: illegal multibyte sequence
3 
4 # 这个提示需要指定一个编码,操作系统是中文的,默认的是GBK的方式打开,但是python默认的文件格式是utf-8,所以会出错的

# 我们可以一部到位的读取文件里面的内容,但是我们打开了以后只是读了内容并没有关闭文件,这个还存在内存中的
# 指定打开文件的编码格式
# data = open('02_data_yesterday',encoding='utf-8').read()
# print(data)

 上面的操作我们如果需要将文件打开以后还需要更多的操作就需要将打开的文件存起来,方便后面的操作

 

 1 f = open('02_data_yesterday',encoding='utf-8') #打开一个文件以utf-8的编码格式读取,得到一个打开文件的句柄f
 2 data1 = f.read() #读取文件里面所有的内容
 3 data2 = f.read() #这里再次读取内容这里面没有数据了
 4 
 5 print(data1)
 6 print("*"*30)
 7 print(data2)  #这里没有数据
 8 
 9 # 因为read()在读取的时候将内容全部读回来了
10 # 再读的话就读到文件最末尾再往后读就没有数据的了
11 # 在文件里同维护着一个文件指针的概念,每次打开就从最开始读

 

1 f = open("02_data_yesterday",'r',encoding='utf-8')
2 # 连续读3行数据
3 print(f.readline())#Somehow, it seems the love I knew was always the most destructive kind
4 print(f.readline())#不知为何,我经历的爱情总是最具毁灭性的的那种
5 print(f.readline())#Yesterday when I was young

上面的直接循环读3次效果是一样的

1 f = open("02_data_yesterday",'r',encoding='utf-8')
2 for i in range(3):
3     print(f.readline().strip())#读取一行,并去掉后面的换行与空格

radlines() 这个可以将内容读成一个列表格式

1 f = open("02_data_yesterday",'r',encoding='utf-8')
2 # print(f.readlines()) #这是将整个文件读成一个列表格式
3 
4 # 假如我们第10条不需要打印出来如何做到?
5 for line in f.readlines():
6     print(line.strip())

假如我们第10条不需要打印出来如何做到?

1 f = open("02_data_yesterday",'r',encoding='utf-8')
2 for index,line in enumerate(f.readlines()):
3     if index == 10: #如果index到10就跳过
4         continue
5     print(index,line.strip())
0 Somehow, it seems the love I knew was always the most destructive kind
1 不知为何,我经历的爱情总是最具毁灭性的的那种
2 Yesterday when I was young
3 昨日当我年少轻狂
4 The taste of life was sweet
5 生命的滋味是甜的
6 As rain upon my tongue
7 就如舌尖上的雨露
8 I teased at life as if it were a foolish game
9 我戏弄生命 视其为愚蠢的游戏
11 就如夜晚的微风
12 May tease the candle flame
13 逗弄蜡烛的火苗
14 The thousand dreams I dreamed
15 我曾千万次梦见
16 The splendid things I planned
17 那些我计划的绚丽蓝图
18 I always built to last on weak and shifting sand
19 但我总是将之建筑在易逝的流沙上
20 I lived by night and shunned the naked light of day
21 我夜夜笙歌 逃避白昼赤裸的阳光
22 And only now I see how the time ran away
23 事到如今我才看清岁月是如何匆匆流逝
24 Yesterday when I was young
25 昨日当我年少轻狂
26 So many lovely songs were waiting to be sung
27 有那么多甜美的曲儿等我歌唱
28 So many wild pleasures lay in store for me
29 有那么多肆意的快乐等我享受
30 And so much pain my eyes refused to see
31 还有那么多痛苦 我的双眼却视而不见
32 I ran so fast that time and youth at last ran out
33 我飞快地奔走 最终时光与青春消逝殆尽
34 I never stopped to think what life was all about
35 我从未停下脚步去思考生命的意义
36 And every conversation that I can now recall
37 如今回想起的所有对话
38 Concerned itself with me and nothing else at all
39 除了和我相关的 什么都记不得了
40 The game of love I played with arrogance and pride
41 我用自负和傲慢玩着爱情的游戏
42 And every flame I lit too quickly, quickly died
43 所有我点燃的火焰都熄灭得太快
44 The friends I made all somehow seemed to slip away
45 所有我交的朋友似乎都不知不觉地离开了
46 And only now I'm left alone to end the play, yeah
47 只剩我一个人在台上来结束这场闹剧
48 Oh, yesterday when I was young
49 噢 昨日当我年少轻狂
50 So many, many songs were waiting to be sung
51 有那么那么多甜美的曲儿等我歌唱
52 So many wild pleasures lay in store for me
53 有那么多肆意的快乐等我享受
54 And so much pain my eyes refused to see
55 还有那么多痛苦 我的双眼却视而不见
56 There are so many songs in me that won't be sung
57 我有太多歌曲永远不会被唱起
58 I feel the bitter taste of tears upon my tongue
59 我尝到了舌尖泪水的苦涩滋味
60 The time has come for me to pay for yesterday
61 终于到了付出代价的时间 为了昨日
62 When I was young
63 当我年少轻狂
[Finished in 0.2s]
View Code

假如一个文件有1G左右的话或者20G呢?实体机只有8G那就直接没办法运行了,如果用readlines()一次读进来直接死机了
我们就需要转变一种方式了,用高逼格的方式来实现!

# high bige ,这种方式内部实现的是一个迭代器的方式

1 f = open("02_data_yesterday",'r',encoding='utf-8')
2 # 这种方式是一行一行的读取的
3 count = 0
4 for line in f: #迭代器的方式读取
5     if count == 10:
6         count +=1
7         continue
8     print(count,line)
9     count+=1
0 Somehow, it seems the love I knew was always the most destructive kind

1 不知为何,我经历的爱情总是最具毁灭性的的那种

2 Yesterday when I was young

3 昨日当我年少轻狂

4 The taste of life was sweet

5 生命的滋味是甜的

6 As rain upon my tongue

7 就如舌尖上的雨露

8 I teased at life as if it were a foolish game

9 我戏弄生命 视其为愚蠢的游戏

11 就如夜晚的微风

12 May tease the candle flame

13 逗弄蜡烛的火苗

14 The thousand dreams I dreamed

15 我曾千万次梦见

16 The splendid things I planned

17 那些我计划的绚丽蓝图

18 I always built to last on weak and shifting sand

19 但我总是将之建筑在易逝的流沙上

20 I lived by night and shunned the naked light of day

21 我夜夜笙歌 逃避白昼赤裸的阳光

22 And only now I see how the time ran away

23 事到如今我才看清岁月是如何匆匆流逝

24 Yesterday when I was young

25 昨日当我年少轻狂

26 So many lovely songs were waiting to be sung

27 有那么多甜美的曲儿等我歌唱

28 So many wild pleasures lay in store for me

29 有那么多肆意的快乐等我享受

30 And so much pain my eyes refused to see

31 还有那么多痛苦 我的双眼却视而不见

32 I ran so fast that time and youth at last ran out

33 我飞快地奔走 最终时光与青春消逝殆尽

34 I never stopped to think what life was all about

35 我从未停下脚步去思考生命的意义

36 And every conversation that I can now recall

37 如今回想起的所有对话

38 Concerned itself with me and nothing else at all

39 除了和我相关的 什么都记不得了

40 The game of love I played with arrogance and pride

41 我用自负和傲慢玩着爱情的游戏

42 And every flame I lit too quickly, quickly died

43 所有我点燃的火焰都熄灭得太快

44 The friends I made all somehow seemed to slip away

45 所有我交的朋友似乎都不知不觉地离开了

46 And only now I'm left alone to end the play, yeah

47 只剩我一个人在台上来结束这场闹剧

48 Oh, yesterday when I was young

49 噢 昨日当我年少轻狂

50 So many, many songs were waiting to be sung

51 有那么那么多甜美的曲儿等我歌唱

52 So many wild pleasures lay in store for me

53 有那么多肆意的快乐等我享受

54 And so much pain my eyes refused to see

55 还有那么多痛苦 我的双眼却视而不见

56 There are so many songs in me that won't be sung

57 我有太多歌曲永远不会被唱起

58 I feel the bitter taste of tears upon my tongue

59 我尝到了舌尖泪水的苦涩滋味

60 The time has come for me to pay for yesterday

61 终于到了付出代价的时间 为了昨日

62 When I was young

63 当我年少轻狂
[Finished in 0.1s]
View Code

文件指针所在位置

 1 f = open("02_data_yesterday",'r',encoding='utf-8')
 2 print(f.tell()) # 0 当前指针所在位置 0代表当前文件指针位置在文件的最开始
 3 # data = f.readline() #这里读取一行
 4 data = f.read(71) #71这里指定要读取的位置长度为71
 5 print(len(data),data) #读取一行,长度是71,指针指向下一个位置
 6 print(f.tell()) #72 当前文件指针所在位置72
 7 
 8 # seek()设置进去
 9 f.seek(0)#设置回去的位置到文件的起始位置
10 print(f.tell()) # 0  当前位置为文件开始
11 print(f.readline()) #Somehow, it seems the love I knew was always the most destructive kind
12 
13 
14 
15 # f.encoding 显示这个文件的编码格式
16 print(f.encoding) #utf-8
17 
18 # f.buffer()
19 print(f.fileno()) #返回这个文件在内存的编号 #3
20 
21 print(f.seekable())#不是所有的文件都有移回去的,这个是判断是不是两进制文件
22 print(f.tell()) #72 当前
23 
24 print(f.readable())#判断文件是否可读 #True
25 
26 print(f.writable())#判断是否可写 #False
f.flush() #刷新文件,如写一个文件,我们以为写进去了,但可能会出现还在内存里面但没有写进去,因为内存有一个缓存buffer,当满了以后才刷新到文件中,如果没有满就不刷新状态的

编写一个小实例,进度条程序

1 import sys
2 import time
3 
4 for i in range(50):
5     sys.stdout.write('#') #写入#到显示器
6     sys.stdout.flush() #刷新缓存区
7     time.sleep(0.2) #每次等待0.2秒

f.close() #关闭文件

1 f = open('02_data_yesterday','r',encoding='utf-8')
2 f.readline()
3 f.close()

f.truncate() #截段文件,将文件截断成为指定的长度

1 # 文件里面内容写上:Somehow, it seems the love I knew was always the most destructive kind
2 f = open('02_data_yesterday_wb','a')  #Somehow, it seems the love I knew was always the most destructive kind
3 f.truncate(10) #这个记得一定要能写入的方式打开,不然操作不了 打开文件的时候要吧用a的方式打开
4 #Somehow, i 这个是截取以后10个字符

文件打开的方式

# r+ 读写方式

1 f = open("02_data_yesterday",'r+',encoding='utf-8') #读写,是先读里面的内容,然后写到文件最后面
2 # f = open("02_data_yesterday",'w+',encoding='utf-8') #写读,先创建一个文件然后再写入去
3 # f = open("02_data_yesterday",'a+',encoding='utf-8') #追加读写,将写文件最后面
4 # f = open("02_data_yesterday",'rb') #以二进制只读的方式打开
5 print(f.readline())
6 print(f.readline())
7 print(f.readline())
8 f.write("#####################") #这个将写在文件最后面
9 print(f.readline())

# 以二进制读写追加模式打开,这类的在网络传送的时候用到这种方式

1 f = open('02_data_yesterday','rb') #以只读的2进制方式打开
2 print(f.readline()) #b'Somehow, it seems the love I knew was always the most destructive kind\r\n'

以2进制写的方式打开

1 f = open("02_data_yesterday_wb",'wb')
2 # f.write("小飞哥")  #TypeError: a bytes-like object is required, not 'str'
3 f.write("小飞哥".encode())  #转换为2进制,默认不写就是utf-8编码

写两个小实例,一个进度条,一个文件指针的移动

一、 进度条

1 import sys
2 import time
3 for i in range(50): #循环50次
4     sys.stdout.write('#') #写入#到显示器
5     sys.stdout.flush() #刷新缓存区
6     time.sleep(0.2) #每次等待0.2秒

二、一个文件指针的位置移动

1 f = open("02_data_yesterday",'r+',encoding='utf-8')
2 print(f.tell()) #0 当前位置是0
3 print(f.readline(),f.tell()) # 72
4 print(f.readline(),f.tell()) #140
5 print(f.readline(),f.tell()) #168
6 f.seek(0) #将文件指引移动到文件开始 0
7 print(f.readline(),f.tell())  #72

总结:文件加载,与文件的修改,所有文件的修改都是全新的存储,不可能局部的修改的

# 三、旅行者1号探测器,人的渺小地球的渺小
# 1.多看书,多看电影,多旅行让你的人生见识多了,产生文化冲突,会引法自己的思考
# 人的痛苦源于对自己无能的愤怒!!!
# 落日,西港的海滩

with 打开文件with可以自动关闭文件,不需要调用文件的f.close()

with语句的使用,with的作用是自动帮你关闭文件
# 1)、单个文件的打开
    # with open('log1','rb') as file1 ,open('log2') as file2:
    #     pass

# python建议每一行的代码不要超过80个字符,长了可以用\分行写

1)、打开单个文件

1 with open('02_data_yesterday','r',encoding='utf-8') as f:
2     for line in f:
3         print(line.strip())

2)、打开多个文件,官方建议每一行python代码不要超过80个字符 长了可以用\分行

1 with open('02_data_yesterday','rb') as file1 ,\
2 open('02_data_yesterday_wb','rb') as file2:
3     print(file1.readline(),file2.readline())

五. 字符编码与转码

先说python2

  1. py2里默认编码是ascii
  2. 文件开头那个编码声明是告诉解释这个代码的程序 以什么编码格式 把这段代码读入到内存,因为到了内存里,这段代码其实是以bytes二进制格式存的,不过即使是2进制流,也可以按不同的编码格式转成2进制流,你懂么?
  3. 如果在文件头声明了#_*_coding:utf-8*_,就可以写中文了, 不声明的话,python在处理这段代码时按ascii,显然会出错, 加了这个声明后,里面的代码就全是utf-8格式了
  4. 在有#_*_coding:utf-8*_的情况下,你在声明变量如果写成name=u"大保健",那这个字符就是unicode格式,不加这个u,那你声明的字符串就是utf-8格式
  5. utf-8 to gbk怎么转,utf8先decode成unicode,再encode成gbk

再说python3

  1. py3里默认文件编码就是utf-8,所以可以直接写中文,也不需要文件头声明编码了,干的漂亮
  2. 你声明的变量默认是unicode编码,不是utf-8, 因为默认即是unicode了(不像在py2里,你想直接声明成unicode还得在变量前加个u), 此时你想转成gbk的话,直接your_str.encode("gbk")即可以
  3. 但py3里,你在your_str.encode("gbk")时,感觉好像还加了一个动作,就是就是encode的数据变成了bytes里,我擦,这是怎么个情况,因为在py3里,str and bytes做了明确的区分,你可以理解为bytes就是2进制流,你会说,我看到的不是010101这样的2进制呀, 那是因为python为了让你能对数据进行操作而在内存级别又帮你做了一层封装,否则让你直接看到一堆2进制,你能看出哪个字符对应哪段2进制么?什么?自己换算,得了吧,你连超过2位数的数字加减运算都费劲,还还是省省心吧。  
  4. 那你说,在py2里好像也有bytes呀,是的,不过py2里的bytes只是对str做了个别名(python2里的str就是bytes, py3里的str是unicode),没有像py3一样给你显示的多出来一层封装,但其实其内部还是封装了的。 这么讲吧, 无论是2还是三, 从硬盘到内存,数据格式都是 010101二进制到-->b'\xe4\xbd\xa0\xe5\xa5\xbd' bytes类型-->按照指定编码转成你能看懂的文字

编码应用比较多的场景应该是爬虫了,互联网上很多网站用的编码格式很杂,虽然整体趋向都变成utf-8,但现在还是很杂,所以爬网页时就需要你进行各种编码的转换,不过生活正在变美好,期待一个不需要转码的世界。

最后,编码is a piece of fucking shit, noboby likes it.

python3默认是unicode(万国码)编码,如果需要将字符编码的转换就应该先将所有的编码转换为中间的unicode然后再转成自己想要的编码格式

# 每个国家都有自己的编码格式,所以就出来了unicode,这个所有的字符都是存两个字符
# utf-8 可变长的字符编码,所有的英文占一个字节,但是所有的中文是3个字节
# 编码的原则记得一定要先将所有的当前编码转换为unicode,然后再通过已转的unicode转换为自己想要的编码格式

1 #-*- coding:utf-8 -*-
2 s = "你好"
3 s_to_gbk = s.encode('gbk')
4 print(s_to_gbk) #b'\xc4\xe3\xba\xc3'

打印当前系统的默认编码格式

1 import sys
2 print(sys.getdefaultencoding())  #utf-8

python3中的来回转换编码

1 s = "你好" #python中默认是unicode
2 # s_to_gbk = s.decode("utf-8").encode('gbk') #告诉这个s是utf-8 的编码,转成unicode,然后再转成gbk
3 s_to_unicode = s.decode('utf-8')#告诉系统将上面的s转换为unicode,他的编码是utf-8,不写就是系统编码
4 print(s_to_unicode,type(s_to_unicode))

python3中,所有的变量字符串这些都是 Unicode编码,就算是设置了也只是文件的编码,但内部默认还是Unicode编码的

1 s = "你好" #这个在python3默认就是Unicode的编码
2 print(s.encode('gbk'))  #b'\xc4\xe3\xba\xc3'
3 s_utf8 = s.encode("utf-8")
4 print(s_utf8) #b'\xe4\xbd\xa0\xe5\xa5\xbd'
5 print(s_utf8.decode('utf-8').encode("gb2312")) #b'\xc4\xe3\xba\xc3'
6 # 这句话的意思是告诉当前是utf-8的编码转成gb2312

python2小练习

 1 #-*-coding:gb2312 -*-   #这个也可以去掉
 2 # 练习,在python2里面将所有的gb2312转换为utf-8,然后再将gb2312转换为gbk
 3 
 4 # 打印当前系统的默认编码格式
 5 # import sys
 6 # print(sys.getdefaultencoding())  #pytnon 2 中默认是 ascii
 7 
 8 import sys
 9 print(sys.getdefaultencoding()) #pytnon 2 中默认是 ascii
10 
11 msg = "我爱北京天安门"
12 #msg_gb2312 = msg.decode("utf-8").encode("gb2312")
13 msg_gb2312 = msg.encode("gb2312") #默认就是unicode,不用再decode,喜大普奔
14 gb2312_to_unicode = msg_gb2312.decode("gb2312")
15 gb2312_to_utf8 = msg_gb2312.decode("gb2312").encode("utf-8")
16 
17 print(msg)
18 print(msg_gb2312)
19 print(gb2312_to_unicode)
20 print(gb2312_to_utf8)

六. 函数

函数是什么?

函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

特性:

  1. 减少重复代码
  2. 使程序变的可扩展
  3. 使程序变得易维护

语法定义

定义一个函数

1 def func1():
2     '''第一个函数testing1'''
3     print('int the func1')
4     return 0

定义了一个过程,没有返回值的函数,所以叫一个过程

1 def func2():
2     '''testing 2'''
3     print("in the func2")

函数的返回,可以返回多个值

def func3():
    '''testing 3'''
    print("int the func3")
    return 1,"hello",['name','name2'],{'age',30}

调用上面的三个函数

1 x = func1() #int the func1
2 y = func2() #in ther func2
3 z = func3()
4 print(x) #返回的是0
5 print(y) #返回的是None  过程
6 print(z) #(1, 'hello', ['name', 'name2'], {'age', 30}) 返回的是一个元组

总结:
返回值数=0:返回的是None
返回值数=1:返回的是一个Object
返回值数>1:返回的是tuple

为什么要有返回值?

根据执行结果来执行不同的操作

2.函数参数与局部变量

带参数的函数

1 def test(x,y):  #这里的x,y是形参
2     print(x)
3     print(y)
4 
5 # test() #TypeError: test() missing 2 required positional arguments: 'x' and 'y'
6 # 调用函数的时候缺少参数
7 
8 test(2,3) #这里传入的是实参
9 #实参与形参是完全一一对应的

默认参数

 1 def test(x,y=2):  #这里的x,y默认值是2
 2     print(x)
 3     print(y)
 4 
 5 # test() #TypeError: test() missing 2 required positional arguments: 'x' and 'y'
 6 # 缺少参数
 7 
 8 test(2,3) #2 3 这里传入的是实参,传入的时候可以少传入一个
 9 test(333)  #333 2
10 # 默认参数,可以省略带有默认值的参数

指定关键字的方式传入参数,与位置调用方式

1 def test(x,y):
2     print(x)
3     print(y)
4 
5 test(y=30,x=20)# 关键字方式调用,与形参顺序无关,指定名字的方式传入参数 20 ,30 还是这样子传入的
6 
7 x = 1
8 y = 2
9 test(x=x,y=y) #注意这里是两种不同的方式,后面的是实参。前面的形参 1,2

1.形参和实参:
形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是函数调用时接收实参(实参个数,类型就与实参一一对应)

实参:实际参数,调用函数时传给函数的参数,可以是变量,表达式,函数,传给形参

区别:形参是虚拟的,不占用空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,不参形参传给实参

2.位置参数和关键字(标准调用,实参与形参位置一一对应,关键字调用:位置无需固定)

3.默认参数,可以省略带有默认值的参数
默认参数的特点:调用函数的时候,默认参数非必须传递

参数组:若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数

可变长度的参数

1 # *args接收N个元组参数
2 def test1(*args):
3     print(args)
4 test1(1,2,3,3,5) #传入的是一个元组 (1, 2, 3, 3, 5)
5 test1(*[1,2,3,45,66]) #args = tuple(1, 2, 3, 45, 66)

可变长度的参数,可以与实参合用

1 def test2(x,*args):
2     print(x)
3     print(args)
4 
5 test2(1,2,3,4,5,6,68)  #1 (2, 3, 4, 5, 6, 68)

把关键字参数以字典的方式传入,个数都是可变长度

 1 # **kwargs:接受N个关键字参数,转换成字典的方式
 2 def test_dict(**kwargs):  
 3     print(kwargs)
 4 
 5 
 6 test_dict(name="king",age=30) #{'name': 'king', 'age': 30}
 7 
 8 
 9 # 如果是传入字典的模式,就需要写两个**
10 d = {'name': 'king', 'age': 30}
11 test_dict(**d) #{'name': 'king', 'age': 30}

可变长度参数与默认参数/必填参数的实例

def test(name,age=18,**kwargs):
    print(name)
    print(age)
    print(kwargs)

test('king',sex='m',hoboy='tesla')
test('king',sex='m',hoboy='tesla',age=3) #这样子也以的
test('king',3,sex='m',hoboy='tesla') #这样子也以的,3可以理解为以位置方式传值
    # king
    # 18
    # {'sex': 'm', 'hoboy': 'tesla'}

 

 1 def test(name,age=18,*args,**kwargs):
 2     print(name)
 3     print(args)
 4     print(age)
 5     print(kwargs)
 6 
 7 test('king',age=34,sex='m',hoboy='tesla')
 8 
 9 # king
10 # ()
11 # 34
12 # {'sex': 'm', 'hoboy': 'tesla'}

七. 局部变量

1)。定义一个可以修改名字的程序

 1 def change_name(name):
 2     print('before change %s'%name,id(name))
 3     name = 'xiaofei'  #这个就是一个局部变量,只在函数内部生效,不会影响外面变量,这个函数就是这个变量的作用域
 4     print(id(name),name)
 5 
 6 name = 'king'
 7 print(id(name),name) #59663200 king
 8 
 9 change_name(name)
10     # before change king 59663200
11     # 59663328 xiaofei
12 
13 print(id(name),name) #59663200 king  说明没有修改到?
14 
15 # 局部变量与全局变量
16 # 局部变量,只在作用域内生效,如上面的只在函数体内生效
17 # 全局变量:这个是一级变量,放在文件的顶部,或者说一级,顶格变量

2).在局部变量中就是需要修改全局变量怎么样做

1 name = 'xiaofei' #全局变量
2 
3 def change_name(arg):
4     global name #声明这个是全局变量
5     name = arg
6 
7 print(id(name),name)
8 change_name('king')
9 print(id(name),name)  #king

3).在局部变量里面声明全局变量

1 def change_name(arg):
2     global name #声明这个是全局变量,全局里面如果没有就自动创建,有的话就拿过来
3     name = arg
4 
5 change_name('king')
6 print(id(name),name)  #king

注意:在函数里面不应该修改全局变量,函数里面声明全局变量更加不建议这样子用

4).局部变量是可以修改字典,列表,集合,类里面的数据的

1 names = ['king','xiaofei',{"age":30,"address":'广东'}]
2 def change_name():
3     names[0]='xiaoking' #修改列表的数据
4     names[2]['age'] = 40 #修改字典里面的数据
5 
6 print(id(names),names)  #11855952 ['king', 'xiaofei', {'age': 30, 'address': '广东'}]
7 change_name()
8 print(id(names),names)  #11855952 ['xiaoking', 'xiaofei', {'age': 30, 'address': '广东'}]

上面局部变量可以修改引用的数据类型,除了字符串与数字不能修改,其它引用的类型,都可以修改

八. 递归

python的递归最大是999层

1 def calc(n):
2     print(n)
3     return calc(n+1)
4 
5 
6 # calc(0)  #RecursionError: maximum recursion depth exceeded while calling a Python object

写一个程序一直除以2,直到除不近的时候退出

 1 def calc(n):
 2     print(n)
 3     if int(n/2) >0:
 4         return calc(int(n/2))
 5     print("--->",n)
 6 
 7 calc(10)
 8 # 10
 9 # 5
10 # 2
11 # 1
12 # ---> 1

九. 高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

1 def add(a,b,fun):
2     return fun(a)+fun(b)
3 
4 # abs 这个是绝对值,可以将负数转换为正数
5 res = add(3,-6,abs)
6 print(res) #9

# http://www.cnblogs.com/alex3714/articles/5717620.html
作业:程序练习
程序1:实现简单的shell sed 替换功能

data_db

 1 Somehow, it seems the love I knew was always the most destructive kind
 2 不知为何,我经历的爱情总是最具毁灭性的的那种
 3 Yesterday when I was young
 4 昨日当我年少轻狂
 5 The taste of life was sweet
 6 生命的滋味是甜的
 7 As rain upon my tongue
 8 就如舌尖上的雨露
 9 I teased at life as if it were a foolish game
10 我戏弄生命 视其为愚蠢的游戏
11 The way the evening breeze
12 就如夜晚的微风
13 May tease the candle flame
14 逗弄蜡烛的火苗
15 The thousand dreams I dreamed
16 我曾千万次梦见
17 The splendid things I planned
18 那些我计划的绚丽蓝图
19 I always built to last on weak and shifting sand
20 但我总是将之建筑在易逝的流沙上
21 I lived by night and shunned the naked light of day
22 我夜夜笙歌 逃避白昼赤裸的阳光
23 And only now I see how the time ran away
24 事到如今我才看清岁月是如何匆匆流逝
25 Yesterday when I was young
26 昨日当我年少轻狂
27 So many lovely songs were waiting to be sung
28 有那么多甜美的曲儿等我歌唱
29 So many wild pleasures lay in store for me
30 有那么多肆意的快乐等我享受
31 And so much pain my eyes refused to see
32 还有那么多痛苦 我的双眼却视而不见
33 I ran so fast that time and youth at last ran out
34 我飞快地奔走 最终时光与青春消逝殆尽
35 I never stopped to think what life was all about
36 我从未停下脚步去思考生命的意义
37 And every conversation that I can now recall
38 如今回想起的所有对话
39 Concerned itself with me and nothing else at all
40 除了和我相关的 什么都记不得了
41 The game of love I played with arrogance and pride
42 我用自负和傲慢玩着爱情的游戏
43 And every flame I lit too quickly, quickly died
44 所有我点燃的火焰都熄灭得太快
45 The friends I made all somehow seemed to slip away
46 所有我交的朋友似乎都不知不觉地离开了
47 And only now I'm left alone to end the play, yeah
48 只剩我一个人在台上来结束这场闹剧
49 Oh, yesterday when I was young
50 噢 昨日当我年少轻狂
51 So many, many songs were waiting to be sung
52 有那么那么多甜美的曲儿等我歌唱
53 So many wild pleasures lay in store for me
54 有那么多肆意的快乐等我享受
55 And so much pain my eyes refused to see
56 还有那么多痛苦 我的双眼却视而不见
57 There are so many songs in me that won't be sung
58 我有太多歌曲永远不会被唱起
59 I feel the bitter taste of tears upon my tongue
60 我尝到了舌尖泪水的苦涩滋味
61 The time has come for me to pay for yesterday
62 终于到了付出代价的时间 为了昨日
63 When I was young
64 当我年少轻狂
View Code

python代码部分

 1 '''
 2 python3 执行这个程序
 3 格式 python 文件名  查找的字符串 替换的字符串
 4 
 5 '''
 6 import sys
 7 import os
 8 print(len(sys.argv),sys.argv)
 9 
10 # 输入的参数必须等于3,不然就格式不对
11 if len(sys.argv) == 3:
12     old_str = sys.argv[1] #查找的字符串
13     new_str = sys.argv[2] #被替换的字符串
14 else:
15     print("缺少参数!!!\n格式:python 文件名.py 查找字符串 替换字符串")
16     exit()
17 
18 
19 with open('data_db','r',encoding='utf-8') as old_file ,open('data_bk_db','w',encoding='utf-8') as new_file:
20     for line in old_file:
21         line = line.replace(old_str,new_str)
22         new_file.write(line)
23 
24 
25 # 替换完了以后修改文件名
26 os.rename('data_db','data_db_bak')
27 os.rename('data_bk_db','data_db')
28 os.rename('data_db_bak','data_bk_db')
29 
30 # shell命令
31 # F:\Design\git\gitlab\python\oldpythons14\s3\student_class>python 01_实现简单的shell替换功能.py 年少轻狂 **年少轻狂**
32 # 3 ['01_实现简单的shell替换功能.py', '年少轻狂', '**年少轻狂**']

# 程序2:修改haproxy配置文件

 1 global       
 2         log 127.0.0.1 local2
 3         daemon
 4         maxconn 256
 5         log 127.0.0.1 local2 info
 6 defaults
 7         log global
 8         mode http
 9         timeout connect 5000ms
10         timeout client 50000ms
11         timeout server 50000ms
12         option  dontlognull
13 
14 listen stats :8888
15         stats enable
16         stats uri       /admin
17         stats auth      admin:1234
18 
19 frontend oldboy.org
20         bind 0.0.0.0:80
21         option httplog
22         option httpclose
23         option  forwardfor
24         use_backend www.oldboy.org if www
25 
26 
27 
28 backend www.qq.com
29          server 192.168.100.102 192.168.100.102 weight 20 maxconn 30
View Code

# 实现增删改查的功能
# eval()可以将字符串转换为字典

 

  1 # 1、查
  2 #     输入:www.qq.com
  3 #     获取当前backend下的所有记录
  4 
  5 # 2、新建
  6 #     输入:
  7 #         arg = {
  8 #             'bakend': 'www.qq.com',
  9 #             'record':{
 10 #                 'server': '100.1.7.9',
 11 #                 'weight': 20,
 12 #                 'maxconn': 30
 13 #             }
 14 #         }
 15 
 16 # 3、删除
 17 #     输入:
 18 #         arg = {
 19 #             'bakend': 'www.oldboy.com',
 20 #             'record':{
 21 #                 'server': '100.1.7.9',
 22 #                 'weight': 20,
 23 #                 'maxconn': 30
 24 #             }
 25 #         }
 26 
 27 def count_host(fileAllPath='haproxy_db'):
 28     '''
 29     统计里面的文件所在的行数
 30     :param fileAllPath:
 31     :return:返回一个字典 格式 {27: 'www.oldboy.org', 30: 'www.163.com'}
 32     '''
 33     hosts = {}
 34     f = open(fileAllPath, 'r', encoding='utf-8')
 35     data = f.readlines()
 36     for n, line in enumerate(data):
 37         if line.find('backend') != -1 and line.find('use_backend') == -1:
 38             hosts[n] = line.replace('backend', '').strip()
 39     f.close()
 40     return hosts
 41 
 42 
 43 def host(bakend, server, weight=20, maxconn=30):
 44     arg = {
 45         'bakend': bakend,
 46         'record': {
 47             'server': server,
 48             'weight': weight,
 49             'maxconn': maxconn
 50         }
 51     }
 52     return arg
 53 
 54 
 55 def addBackend(databases):
 56     # 请输入相关的信息
 57     inp_bakend = input("请输入网址:")
 58     inp_server = input("请输入服务器IP:")
 59     d = host(bakend=inp_bakend, server=inp_server)
 60     # print(d)
 61     # print('bakend\t{bakend}\n\t\tserver {server} 100.1.7.9 weight 20 maxconn 3000' % (bakend = d['bakend'], server =
 62     # d['record']['server']))
 63     string = '''
 64 backend {backend}
 65          server {server} {server} weight {weight} maxconn {maxconn}'''.format(backend=d['bakend'],
 66                                                                               server=d['record']['server'],
 67                                                                               weight=d['record']['weight'],
 68                                                                               maxconn=d['record']['maxconn'])
 69     # print(string)
 70     with open(databases, 'a', encoding='utf-8') as f:
 71         ret = findDomain(databases, d['bakend'])
 72         # print(ret)
 73         if not ret[0]:
 74             print("操作成功!!!")
 75             f.write(string)
 76         else:
 77             print("域名已存在跳过!!!")
 78 
 79 
 80 def getMenu():
 81     menu = {1: "查找", 2: "添加", 3: "修改", 4: "删除"}
 82     print('请选择需要操作的菜单序号!')
 83     for x in menu:
 84         print(x, menu[x])
 85     return menu
 86 
 87 
 88 def findDomain(databases, inp_domain):
 89     # inp_domain = input("请输入要查询的域名")
 90     hosts = count_host(databases)
 91     # print(inp_domain in hosts.values(),hosts)
 92     return inp_domain in hosts.values(), hosts, inp_domain
 93 
 94 
 95 def getDomain(databases):
 96     host = count_host(databases)
 97     for i in host:
 98         print(i, host[i])
 99     inp_delDomain = input("请输入的域名序号:")
100     return inp_delDomain
101 
102 
103 def delBackend(databases):
104     ret = getDomain(databases)
105     ret = int(ret)
106     # 正式删除配置信息
107     bak_database = databases + '_bk'
108     # print(old_database)
109     old_file = open(databases, 'r', encoding='utf-8')
110     new_file = open(bak_database, 'w', encoding='utf-8')
111     for n, line in enumerate(old_file.readlines()):
112         if n == ret or n == ret + 1:
113             continue
114         new_file.write(line)
115     new_file.close()
116     old_file.close()
117 
118     # 修改文件配置,重命名文件
119     os.remove(databases)
120     os.rename(bak_database, databases)
121 
122 def changeBackend(databases):
123     ret = getDomain(databases)
124     ret = int(ret)
125     # 正式删除配置信息
126     bak_database = databases + '_bk'
127     old_file = open(databases, 'r', encoding='utf-8')
128     new_file = open(bak_database, 'w', encoding='utf-8')
129     for n, line in enumerate(old_file.readlines()):
130         if n == ret or n == ret + 1:
131             continue
132         new_file.write(line)
133     new_file.close()
134     old_file.close()
135 
136     # 修改文件配置,重命名文件
137     os.remove(databases)
138     os.rename(bak_database, databases)
139 
140     addBackend(databases)
141 
142 import sys
143 import time
144 import os
145 
146 databases = 'haproxy_db'
147 
148 falg = True
149 while falg:
150     menu_n = getMenu()
151     inp_menu = input("请选择你要输入的序号:")
152     if inp_menu.isdigit():
153         inp_menu = int(inp_menu)
154         if inp_menu > 0 and inp_menu <= len(menu_n):
155             # print("序号合法!!!")
156             if inp_menu == 1:
157                 # print("查询!!!")
158                 inp_domain = input("请输入要查询的域名")
159                 ret = findDomain(databases, inp_domain)
160                 if ret[0]:
161                     print('%s域名存在!!!' % ret[2])
162                     print('\t所有域名列表:')
163                     for line in ret[1].values():
164                         print('\t\t', line)
165                     break
166                 else:
167                     print("\t域名不存在\n所有的域名列表如下!!")
168                     for line in ret[1].values():
169                         print('\t\t', line)
170             elif inp_menu == 2:
171                 print("添加!")
172                 addBackend(databases)
173             elif inp_menu == 3:
174                 print("修改")
175                 changeBackend(databases)
176             else:
177                 print('删除')
178                 delBackend(databases)
179         else:
180             print("输入不合法!!!")
181     elif inp_menu == 'q':
182         sys.stdout.write("正在退出系统!!!")
183         for i in range(15):
184             sys.stdout.write("$")
185             sys.stdout.flush()
186             time.sleep(0.05)
187         falg = False
188     else:
189         print("你的输入有误!!!")

 

posted @ 2017-10-09 22:49  fullvip  Views(121)  Comments(0)    收藏  举报