python學習筆記(集合的使用、文件操作、字符編碼與轉碼、函數)
集合
集合(set):把不同的元素組成一起形成集合,是python基本的數據類型。
集合元素(set elements):組成集合的成員
為什麽需要集合?
集合的作用
1 .列表去重復數據
按照現有知識的解決思路:先設置空列表,然後使用for尋獲,把需要去重的列表的第一個數據放到新列表中,然後依次取出第二個數據,把第二個數據和第一個數據作比較,如果不一樣,則存入新列表中;以此類推,每取一次都要和新列表中的數據作對比,不一樣的則添加入新列表中。
2. 關系測試
比如有學員同時報了python班和linux班,同時在2個列表中,可以用集合來找出該關系。
列表去重
list_1 =[1,4,5,7,3,6,7,9,9,9,1,3,2,5,11,23,222,234,35,11] list_1 = set(list_1) print(list_1)
查看運行結果,列表在轉成集合後去除了重復數據。
註意點:集合也是無序的。
集合的關系測試
list_1 =[1,4,5,7,3,6,7,9,9,9,1] list_1 = set(list_1) list_2 = set([2,6,0.66,22,8,4]) # print(list_1,list_2) #交集 print(list_1.intersection(list_2)) #並集 print(list_1.union(list_2)) #差集 list_1裏有,list_2裏沒有 print(list_1.difference(list_2)) print(list_2.difference(list_1)) #子集 list_3 = set([1,3,7]) print(list_3.issubset(list_1)) #list_3是list_1的子集,返回True #父集 print(list_1.issuperset(list_3)) #list_1是list_3的父集,返回True #對稱差集 print(list_1.symmetric_difference(list_2)) print("-----------") list_4 = set([5,6,8]) print(list_3.isdisjoint(list_4)) #判斷是否是分離集合,不相交
集合的運算符
list_1 =[1,4,5,7,3,6,7,9,9,9,1] list_1 = set(list_1) list_2 = set([2,6,0.66,22,8,4]) #交集(intersection):& print(list_1 & list_2) #並集(union):| print(list_1 | list_2) #差集(difference):- print(list_1 - list_2) #對稱差集(symmetric_difference):^ print(list_1 ^ list_2)
集合的增刪改查
list_1 = set([1,3,5,2,8,11,17]) list_1.add(999) #添加一項 list_1.update([888,777,555]) #添加多項 print(list_1) list_1.remove(888) #刪除一項 print(list_1) print(len(list_1)) #集合的長度 list_1 in list_2 #判斷list_1是否是list_2的成員 list_1 not in list_2 #判斷list_1是否不是list_2的成員 print(list_1.pop()) #任意刪除一項 print(list_1.remove(‘ddd‘)) #使用remove時,如果對象不存在,會出現報錯信息 print(list_1.discard(‘ddd‘)) #使用discard時,對象不存在也不會報錯
文件操作
對文件操作流程:
1. 打開文件,得到文件句柄並賦值給一個變量
2. 通過句柄對文件進行操作
3. 關閉文件
實例一:
f = open(‘yesterday.txt‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象 data = f.read() data2 = f.read() print(data) print(‘data2‘.center(50,‘-‘),data2)
以上例子中,data和data2讀取了2次文件內容,但在屏幕輸出時,只顯示一次內容。因為文件的操作在讀取完之後,指針停留在最後一行,所以data2的賦值,並沒有讀取到內容。
文件基礎操作:
以下三種文件打開操作,寫入並不兼容讀取。有‘r’權限的時候不能寫入,有‘w‘權限的時候不能讀取,程序會報錯。
#讀取文件內容 f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象 data = f.read() print(data) f.close()
#文件只寫操作 f = open(‘yesterday2.txt‘,‘w‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象,open可以創建文件,使用寫入權限時千萬註意 f.write("我愛北京天安門,\n") f.write("天安門上太陽升,\n") f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘) data = f.read() print(data) #查看輸出,文件原有內容丟失。證明open ‘w’操作是創建文件。不能亂用。
#文件追加內容 f = open(‘yesterday2.txt‘,‘a‘,encoding=‘utf-8‘) #文件句柄 文件的內存對象 #a = append 追加 f.write("我愛北京天安門2,\n") f.write("天安門上太陽升2,\n") f = open(‘yesterday2.txt‘,‘r‘,encoding=‘utf-8‘) data = f.read() print(data) f.close()
其他文件打開模式:
文件讀寫:(r+)
文件寫讀:(w+)
文件追加讀:(a+)
"U"表示在讀取時,可以將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)
- rU
- r+U
"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標註)
- rb
- wb
- ab
實例:
需求:打印歌詞文件,跳過第十行不打印,第十行打印分割線。
f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘) for index,line in enumerate(f.readlines()): #註意:readlines一次讀取文件內容到內存,只適合小文件。 if index == 9: print("-------------------------") continue print(line.strip()) #strip()默認刪除空白符(包括‘\n‘, ‘\r‘, ‘\t‘, ‘ ‘)
前一個需求的改進寫法:
#高效率方法 f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘) count = 0 for line in f: #文件變成叠代器,讀取一行刪除一行,內存中只占一行內容 if count == 9: print("-------我是分割線-------") count +=1 continue print(line.strip()) count +=1
文件讀/寫指針操作:
f = open(‘yesterday.txt‘,‘r‘,encoding=‘utf-8‘) print(f.tell()) #返回文件讀/寫指針當前位置,開始是0 print(f.read(5)) #讀取字符數 print(f.tell()) #返回當前指針所在位置,按字符計算 f.seek(0) #讓文件讀/寫指針移到指定位置 print(f.readline()) #文件已回到開頭 f.close()
以1個例子說明tell()和seek()函數的作用:
fso = open("a.txt",‘w+‘) #以w+方式,並非a方式打開文件,故文件原內容被清空 print(fso.tell()) #文件原內容被清空,故此時tell()=0 fso.write("abcde\n") #寫入文件abcde\n,因為換行\n占兩個字符,故共寫入7個字符 print(fso.tell()) #此時tell()=7 fso.write("fghwm") #又寫入文件fghwm,故此時文件共寫入7+5 =12個字符 print(fso.tell()) #此時tell()=12 fso.seek(1, 0) #從起始位置即文件首行首字符開始移動1個字符 print(fso.tell()) #此時tell() =1 print(fso.readline()) #讀取當前行,即文件的第1行,但是從第二個字符(tell()+1)開始讀,結果為:bcde。 #若換成for讀取整個文件或read讀取整個文件則結為bcdefghwm print(fso.tell()) #因為readline此時tell() =7, fso.truncate(8) #從寫入後文件的首行首字符開始階段,截斷為8個字符,即abcde\nf,即文件的內容為:abcde\nf print(fso.tell()) #tell() 依舊為7,並為受truncate(8)影響,但是此時文件內容為abcde\nf print(fso.readline()) #從tell()+1=8開始讀取,讀取當前行內容:f fso.close()
文件操作:flush()實例
flush() 方法是用來刷新緩沖區的,即將緩沖區中的數據立刻寫入文件,同時清空緩沖區,不需要是被動的等待輸出緩沖區寫入。
一般情況下,文件關閉後會自動刷新緩沖區,但有時你需要在關閉前刷新它,這時就可以使用 flush() 方法。
在cmd命令行中才能看到實際測試效果。在命令行中往文本文件中寫入數據後,並不是馬上就會保存,python會在寫滿緩存後再一次性寫入硬盤。使用了f.flush()代碼後,可以馬上寫入硬盤。
進度條實例:
import sys,time for i in range(50): sys.stdout.write("#") sys.stdout.flush() time.sleep(0.1)
文件修改實例:
需求:已有Yesterday when I was young這首歌的歌詞文件yesterday.txt,修改其中的一句歌詞翻譯:”肆意的快樂等我享受”改為“肆意的快樂等Alex享受”。
解決方法:一行行讀取,遇到符合條件的行後進行修改,然後新建yesterday3.txt文件保存歌詞文件。
f = open("yesterday.txt",‘r‘,encoding="utf-8") f_new = open("yesterday3.txt","w",encoding="utf-8") for line in f: if "肆意的快樂" in line: line = line.replace("肆意的快樂等我享受","肆意的快樂等Alex享受") f_new.write(line) f.close() f_new.close()
with語句
with語句作用,自動關閉文件
with open("yesterday.txt","r",encoding="utf-8") as f: for line in f: print(line.strip())
可以用with同時打開多個文件
with open("yesterday.txt","r",encoding="utf-8") as f , open("yesterday3.txt","r",encoding="utf-8") as f2: #官方文檔建議每行代碼不超過82個字符,所以分行編寫 for line in f: print(line)
字符編碼與轉碼
#-*- coding:utf-8 -*- #python2中需要指定編碼類型為:utf-8,python3中默認編碼類型為Unicode
ASCII碼
GB2312:GB是“國標”兩字的拼音首字,2312是標準序號。GB2312編碼是第一個漢字編碼國家標準,由中國國家標準總局1980年發布,1981年5月1日開始使用。共收錄漢字6763個。
GBK:是對GB2312編碼的擴展。共收錄漢字和圖形符號21886個。其中漢字21003個。
GB18030:2000年3月17日發布。是對GBK編碼的擴充。收錄27484個漢字。
UNICODE(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。
Unicode 是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一並且唯一的二進制編碼,規定雖有的字符和符號最少由 16 位來表示(2個字節),即:2 **16 = 65536, 註:此處說的的是最少2個字節,可能更多。
UTF-8:是對Unicode編碼的壓縮和優化,他不再使用最少使用2個字節,而是將所有的字符和符號進行分類:ascii碼中的內容用1個字節保存、歐洲的字符用2個字節保存,東亞的字符用3個字節保存...
編碼實例:
來自於:http://www.cnblogs.com/luotianshuai/articles/5735051.html
python3中:
#!/usr/bin/env python #-*- coding:utf-8 -*- #author luotianshuai tim = ‘天帥‘ #轉為UTF-8編碼 print(tim.encode(‘UTF-8‘)) #轉為GBK編碼 print(tim.encode(‘GBK‘)) #轉為ASCII編碼(報錯為什麽?因為ASCII碼表中沒有‘天帥’這個字符集~~) print(tim.encode(‘ASCII‘))
python2中:
因為在python2.X中默認是ASCII編碼,你在文件中指定編碼為UTF-8,但是UTF-8如果你想轉GBK的話是不能直接轉的,的需要Unicode做一個轉接站點。
#!/usr/bin/env python #-*- coding:utf-8 -*- #author luotianshuai import chardet tim = ‘你好‘ print chardet.detect(tim) #先解碼為Unicode編碼,然後在從Unicode編碼為GBK new_tim = tim.decode(‘UTF-8‘).encode(‘GBK‘) print chardet.detect(new_tim) #結果 ‘‘‘ {‘confidence‘: 0.75249999999999995, ‘encoding‘: ‘utf-8‘} {‘confidence‘: 0.35982121203616341, ‘encoding‘: ‘TIS-620‘} ‘‘‘
函數與函數式編程
編程方式:
1. 面向對象:類----->>class
2. 面向過程:過程---->>def
3. 函數式編程:函數---->>def
函數定義:
初中數學函數定義:一般的 ,在一個變化過程中,如果有兩個變量x和y,並且對於x的每一個確定的值,y都有唯一確定的值與其對應,那麽我們就把x稱為自變量,把y稱為因變量,y是x的函數。自變量x的取值範圍叫做這個函數的定義域。
編程語言中函數定義:函數式邏輯結構化和過程化的一種編程方法。
python中函數定義方法:
#python中函數定義方法: def test(x): ‘‘‘The function definitions‘‘‘ x +=1 return x # def:定義函數的關鍵字 # test:函數名 # ():內可定義形參 # ‘‘‘‘‘‘:文檔描述(非必要,但是強烈建議為你的函數添加描述信息) # x+=1:泛指代碼塊或程序處理邏輯 # return:定義返回值
函數式編程就是:先定義一個數學函數,然後按照這個數學模型用編程語言去實現它。
為什麽要使用函數:
沒有函數的編程只是在寫邏輯(功能),想脫離函數,重用你的邏輯,唯一的方法就是拷貝
例子一:
def test1(): print(‘in the test1‘) with open(‘a.txt‘,‘a+‘) as f: f.write(‘end action\n‘) def test2(): print(‘in the test2‘) with open(‘a.txt‘,‘a+‘) as f: f.write(‘end action\n‘) def test3(): print(‘in the test3‘) with open(‘a.txt‘,‘a+‘) as f: f.write(‘end action\n‘) test1() test2() test3()
例子二:對以上代碼進行優化,並且加入日誌時間。使用函數編程方法:
import time def logger(): time_format = ‘%Y-%m-%d %X‘ time_current = time.strftime(time_format) with open(‘a.txt‘,‘a+‘) as f: f.write(‘%s end action\n‘ %time_current) def test1(): print(‘in the test1‘) logger() def test2(): print(‘in the test2‘) logger() def test3(): print(‘in the test3‘) logger() test1() test2() test3()
使用函數的三大優點:
1. 代碼重用
2. 保持一致性
3. 可擴展性
函數參數及調用
函數返回值:
def test1(): print(‘in the test1‘) def test2(): print(‘in the test2‘) return 0
def test3(): print(‘in the test3‘) return 1,‘hello‘,[‘alex‘,‘wupeiqi‘],{‘name‘:‘alex‘} #return test2 #return可以返回任意類型,也可以是函數 x=test1() y=test2() z=test3() print(x) print(y) print(z)
總結:
返回值數=0;返回None
返回值數=1;返回object
返回值數>1;返回tuple
為什麽要有返回值?
其他的程序邏輯需要根據返回值進行操作
調用方法:
1. 形參和實參
根據位置一一對應
例一:
def test(x,y): print(x) print(y) test(1,2)
# test(y=2,x=1) #與形參順序無關
# test(1,2) #位置參數與形參一一對應
test(3,x=1) #程序報錯,因為同時給x賦值2次,y沒有賦值
例二:
def test(x,y,z): print(x) print(y) print(z) test(3,y=1,z=6) #這樣賦值是允許的 test(3,y=1,6) #位置參數雖然一一對應,但程序會報錯。因為關鍵參數不能出現在位置參數前面。切記。
函數的非固定參數
默認參數:
def test(x,y=2): #y=2是默認參數 print(x) print(y) test(1,3)
默認參數特點:調用函數的時候,默認參數非必須傳遞
默認參數用途:例如連接mysql數據時,可以默認指定端口號:3306
參數組:
1.
def test(*args): print(args) test(1,2,3,4,5,5) test(*[1,2,3,4,5]) # args=tuple([1,2,3,4,5])
2.
# **kwargs:把N個關鍵字參數,轉換成字典的方式 def test2(**kwargs): print(kwargs) test2(name=‘alex‘,age=8,sex=‘F‘)
def test3(name,**kwargs): print(name) print(kwargs) test3(‘alex‘,age=18,sec=‘m‘) # 使用關鍵字方式傳入
def test4(name,age=18,**kwargs): print(name) print(age) print(kwargs) test4(‘alex‘,sex=‘m‘,age=3,hobby=‘tesla‘) #age參數可以在任意位置
3.
def test4(name,age=18,*args,**kwargs): print(name) print(age) print(args) #args接收N個位置參數 print(kwargs) #kwargs接收N個關鍵字參數 test4(‘alex‘,34,1,2,3,sex=‘m‘,hobby=‘tesla‘) #34傳遞給age,1,2,3傳遞給了args
作用域、局部與全局變量
在子程序中定義的變量稱為局部變量,在程序的一開始定義的變量稱為全局變量。
全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。
當全局變量與局部變量同名時:在定義局部變量的子程序內,局部變量起作用;在其他地方全局變量起作用。
實例一:局部變量、作用域、全局變量的定義
school = "Oldboy edu." #全局變量 def change_name(name): school = "Mage" #局部變量 print("before change",name,school) name = "Alex Li" #局部變量,只在函數內生效。這個函數就是該變量的作用域。 age =23 print("after change",name) name = ‘alex‘ change_name(name) print(name) print(school)
實例二:如何在子程序(函數)中修改全局變量。
註意事項:千萬不要在函數中改全局變量。容易造成程序邏輯混亂,增加排錯難度。
school = "Oldboy edu." #全局變量 def change_name(name): global school # 在函數中定義全局變量 school = "Mage" #使用global後,school被聲明為全局變量 print("before change",name,school) name = "Alex Li" print("after change",name) name = ‘alex‘ change_name(name) print(name) print(school)
註意事項二:
字符串和整數類型變量不能在函數中直接更改
列表、字典、集合、類都可以在函數中更改
遞歸
在函數內部,可以調用其他函數。如果一個函數在內部調用自身,這個函數就是遞歸函數。
遞歸特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用時通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)
函數式編程介紹
函數式編程中的函數這個術語不是指計算機中的函數(實際上是Subroutine),而是指數學中的函數,即自變量的映射。也就是說一個函數的值僅決定於函數參數的值,不依賴其他狀態。比如sqrt(x)函數計算x的平方根,只要x不變,不論什麽時候調用,調用幾次,值都是不變的。
函數式編程(請註意多了一個“式”字)——Functional Programming,雖然也可以歸結到面向對象過程的程序設計,但其思想更接近數學計算。
函數式編程時一種抽象程度很高的編程範式。
定義:
簡單說,“函數式編程”是一種“編程範式”(programming paradigm),也就是如何編寫程序的方法論。
主要思想是把運算過程盡量寫成一系列嵌套的函數調用。
高階函數
變量可以指向函數,函數的參數能接收變量,那麽一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。
舉例:
def add(a,b,f): return f(a)+f(b) res = add(3,-6,abs) #abs是絕對值函數 print(res)
python學習筆記(集合的使用、文件操作、字符編碼與轉碼、函數)