引言 本來計劃每周完成一篇Python的自學博客,由於上一篇到這一篇遇到了過年、開學等雜事,導致托更到現在。現在又是一個新的學期,春天也越來越近了(冷到感冒)。好了,閑話就說這麼多。開始本周的自學Python之路。而且,同時從這周開始,也要開始自學Tensorflow。希望能嚴格要求自己,不會托更。 ...
引言
本來計劃每周完成一篇Python的自學博客,由於上一篇到這一篇遇到了過年、開學等雜事,導致托更到現在。現在又是一個新的學期,春天也越來越近了(冷到感冒)。好了,閑話就說這麼多。開始本周的自學Python之路。而且,同時從這周開始,也要開始自學Tensorflow。希望能嚴格要求自己,不會托更。加油啦。
正文
這個周主要學習了集合,文件的操作,以及一點函數中的知識。下麵將會詳細介紹各個內容。
集合
集合也是Python的一種變數類型。它與列表不同,集合中沒有順序,沒有重覆。通常定義一個集合可以用以下兩種方法。例子:
#直接寫出集合中的各個元素 list = set([2,1,10,15,18]) #將列表轉換為集合,會去掉重覆的值 list = [1,5,8,2,4,3,6,1,3] list = set(list)
對集合的編輯首先從添加開始,向集合中添加一個或多個元素的方法,例子:
list = set([2,1,10,15,18])#建立集合 list.add(99)#添加一項 list.update([99,100,101])#添加多項
說完了添加,下麵將會帶來幾種刪除的方法,例子:
list = set([2,1,10,15,18])#建立集合 list.remove(2)#刪除2,若list中不存在會報錯 list.discard(114514)#刪除114514,若list中不存在不會報錯 list.pop()#隨機刪除一個並返回
講完了集合的編輯,就不得不提集合的幾種運算,即交集、並集、差集。在Python中還多了一種對稱差集,也就是集合A與集合B中所有不屬於A∩B的元素的集合。例子:
list = set([2,1,10,15,18])#建立集合 list_new = set([10,15,18,99,65])#建立集合 #交集 list.intersection(list_new) list & list_new #並集 list.union(list_new) list | list_new #差集 list.difference(list_new) list - list_new #對稱差集 list.symmetric_difference(list_new) list ^ list_new
同樣,Python中也預設了一些判斷語句,方便判斷時使用。例子:
list = set([2,1,10,15,18])#建立集合 list_new = set([10,15,18,99,65])#建立集合 #判斷是否為子集 list.issubset(list_new) list_new in list #判斷是否為父集 list.issuperset(list_new) #未相交判斷 list.isdisjoint(list_new)
文件操作
文件操作是任何一種語言學習中的重點。讀寫硬碟中的文件一方面是為記憶體中的程式運行提供必要數據,另一方面也是保存記憶體中運算結果的重要手段。
在Python中,文件操作主要由三個步驟組成:打開——操作——關閉。但是這裡首先講解文件操作中的打開和關閉。
打開一個文件與關閉這個文件是一一對應的。之要打開,就需要關閉。雖然,在程式運行結束後,會自動從記憶體中釋放打開的文件,但是在整個程式運行的過程中,這個文件都是打開的,這對於數據的安全和運行都是不利的。所以,一定要關閉文件。打開和關閉的方法比較簡單。例子:
f = open('test.txt','r')#打開文件,('文件名及絕對或相對路徑','操作許可權') #操作 f.close()#關閉文件
為了避免忘記關閉文件的不便,鑒於Python縮進編程的優勢,還有一種無需寫關閉文件的打開方法。例子:
#打開一個文件 with open('test.txt','r') as f: #操作 #後續代碼 #打開多個文件 with open('test.txt','r') as f,\ open('test_new','w') as f_new: #操作 #後續代碼
在填寫路徑時,由於Linux用戶的路徑使用的是正斜杠,'/';而Windows用戶的路徑使用的是反斜杠,'\'。而反斜杠容易被組合形成轉義字元,發生衝突。這裡Windows用戶也可以一律在路徑中填寫正斜杠,也會識別。下麵就要介紹幾種常用的操作許可權:
''' 'r' 只讀 'w' 只寫,若文件存在會覆蓋原文件 'a' 添加,在文件後繼續添加,不能讀 'b' 二進位模式,與r和w組合使用,rb,wb '+' 添加另一種模式,與r和w組合使用,r+,w+,但只會寫在最後 'U' #linux與windows的區別,將\r\n自動轉換為\n '''
之後,就要介紹文件的操作方法了。首先,要將文件全部讀為字元一次性讀入記憶體,可以用這個方法。例子:
with open('test.txt','r') as f: f.readlines()#每行一個元素,全部讀入
這種方法只適用於小文件讀取。當文件比較大是,如果用這種方法有可能會爆掉記憶體。這裡就要介紹另外一種方法了,及一行一行的讀取。文件在剛打開時,文件讀取的指針放在了文件初始位置。每讀取一次一行,讀取指針就會移動到下一行的開頭。當讀取為空時,就完成了文件的讀取。例子:
with open('test.txt','r') as f: f.readline()#讀取第一行 f.readline()#讀取第二行 f.readline()#讀取第三行
當讀取到一半時,很難確定此時指針的位置。Python中提供了獲取指針位置和移動指針到某一位置的方法。例子:
with open('test.txt','r') as f: f.readline()#讀取一行 f.tell()#返回此時指針的位置 f.seekable(0)#將指針移動到括弧中的位置,0為開始位置
寫入文件的方法比較簡單。例子:
with open('test.txt','w') as f: f.write('字元串')#寫入文件要想寫入後換行可以在字元串結尾加入\n
出了讀寫外,Python還為文件操作增加了一些其他內容,這裡一併介紹。例子:
with open('test.txt','w') as f: f.encoding#文件的編碼 f.fileno()#返回操作系統調用文件介面的編號 f.truncate()#清空文件,或進行括弧內字元量的截斷,與游標指針位置無關 f.flush()#強制刷新
同樣,Python也為文件操作提供了一些判斷。例子:
with open('test.txt','w') as f: f.seekable()#判斷游標能否移動 f.readable()#判斷是否可讀 f.writable()#判斷是否可寫 f.closed#判斷是否關閉
文件內容的迴圈。例子:
with open('test.txt','r+') as f: #低效迴圈 for line in f.readlines(): print(line.strip())#讀一行,strip去掉前後空格 for index,line in enumerate(f.readlines()): print(index) print(line.strip()) #高效迴圈 count = 0 for line in f:#一行行讀入記憶體 print(count) print(line.strip()) count += 1
對於硬碟上的文件修改,也有兩種方法。一種是低效方法,即將文件中的內容全部讀入記憶體後,利用正則表達式等方法對其修改後再將其重新寫入文件。另一種方法是同時打開兩個文件,一個讀一個寫,然後迴圈每行讀出需要修改的文件,然後逐行修改後分別存入另一個文件。這裡不再舉例。
字元編碼與轉碼
字元編碼有多種多樣,如ASCII碼、UTF-8、Unicode、GBK、GB2312。字元編碼的不同往往會導致程式中出現各種各樣的問題。所以學會轉碼是避免字元編碼導致問題的一種手段。
起初美國確立了ASCII碼,在這裡面每個字母符號均占一個位元組。為了顯示各國文字,各個國家分別建立了自己的字元編碼,如GBK,但是它們之間又不互相相容。為瞭解決各國編碼不相容的問題,萬國碼Unicode應用而生。但是Unicode中所有的符號都占用2個位元組,使得英文體積變大。為此,又出現了UTF-8,在UTF-8中,英文占一個位元組其他文字占3個位元組。Python3.X中的預設編碼格式為UTF-8。
Unicode由於其相容性,成為了各種編碼間互相轉換的橋梁。UTF-8和Unicode可以直接轉換為各國的編碼。各國的編碼要想互相轉換,就需要先解碼為Unicode然後由Unicode轉換為其他編碼。
轉換例子:
#-*- coding:UTF-8 -*- #聲明文檔的編碼格式 utf8 = 'hello world!' utf8_gbk = utf8.encode('gbk')#UTF-8轉GBK gbk_utf8 = utf8_gbk.decode('gbk').encode('utf-8')#GBK轉其他
函數
編寫函數可以大大減輕編程中重覆代碼編寫為編程人員帶來的麻煩。函數具有:代碼可重覆利用、可擴展性以及保持一致性的優點。下麵將介紹函數的一般形式。例子:
def 函數名(變數名=預設值,…):#變數名與預設值非必須填寫 '''函數功能介紹''' 函數體 return 返回值1,返回值2…
當不寫return時,函數返回None。調用函數時,括弧中的變數應該互相對應。每個變數都應該賦有確定的值。但是當該變數由預設值時,可以省略不寫。當依靠位置為變數賦值時,對應位置的值,與付給的值相對應。例子:
def number(x,y,z=0):#z初始值為0 print(x) print(y) print(z) return x+y,x-z number(3,2,1)#此時,x=3,y=2,z=1 number(2,1)#此時不會報錯,x=2,y=1,z=0
當使用關鍵字參數賦值時,可以更改位置。當位置參數與關鍵字參數混用時關鍵字參數不能寫在位置參數前面,且不能賦給已賦值的位置參數。例子:
def number(x,y,z=0):#z初始值為0 print(x) print(y) print(z) return x+y,x-z number(x=3,2,1)#報錯 number(2,x=1)#報錯 number(2,z=1,y=3)#不報錯,x=2,y=3,z=1
當賦入位置參數個數不確定時,可以將不確定個數個位置參數以元組的形式傳入。例子:
def number(*args):#z初始值為0 print(args) return 0 number(1,2,3) number(*[1,2,3])
當賦入關鍵字參數個數不確定時,可以將不確定個數個關鍵字參數以字典的形式傳入。例子:
def number(**kwargs):#z初始值為0 print(kwargs) return 0 number(age = 12,name = 'kai') number(**{'age':12,'name':'kai'})
終極混亂函數形式。字典形式應放在最後,原組放在字典前。例子:
def number(name,age=12,*args,**kwargs): print(name) print(age) print(args) print(kwargs) return 0 number('kai',22,sex='kai',age=5)#age報錯 number('kai',22,33,44,55,sex='men')#name=kai,age=22,args=(33,44,55),kwargs={'sex':'men'}
除了普通的函數,還有一種叫遞歸函數。遞歸函數是指函數內部可以調用其他函數,如果調用自己就是遞歸函數。遞歸函數必須有明確的結束條件,每進入更深一層,問題規模應該有所減少。
遞歸函數的運行效率低,並且,程式每調用一個函數,棧中會增加一層棧幀,每返回一個函數,棧中會減少一層棧幀。多層的遞歸函數容易導致棧溢出。
下麵將寫一個簡單的遞歸函數。例子:
def number(n): '''判斷奇偶''' if n-2>0: return number(n-2) else: return n
高階函數是接收另一個函數作為參數的函數。下麵將寫一個簡單的高階函數。例子:
def number(x,y,f):#這裡f作為某種函數被當作輸入參數 z = f(x)+f(y) return z sum(-3,9,sqrt)#sqrt開方函數
介紹了函數,就不得不講一下全局變數與局部變數。而這個定義與C++等其他語言中相似,所以不再贅述。在函數中想要修改或定義全局變數需要聲明global。但一般情況下不建議這樣做。
x = 3 def number(): global x x = 5 return 0 print(x)#x = 3 number() print(x)#x = 5
作業
對一個用戶文件實現增刪改查
流程圖:
主程式:
#-*- coding:UTF-8 -*- #Author:猛男落淚 #配置文件的增刪改查 import os #列印標題 title = '歡迎進入用戶管理系統' print(title.center(50,'-')) def option_error(): '''輸入錯誤提醒''' print('請輸入正確的選項編號!') quit_flag = True while quit_flag: back_flag = True print(''' 1.查詢用戶 2.增加用戶 3.刪除用戶 4.修改用戶 q.退出系統 ''') option = input('請輸入所需求的功能:') if option == 'q': #退出 quit_flag = False elif option.isdigit(): option = int(option) if option == 1: #查詢系統 while back_flag: info = input('請輸入要查詢的用戶姓名:') if info == 'b': back_flag = False elif info == 'q': back_flag = False quit_flag = False else: with open('user information.txt','r') as f: for line in f: if info in eval(line): print(eval(line)[info]) break else: option_error() elif option == 2: #增加系統 while back_flag: info = input('請輸入增加用戶的姓名,年齡,性別,職業(空格隔開,b返回q退出):') if info == 'b': back_flag = False elif info == 'q': back_flag = False quit_flag = False else: info = info.split() dic_info = {} dic = {} dic_info['年齡'] = info[1] dic_info['性別'] = info[2] dic_info['職業'] = info[3] dic[info[0]] = dic_info info = str(dic) with open('user information.txt','a') as f: f.write('%s\n' %info) f.flush()#強制刷新 print('%s保存成功!' %info) elif option == 3: #刪除系統 while back_flag: info = input('請輸入要刪除的用戶姓名:') if info == 'b': back_flag = False elif info == 'q': back_flag = False quit_flag = False else: f = open('user information.txt','r') f_new = open('user information_new.txt','w') for line in f: if info in eval(line): print('用戶刪除') break else: option_error() f.seek(0)#游標指針回歸 for line in f: if info in eval(line): continue f_new.write('%s' %line) f.close() f_new.close() os.remove('user information.txt') os.rename('user information_new.txt','user information.txt') elif option == 4: #修改系統 while back_flag: info = input('請輸入要修改的用戶姓名:') if info == 'b': back_flag = False elif info == 'q': back_flag = False quit_flag = False else: f = open('user information.txt','r') f_new = open('user information_new.txt','w') for line in f: if info in eval(line): info_new = input('請輸入要修改用戶的年齡,性別,職業(空格隔開):') info_new = info_new.split() dic_info = {} dic = {} dic_info['年齡'] = info_new[0] dic_info['性別'] = info_new[1] dic_info['職業'] = info_new[2] dic[info] = dic_info info_new = str(dic) print('%s保存成功!' %info_new) break else: option_error() f.seek(0)#游標指針回歸 for line in f: if info in eval(line): f_new.write('%s\n' %info_new) else: f_new.write('%s' %line) f.close() f_new.close() os.remove('user information.txt') os.rename('user information_new.txt','user information.txt') else: option_error() else: option_error() print('感謝你的使用!')
用戶信息文件:
user information.txt
{'凱凱王': {'年齡': '17', '性別': '男', '職業': '學生'}} {'賣力頭': {'年齡': '16', '性別': '男', '職業': '學生'}} {'飄飄流': {'年齡': '17', '性別': '男', '職業': '學生'}}