上周復習:
列表增刪改查? 元祖是可讀列表
字符串操作
字典是無序的,通過key來找值。字典可以嵌套列表和字典
?
本周內容:集合--文件---字符編碼?
集合引入:
#隨機生成20個小于20的數,輸出所有的數,
# 要求重復的輸出一次


1 import random 2 a=[] 3 for i in range(20): 4 a.append(random.randint(1,20)) 5 for i in a: 6 if i not in b: 7 b.append(i) 8 print(b)


1 import random 2 a=[] 3 for i in range(20): 4 a.append(random.randint(1,20)) 5 print(a) 6 b=list(set(a)) 7 print(b)
?
一、集合
集合:非常簡單的去重復。關系測試,不同列表的中的元素的關系。
集合和字典一樣是無序的。
集合用的符號是{},和字典一樣。
集合:只能存儲不可修改的數據(數值,字符串,元祖), 不能存儲可以修改的數據類型(列表,字典,集合)
1)集合的創建 ? ??set方法:可以把列表換成集合。


1 list_1 = [1,4,5,7,3,6,7,9] 2 list_1 = set(list_1) 3 4 list_2 =set([2,6,0,66,22,8,4]) 5 6 print(list_1,list_2)
2)集合的關系
交集、并集、差集、子集、父集、對稱差集
交集:兩個集合都擁有的公共部分
并集:兩個集合都擁有的所有部分
差集:一個集合用戶而另外一個集合沒有的
子集:集合A的所有元素都在集合B中,集合A稱為集合B的子集,集合B稱為集合A的父集。
對稱差集:兩個集合的并集減去兩個集合的交集。


1 list_1 = [1,4,5,7,3,6,7,9] 2 list_1 = set(list_1) 3 4 list_2 =set([2,6,0,66,22,8,4]) 5 print(list_1,list_2) 6 7 #交集 8 print( list_1.intersection(list_2) ) 9 10 #并集 11 print(list_1.union(list_2)) 12 13 #差集 in list_1 but not in list_2 14 print(list_1.difference(list_2)) 15 print(list_2.difference(list_1)) 16 17 #子集 18 list_3 = set([1,3,7]) 19 print(list_3.issubset(list_1)) 20 print(list_1.issuperset(list_3)) 21 22 #對稱差集 23 print(list_1.symmetric_difference(list_2)) 24 25 print("-------------") 26 27 list_4 = set([5,6,7,8]) 28 print(list_3.isdisjoint(list_4)) # Return True if two sets have a null intersection. 29 30 #交集 31 print(list_1 & list_2) 32 #并集 33 print(list_2 | list_1) 34 #差集 35 print(list_1 - list_2) # in list 1 but not in list 2 36 #對稱差集 37 print(list_1 ^ list_2)
3)集合的操作
增加 add():添加一項
添加update():添加多項
刪除pop()隨機刪除一項
刪除remove():刪除,如果不存在,報錯
刪除discard():直接刪除,沒有返回值
求長度,len()
判斷存在 x in s ?
判斷不存在 x not in s


1 list_1 = [1,4,5,7,3,6,7,9] 2 list_1 = set(list_1) 3 list_1.add(999) 4 list_1.update([888,777,555]) 5 print(list_1) 6 print(list_1.pop()) 7 print( list_1.discard(888) ) 8 print(len(list_1)) 9 print( '1' in list_1) 10 11 結果: 12 {1, 3, 4, 5, 6, 7, 999, 9, 777, 555, 888} 13 1 14 None 15 9 16 False
二、字符編碼
decode 解碼 ? encode ?編碼
先說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類型-->按照指定編碼轉成你能看懂的文字
5)編碼應用比較多的場景應該是爬蟲了,互聯網上很多網站用的編碼格式很雜,雖然整體趨向都變成utf-8,但現在還是很雜,所以爬網頁時就需要你進行各種編碼的轉換,不過生活正在變美好,期待一個不需要轉碼的世界。
(轉自金角大王的博客)
?
unicode都占兩個字符
ascii碼英文都占一個字符
Utf-8可變長的字符編碼,里面所有英文字符一個字節,中文三個字節。
字符編碼的轉換:
?
不同編碼之間的轉換,需要unicode編碼
聲明文件編碼:
#-*-coding:gbk-*-
Python程序中默認unicode
區分文件編碼和程序中字符編碼
理解這句話:
s="你好"
print(s.encode("utf-8").decode("utf-8").encode("gb2312"))
?
encode()轉化為編碼,通過decode()才能轉化字符顯示。
?
三、文件的操作
?
# 文本存儲的原理
# 1、打開編輯器就打開了啟動了一個進程,是在內存中的,
# 所以,用編輯器編寫的內容也都是存放與內存中的,斷電后數據丟失
# 2、要想永久保存,需要點擊保存按鈕:編輯器把內存的數據刷到了硬盤上。
# 3、在我們編寫一個py文件(沒有執行),跟編寫其他文件沒有任何區別,
# 都只是在編寫一堆字符而已。
?
?
對文件操作的流程
1)打開文件,得到文件的句柄,并賦值給一個變量
2)通過句柄,對文件進行操作
3)關閉文件
?
打開文件的模式有:
- r,只讀模式(默認)。
- w,只寫模式。【不可讀;不存在則創建;存在則刪除內容;慎用】
- a,追加模式。【可讀; ? 不存在則創建;存在則只追加內容;】
"+" 表示可以同時讀寫某個文件
- r+,可讀寫文件。【可讀;可寫;可追加,最常用】
- w+,寫讀
- a+,同a
"U"表示在讀取時,可以將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)
- rU
- r+U
"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標注)
- rb
- wb
- ab
打印進度條的例子:


1 import sys,time 2 3 for i in range(20): 4 sys.stdout.write("#") 5 sys.stdout.flush() 6 time.sleep(0.1)
實際通過f.flush()方法,大家就會理解了為什么斷電會數據丟失。
計算機中硬盤和內存的處理數據的速度是不一樣的,在向硬盤寫數據時候,就需要寫先入緩沖區中,寫滿了,一次性的寫入硬盤中。突然斷電,就會讓緩沖區中的數據丟失。
也就是說我們的程序中把再行過程中,程序顯示的是寫入了硬盤,實際是寫在了緩沖區中,而沒有及時寫入硬盤,從而造成數據丟失。Python解決這個問題的辦法就是f.flush()方法。
?
文件的修改的辦法:
1)加載到內存中,修改!
2)打開一個文件,修改后寫在新文件中。


1 修改 2 f1=open("good_list.txt",'r+') 3 f_new=open("good_list.bak.txt","w",encoding="utf-8") 4 for line_1 in f1: 5 if mod_goods in line_1: 6 line_1=line_1.replace(re.split(":",line_1)[1],"%s:"%mod_price) 7 f_new.write(line_1) 8 f_new.flush() 9 f1.close() 10 f_new.close() 11 12 #寫回原文件 13 f1=open("good_list.txt","w") 14 f_new=open("good_list.bak.txt","r") 15 for line_2 in f_new: 16 f1.write(line_2) 17 f1.flush() 18 f1.close() 19 f_new.close()


1 import sys 2 f = open("yesterday2","r",encoding="utf-8") 3 f_new = open("yesterday2.bak","w",encoding="utf-8") 4 5 find_str = sys.argv[1] 6 replace_str = sys.argv[2] 7 for line in f: 8 if find_str in line: 9 line = line.replace(find_str,replace_str) 10 f_new.write(line) 11 f.close() 12 f_new.close()
練習:
#:實現:linux下vim中替換操作:
# 例如: 1,5s/H/h/g 實現把前5行的H替換為h
# 要求:行號,替換的內容,還有g都是輸入的
# n,m s /替換的內容 / 被替換的內容 /g


1 str1="11,54s/'中國'/'云計算'/g" 2 str1=str1.strip() 3 hang1=int((str1.partition(",")[0])) 4 hang2=int((str1.partition(",")[2].partition("s")[0])) 5 bth=str1.split("/")[1] 6 th=str1.split("/")[2] 7 g=str1.split("/")[3] 8 #測試切割 9 print(hang1,hang2,bth,th,g) 10 #文檔修改的思路: 11 lines=[] 12 with open("123.txt","r",encoding="utf-8") as f: 13 for line in f: 14 if "H" in line: 15 line=line.replace("H","h") 16 lines.append(line) 17 with open("123.txt","w",encoding="utf-8") as f: 18 for i in lines: 19 f.write(i)
練習2:
編程程序,實現set nu 給文檔每一行 添加一個行號:


1 count=1 2 lines=[] 3 with open("123.txt","r+",encoding="utf-8") as f: 4 for line in f: 5 line=str(count)+": "+ line 6 count=count+1 7 lines.append(line) 8 f.seek(0) 9 for i in lines: 10 f.write(i)
練習3:
#編寫函數,實現猜數字的游戲,隨機生成1-20個數字,只能猜三次。
#利用裝飾器,給上面的游戲,增加一個用戶判斷的功能。
#要求用戶名和密碼存在文件中。
四、作業
程序練習
程序1: 實現簡單的shell sed替換功能
程序2:修改haproxy配置文件?
需求:


1 1、查 2 輸入:www.oldboy.org 3 獲取當前backend下的所有記錄 4 5 2、新建 6 輸入: 7 arg = { 8 'bakend': 'www.oldboy.org', 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.org', 20 'record':{ 21 'server': '100.1.7.9', 22 'weight': 20, 23 'maxconn': 30 24 } 25 } 26 27 需求


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 log global 25 acl www hdr_reg(host) -i www.oldboy.org 26 use_backend www.oldboy.org if www 27 28 backend www.oldboy.org 29 server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000 30 31 原配置文件
參考文獻:
http://www.cnblogs.com/alex3714/articles/5717620.html
http://www.cnblogs.com/yuanchenqi/articles/5956943.html
?
?
?
?
?
?