20181127(檔案指標,函式相關)
一、檔案內指標的移動f.seek
強調:只有t模式下的read(n),n代表的是字元個數,除此以外都是以位元組為單位。
with open('a.txt',mode='rt',encoding='utf-8') as f:
res=f.read(4) # 讀取前四個字元
print(res)
with open('a.txt',mode='rb') as f:
res=f.read(3) # 讀取前三個位元組
print(res.decode('utf-8')) #將位元組解碼
with open('a.txt',mode='at',encoding='utf-8') as f:
f.truncate(3) #截斷a.txt中的內容,取前三個字元。此方法用於從檔案的首行首字元開始截斷,截斷檔案為 *個字元,無*表示從當前位置截斷;截斷之後,後面的所有字元被刪除,其中 Widnows 系統下的換行代表2個字元大小。
f.seek():指標移動是以位元組為單位
三種模式:只有0模式可以在t\b模式下都可以使用,1,2只能在b模式下使用。
0(預設):參照檔案開頭
with open('c.txt',mode='rt',encoding='utf-8') as f:
f.seek(3,0)
print(f.tell()) #file.tell() 方法返回檔案的當前位置,即檔案指標當前位置。
print(f.read())
1:參照指標當前所在位置
with open('c.txt',mode='rb') as f:
f.read(2)
f.seek(3,1)
print(f.tell())
print(f.read().decode('utf-8')) #讀取的是位元組,所以顯示的時候需要解碼
2:參照檔案末尾
with open('c.txt',mode='rb') as f:
f.seek(-3,2)
print(f.tell())
print(f.read().decode('utf-8'))
tail -f acces.log小程式:開啟檔案,指標跳到檔案末尾,不停監測是否有新內容,如果有則顯示出來。
先建立檔案,如access.log:
aaa
bbb
#檔案要直接換一行
再建立一個寫入程式,如run.py:
with open('access.log',mode='at',encoding='utf-8') as f: #檔案模式為at(追加,字串模式)
f.write('666\n') # \n為自動換行符,寫入之後則自動換行
編寫檢測程式:
import time #輸入time模組(因為不需要讓檢測程式一直不停的工作,如果一直不停的迴圈,CPU佔用過多)
with open('access.log',mode='rb') as f: # 只讀模式即可
f.seek(0,2) #2即把指標放到檔案末尾,0代表指標不做移動
while True: #建立迴圈
line=f.readline() #readline從檔案讀取整行,包括 "\n" 字元,一行一行讀取
if len(line) == 0: # 行的長度等於0,即表示空,沒有新增內容
time.sleep(0.1) #計算機休息0.1s
else:
print(line.decode('utf-8'),end='') # 開啟是以二進位制開啟的,所以需要解碼過程,且寫入程式自帶換行符,所以此處列印時,不要再有換行符了
二、函式
1.什麼是函式:組織好的,可重複使用的,用來實現單一或相關聯功能的程式碼塊。
在程式具備某一功能的工具=》函式
事先準備好工具=》函式的定義
遇到應用場景,拿來就用=》函式的呼叫
分成兩大類:
①內建函式
②自定義函式
2.為什麼用函式
Ⅰ程式碼冗餘
Ⅱ程式的組織結構不清晰,可讀性差
Ⅲ擴充套件性差
3.如何用函式
函式的使用必須遵循一個原則:
①先定義 #定義階段,只檢測語法,不執行程式碼
定義語法:
def 函式名(參1,參2。。。): #可以沒有引數
"""
文件註釋
"""
程式碼1
程式碼2
。。。
return 值 #可以沒有返回值 ,沒有return語句相當於返回None
②後呼叫 #呼叫階段,開始執行函式體程式碼
函式名()
在呼叫/輸出函式之前把相關函式及變數都設定好就可以了。
在定義階段,只會檢測python的語法,不會執行程式碼。也就是說,只要語法對,就能夠定義(至於執行程式碼時會不會報錯再說)。
在呼叫階段,才會開始執行函式體程式碼。
def foo():
print('from foo')
bar()
def bar():
print('from bar')
foo() #程式碼能夠正常執行,只要在呼叫程式碼之前把函式定義正確/完整就可以了。
#說明:函式呼叫可以看作程式執行流程中的一個迂迴路徑,遇到函式呼叫時,並不會直接繼續執行下一條語句,而是跳到函式體的第一行,繼續執行完函式程式碼塊中的所有語句,再跳回原來離開的地方,
三、定義函式的三種形式
1、無參函式
def func():
print('from func')
func()
2、有參函式
def max2(x,y):
if x > y:
print(x)
else:
print(y)
max2(1,2)
3、空函式
def register():
pass
四、呼叫函式的三種方式
1、語句形式
def func():
print('from func')
func()
2、表示式形式:有返回值的才行
def max2(x,y):
if x > y:
return x
else:
return y
res=max2(2,3)
print(res)
3、函式的呼叫可以當做另外一個函式的引數傳入
def max2(x,y):
if x > y:
return x
else:
return y
res=max2(max2(1,2),3)
print(res)
五、函式的返回值
1.什麼是函式的返回值:
返回值是函式體程式碼的執行成果
2.為何要有返回值
需要拿到函式的處理結果做進一步的處理,則函式必須有返回值
3.如何用:
return返回值的特點:
Ⅰ返回值沒有型別限制,也沒有個數限制
return或者函式沒return:返回值是None
return值:返回的就是該值本身
return值1,值2。。。返回元組(值1,值2)
Ⅱreturn是函式結束執行的標誌,函式內可以有多個return,但只要執行一次函式就會立即結束,並且將return後的值當做本次呼叫的結果返回
def test():
print('111')
return 666
print('222')
return gogogo
test()
print(test())
#輸出結果為:
111
111
666
六、函式引數的使用
Ⅰ函式的引數分為兩大類:
1.形參:在定義函式時括號內指定的引數(變數名),稱之為形參
2.實參:在呼叫函式時括號內傳入的值(變數值),稱之為實參
二者的關係:在呼叫函式時,實參值(變數值)會傳給形參(變數名),這種繫結關係在呼叫函式時生效,呼叫結束後解除繫結。
Ⅱ函式引數詳解
1.形參:
1.1位置形參:在定義階段,按照從左到右的順序依次定義的形參
特點:必須被傳值
def func(x,y,z):
print(x,y,z)
func(1,2,3) #正常輸出
func(1,2,3,4) #報錯
func(1,2) #報錯
1.2預設引數:在定義階段,就已經為某個形參賦值,該形參稱之為預設形參
特點:在定義階段就已經有值,在呼叫階段可以不用為其傳值。
注意點:位置形參必須放在預設形參前面,也就是說非預設引數要放在預設引數的前面。
def fuc(x,y,z=666):
print(x,y,z)
fuc(x=1,y=2)
輸出結果為:
1 2 666
1.3形參中*與**的用法:
①形參中帶*:*會將溢位的位置實參存成元組的形式然後賦值其後變數名
def func(x,y,*args):
print(x,y,args)
func(1,2,3,4,5,6)
輸出結果為:
1 2 (3, 4, 5, 6)
②形參中帶**:**會將溢位的關鍵字實參存成字典的格式然後賦值其後的變數名。
def func(x,y,**kwargs):
print(x,y,kwargs)
func(1,y=2,z=3,m=1,n=2)
輸出結果為:
1 2 {'z': 3, 'm': 1, 'n': 2}
def test(a,*args,**kwargs):
print a
print args
print kwargs
test(1,2,3,d='4',e=5)
輸出結果:
1
(2, 3) #簡單說,對於不是鍵值對的,*args儲存成元組。而有=的,則用**kwargs儲存成字典
{'e': 5, 'd': '4'}
2.實參
2.1位置實參:在呼叫階段,按照從左到右的順序依次傳入的值(傳值的一種格式)
特點:這種傳值方式會與形參一一對應
2.2關鍵字實參:在呼叫階段,按照key=value的格式傳值
特點:可以完全打亂位置,但仍然能為指定的形參傳值
注意:可以混用關鍵字實參與位置實參,但是
①同一個形參是能被賦值一次
def fuc(x,y,z):
print(x,y,z)
fuc(x=1,y=2,z=3)
輸出結果為:
1 2 3
def fuc(x,y,z):
print(x,y,z)
fuc(x=1,y=2,z=3,x=66)
輸出結果會報錯
②位置實參必須在關鍵字實參的前面,否則會報語法錯誤
def fuc(x,y,z):
print(x,y,z)
fuc(1,z=3,y=2)
輸出結果為:
1 2 3
def fuc(x,y,z):
print(x,y,z)
fuc(x=1,2,z=3)
輸出結果會報錯
def fuc(x,y,z):
print(x,y,z)
fuc(1,x=2,z=3)
此種情況也會報錯,會顯示x被賦值兩次
2.3實參中*與**的用法:
①實參中帶*:先將實參打散成位置實參,然後再與形參做對應。
def func(x,y,z):
print(x,y,z)
func(1,[2,3]) #會報錯
func(*[1,2,3]) #輸出結果為1 2 3
func(*'hello') #會報錯,因為給了五個值
func(*'hel') #輸出h e l
②實參中帶**:先將實參打散成關鍵字實參,然後再與形參做對應
def func(x,y,z):
print(x,y,z)
func(**{'x':1,'z':3,'y':2}) #func(z=3,y=2,x=1),此處字典key必須與形參名一致!
輸出結果為:1 2 3
3.可變長引數
可變長指的是實參值的個數不固定,而實參有按位置和按關鍵字兩種形式定義。
針對這兩種形式的可變長,形參對應有兩種解決方案來完整地存放它們,分別是*args,**kwargs
===========*args===========
def foo(x,y,*args):
print(x,y)
print(args)
foo(1,2,3,4,5)
輸出結果:
1 2
(3, 4, 5)
def foo(x,y,*args):
print(x,y)
print(args)
foo(1,2,*[3,4,5])
輸出結果為:
1 2
(3, 4, 5)
def foo(x,y,z):
print(x,y,z)
foo(*[1,2,3])
輸出結果為:
1 2 3
===========**kwargs===========
def foo(x,y,**kwargs):
print(x,y)
print(kwargs)
foo(1,y=2,a=1,b=2,c=3)
輸出結果為:
1 2
{'a': 1, 'b': 2, 'c': 3}
def foo(x,y,**kwargs):
print(x,y)
print(kwargs)
foo(1,y=2,**{'a':1,'b':2,'c':3})
輸出結果為:
1 2
{'a': 1, 'b': 2, 'c': 3}
def foo(x,y,z):
print(x,y,z)
foo(**{'z':1,'x':2,'y':3})
輸出結果為:
2 3 1
===========*args+**kwargs===========
def foo(x,y):
print(x,y)
def wrapper(*args,**kwargs):
foo(*args,**kwargs)