Python學習筆記(第三天,文件操作、函數)
一、文件處理
1、文件打開模式
打開文本的模式,默認添加t,需根據寫入或讀取編碼情況添加encoding參數。
r 只讀模式,默認模式,文件必須存在,不能存在則報異常。
w 只寫模式,若文件不存在則創建,若文件已存在則清空內容,不可以讀文件。
a 追加模式,文件不存在則創建,若文件已存在則在文件末尾追加,不可以讀文件。
打開非文本的模式,使用“b”表示讀取和寫入需使用字節,不可指定編碼。主要有rb、wb、ab三種模式。
2、操作文件方法
讀取文件
with open(‘test.txt‘,‘r‘,encoding="UTF-8") as f:print(f.read()) #讀取文件全部內容 with open(‘test.txt‘, ‘r‘, encoding="UTF-8") as f: print(f.readlines()) # 讀取文件每行內容,存入列表 with open(‘test.txt‘, ‘r‘, encoding="UTF-8") as f: print(f.readline()) # 讀取文件一行內容 with open(‘test.txt‘,‘rb‘) as f: print(f.read()) #字節讀取模式讀取文件全部內容
文件寫入
with open(‘test1.txt‘,‘w‘,encoding="UTF-8") as f: f.write("hello world!\n") #文本模式,需添加換行符 with open(‘test1.txt‘,‘w‘,encoding="UTF-8") as f: f.writelines(["hello\n","world\n"]) #文本模式,需添加換行符 with open(‘test1.txt‘,‘wb‘) as f: f.write("hello world".encode("utf-8")) #b模式需對字符先編碼 with open("test1.txt",‘wb‘) as f: f.writelines(["hello\n".encode("utf-8"),"world\n".encode("utf-8")]) #b模式需對字符串手動編碼
其他操作
import time f = open("test1.txt",‘w‘,encoding="UTF-8") #b模式沒有encoding print(f.writable()) #文件是否看可寫 print(f.readable()) #文件是否可讀 f.write("aa") f.flush() #立刻將文件內容從內容刷入硬盤 time.sleep(5) f.close() #文件關閉,無flush時,關閉文件內容才刷入硬盤
3.文件內光標的移動
1.read(3)
文件打開方式為文本時,代表讀取三個字符。
文件打開方式為b時,代表讀取三個字節。
2.除read外,其他文件光標移動均以字節為單位,入seek,tell,truncate
with open("test.txt",‘r‘,encoding="UTF-8") as f: f.seek(4,0) #第一個參數表示移動的相對位置,第二個參數為0表示移動到文件開頭,1表示就在當前位置,2表示移動到文件末尾 print(f.read()) print(f.tell()) #返回光標當前位置,執行為read()後為文件末尾 #truncate為截斷文件,文件必須可寫,不可使用w或w+模式,會清空文件,建議使用r+或者a或a+模式 with open("test.txt",‘r+‘,encoding="UTF-8") as f: f.truncate(7) #截取前7個字節的內容。
4.文件的修改
方式一,將文件從硬盤讀入內存,內存中修改完後,寫入新文件後替換原文件。文件過大讀入內存時會卡死。
import os with open("test.txt",‘r‘) as read_f,open(".test.txt.swap",‘w‘) as write_f: data = read_f.read() data = data.replace("xxx","eee") #字符不可變,需重新賦值給data write_f.write(data) os.remove("test.txt") os.rename(".test.txt.swap","test.txt")
方式二,將文件每行讀入內存,按行修改,修改完後寫入新文件,完成後替換原文件。
import os with open("test.txt",‘r‘) as read_f,open(".test.txt.swap",‘w‘) as write_f: for line in read_f: if "xxx" in line: line = line.replace("xxx","eee") write_f.write(line) os.remove("test.txt") os.rename(".test.txt.swap","test.txt")
二、函數基礎
使用函數的目的:解決代碼組織結構不清晰、可讀性差的問題;減少代碼冗余;降低維護難度,提高可擴展性。
函數主要分為內置函數和自定義函數。
1.函數定義和調用
定義函數
#語法 def 函數名(參數1,參數2,參數3,...): ‘‘‘註釋‘‘‘ 函數體 return 返回的值 #函數名要能反映其意義
函數使用的原則為:先定義後使用
函數在定義階段只檢測語法,不執行代碼,無法發現代碼中的邏輯錯誤。
2.函數的參數
位置參數:按照從左到右順序定義的參數。
位置形參:必選參數
位置實參:按照位置給形參傳值
關鍵字參數:按照鍵值對形式定義的參數。
實參和形參位置不必一一對應
關鍵字實參必須在位置實參的右側
對同一個形參不能重復傳值
默認參數:形參在定義時已進行賦值
可已傳值也可以不傳,經常需要變的參數定義為位置形參,變化小的定義為默認形參
只在定義時賦值一次,且為不可變類型
默認參數定義在位置形參右側
可變長參數:實參值個數不固定
使用*args接收位置實參,使用**kwargs接收關鍵字實參,*後的參數必須被傳值,必須按照關鍵字實參的形式傳遞。
def func(*args,**kwargs): print(args,kwargs) func(3,4,5,66,a=33,b="asf",c=222) #前面的位置實參被args以元組方式接收,後面的關鍵字實參被kwargs以字典方式接收
def func(x,y,*args,a=1,b,**kwargs): print(x,y) print(args) print(a) print(b) print(kwargs) func(1,2,3,4,5,b=3,c=4,d=5)
三、函數對象、函數嵌套、名稱空間與作用域、裝飾器
1.函數對象的特點:
可以被引用
可以當做參數傳遞
返回值可以是函數
可以當做容器類型的元素
def func1(): print("from func1") return func2 #返回func2 def func2(): print("from func2") list = [] list.append(func1()) #返回func2作為列表元素 list[0]() #執行func2
2.函數的嵌套
def func1(): print("from func1") def func2(): print("from func2") def func3(): print("from func3") func3() func2() func1()
3.名稱空間和作用域
名稱空間為內存中存放名字和值綁定關系的地方,如變量名和變量值的地址的對應關系。主要分為內置名稱空間、全局名稱空間和局部名稱空間。
名稱空間加載順序為:
- python解釋器先啟動時加載內置名稱空間
- 執行py文件時,加載全局名稱空間,程序結束運行後釋放空間
- 執行文件過程中如果調用函數,臨時產生局部名稱空間,函數調用結束後釋放空間
名字的查找順序和加載順序相反,為先局部名稱空間,再全局名稱空間,最後內置名稱空間。全局無法查看局部,局部可以查看全局。
#優先在func()局部名稱空間中找max,如果沒有在全局找,如果還沒有在返回內置名稱空間中的max max = 3 def func(): max = 1 print(max) func()
全局作用域:包括內置名稱和全局名稱空間的名字,全局存活,全局有效,globals()
局部作用域:局部名稱空間的名字,臨時存活,局部有效,locals()
xxx=2222 yyy="dsfsf" print(globals()) print(locals()) #全局作用域中調用locals()相當於調用globals() def func(): zzzzz=[1,2,3,4] print(locals()) print(globals()) #僅比前面的globals多了func函數名字,無func函數中定義的變量名字 func()
函數的作用域關系在函數定義階段已經固定,與調用位置無關。
xxx = "abc" def outter(): def innner(): print("inner",xxx) return innner f = outter() def bar(): x=123456 f() #f()實際上就是inner(),調用時局部作用域中無xxx,則去全局作用域中找,無法調用bar()中的xxx bar()
4.閉包函數
閉包函數為定義在函數內部的函數,函數體代碼保護對外部作用域(不是全局作用域)名字的引用,包在外面的函數通常將閉包函數用return返回,然後可以在任意使用。
z =1 def outter(): x = 1 y = 2 def inner(): print(x,y) return inner f =outter() print(f.__closure__[0].cell_contents) #返回閉包函數中第一個引用外部名字的值
閉包函數主要作為用向函數傳值。因為返回的函數對象包裹了一層作用域,無論在何處調用,優先使用自己外層的作用域。
#普通的調用方法,每次執行時需傳入參數。 import requests def get(url): response = requests.get(url) if response.status_code == 200: print(len(response.text)) get("https://www.baidu.com") #使用閉包函數後,參數由外部函數傳入,方便執行 import requests def outter(url) def get(): response = requests.get(url) if response.status_code == 200: print(len(response.text)) return get baidu = outter("https://www.baidu.com") baidu()
5.裝飾器
裝飾器可以是任意調用對象,被裝飾者可以是任意可調用函數。
裝飾器原則為:不修改被裝飾對象的源代碼;不修改被裝飾對象的調用方式。(即對修改封閉,對擴展開放)
裝飾器目標為在滿足原則的條件下,為被裝飾對象添加新功能。主要通過外層函數為內層函數傳遞被裝飾函數,然後在內層函數中執行被裝飾函數。
無參數的裝飾器:
import time def index(): time.sleep(3) print("welcome to index") def outter(func): def inner(): start = time.time() func() stop = time.time() print("run time is %s"%(stop-start)) return inner index = outter(index) index()
被修飾函數有參數的情況
import time def index(name): time.sleep(3) print("welcome %s to index" % name) def outter(func): def inner(*args,**kwargs): start = time.time() func(*args,**kwargs) stop = time.time() print("run time is %s" %(stop-start)) return inner index = outter(index) index("xxx")
有參數裝飾器,裝飾器外層做多只需要兩層,最內層傳入被裝飾函數的參數。外一層傳入被裝飾函數名,返回內層函數。最外層傳入內層函數需要引入的其他參數,返回中間層的函數名。
def auth(driver=‘file‘): def auth2(func): def wrapper(*args,**kwargs): name = input("input user:") password = input("input password") if driver == "file": if name=="xxx" and password=="123": print("login success") return func(*args,**kwargs) elif driver == "ldap": print("ldap") return wrapper return auth2 @auth(driver="file") def foo(name): print("welcome "+name) foo("xxx")
裝飾器語法
import time def outter(func): def inner(*args,**kwargs): start = time.time() func(*args,**kwargs) stop = time.time() print("run time is %s" %(stop-start)) return inner @outter #相當於index=outter(index),裝飾器函數必須在被修飾函數上方定義 def index(name): time.sleep(3) print("welcome %s to index" % name) #index = outter(index) index("xxx")
裝飾器補充:wraps
from functools import wraps def deco(func): @wraps(func) #將傳入被裝飾函數的信息賦給內層函數,入幫助文檔等。 def wrapper(*args,**kwargs): return(func(*args,**kwargs)) return wrapper @deco def index(): "原始index的幫助文檔" print("from index") print(index.__doc__)
Python學習筆記(第三天,文件操作、函數)