1. 程式人生 > >20181127(檔案指標,函式相關)

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)