1. 程式人生 > >Python學習筆記(第三天,文件操作、函數)

Python學習筆記(第三天,文件操作、函數)

input 釋放空間 打開方式 只需要 不能 解決 信息 無法查看 一個

一、文件處理

  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學習筆記(第三天,文件操作、函數)