1.1 文件處理 1.1.1 打開文件過程 在Python中,打開文件,得到文件句柄並賦值給一個變數,預設打開模式就為r f=open(r'a.txt','w',encoding='utf-8') print(f.writable()) f.write('1111\n') f.write('2222 ...
1.1 文件處理
1.1.1 打開文件過程
在Python中,打開文件,得到文件句柄並賦值給一個變數,預設打開模式就為r
f=open(r'a.txt','w',encoding='utf-8') print(f.writable())
通過句柄對文件進行操作
f.write('1111\n') f.write('2222\n') f.writelines(['3333\n','444\n'])
關閉文件
f.close()
1.1.2 打開文件過程分析
1、由應用程式向操作系統發起系統調用open(...)
2、操作系統打開該文件,並返回一個文件句柄給應用程式
3、應用程式將文件句柄賦值給變數f
1.1.3 註意要點:
第一點:
打開一個文件包含兩部分資源:操作系統級打開的文件+應用程式的變數。在操作完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,回收方法為:
1、f.close() #回收操作系統級打開的文件
2、del f #回收應用程式級的變數
其中del f一定要發生在f.close()之後,否則就會導致操作系統打開的文件還沒有關閉,白白占用資源,而python自動的垃圾回收機制決定了我們無需考慮del f,這就要求我們,在操作完畢文件後,一定要記住f.close()
為避免忘記忘記f.close(),使用with關鍵字來幫我們管理
with open('a.txt','w') as f: pass with open('a.txt','r') as read_f,open('b.txt','w') as write_f: data=read_f.read() write_f.write(data)
強調第二點:
f=open(...)是由操作系統打開文件,那麼如果我們沒有為open指定編碼,那麼打開文件的預設編碼很明顯是操作系統說了算了,操作系統會用自己的預設編碼去打開文件,在windows下是gbk,在linux下是utf-8。
這就用到了上節課講的字元編碼的知識:若要保證不亂碼,文件以什麼方式存的,就要以什麼方式打開。
f=open('a.txt','r',encoding='utf-8')
1.1.4 三種模式:a,r,b
打開文件的模式有(預設為文本模式)
1.1.5 a:之追加寫模式(不可讀;不存在則創建;存在則只追加內容)
文件不存在則創建,文件存在那麼在打開文件後立刻將游標移動到文件末尾,進行追加寫
f=open(r'b.txt','a',encoding='utf-8') print(f.writable()) f.write('4444\n') f.write('5555\n') f.writelines(['66666\n','7777\n']) f.close()
1.1.6 r:只讀模式(預設模式,文件必須存在,不存在則拋出異常)
f=open(r'b.txt','r',encoding='utf-8') print(f.writable()) print(f.read()) print(f.readlines()) print(f.readline(),end='') print(f.readline(),end='') f.close()
with open('b.txt','r',encoding='utf-8') as f: while True: line=f.readline() if len(line) == 0:break print(line) print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline()) print('第八次',f.readline()) # for line in f: print(line)
1.1.7 w,只寫模式(不可讀;不存在則創建;存在則清空內容)
1.1.8 b:bytes表示以位元組的方式操作(而所有文件也都是以位元組的形式存儲的,使用這種模式無需考慮文本文件的字元編碼、圖片文件的jgp格式、視頻文件的avi格式)
with open('111.png','rb') as f: print(f.read())
with open('b.txt','rb',) as f: print(f.read().decode('utf-8'))
with open('b.txt','rt',encoding='utf-8') as f: print(f.read())
with open('b.txt','wb') as f: res='中問'.encode('utf-8') print(res,type(res)) f.write(res)
with open('b.txt','ab') as f: res='哈哈哈'.encode('utf-8') print(res,type(res)) f.write(res)
註:以b方式打開時,讀取到的內容是位元組類型,寫入時也需要提供位元組類型,不能指定編碼
1.2 字元編碼補充
#encoding:utf-8 with open('b.txt','rt',encoding='utf-8') as f: print(f.read())
1.3 操作文件的方法
1.3.1 文件修改
文件的數據是存放於硬碟上的,因而只存在覆蓋、不存在修改這麼一說,我們平時看到的修改文件,都是模擬出來的效果,具體的說有兩種實現方式:
1.3.1.1 利用b模式,編寫一個cp工具,要求如下:
1. 既可以拷貝文本又可以拷貝視頻,圖片等文件
2. 用戶一旦參數錯誤,列印命令的正確使用方法
提示:可以用import sys,然後用sys.argv獲取腳本後面跟的參數
方式一:將硬碟存放的該文件的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟(word,vim,nodpad++等編輯器)
import os with open('info.txt','r',encoding='utf-8') as read_f,open('.info.txt.swap','w',encoding='utf-8') as write_f: data=read_f.read() write_f.write(data.replace('alex','SB')) os.remove('info.txt') os.rename('.info.txt.swap','info.txt')
方式二:將硬碟存放的該文件的內容一行一行地讀入記憶體,修改完畢就寫入新文件,最後用新文件覆蓋源文件
import os with open('info.txt', 'r', encoding='utf-8') as read_f, open('.info.txt.swap', 'w', encoding='utf-8') as write_f: for line in read_f: if 'SB' in line: line=line.replace('SB','alex') write_f.write(line) os.remove('info.txt') os.rename('.info.txt.swap', 'info.txt')
cp複製命令的實現
1、源大小的問題:
2、文件打開模式的問題:b
#!/usr/bin/env python import sys _,src_file,dst_file=sys.argv with open(src_file,'rb') as read_f,\ open(dst_file,'wb') as write_f: # data=read_f.read() # write_f.write(data) for line in read_f: write_f.write(line) write_f.flush()
1.3.2 文件內游標的移動
f.read() #讀取所有內容,游標移動到文件末尾
f.readline() #讀取一行內容,游標移動到第二行首部
f.readlines() #讀取每一行內容,存放於列表中
f.write('1111\n222\n') #針對文本模式的寫,需要自己寫換行符
f.write('1111\n222\n'.encode('utf-8')) #針對b模式的寫,需要自己寫換行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
1.3.2.1 : read(3):
1. 文件打開方式為文本模式時,代表讀取3個字元
2. 文件打開方式為b模式時,代表讀取3個位元組
1.3.2.2 : 其餘的文件內游標移動都是以位元組為單位如seek,tell,truncate
註意:
1. seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的
2. truncate是截斷文件,所以文件的打開方式必須可寫,但是不能用w或w+等方式打開,因為那樣直接清空文件了,所以truncate要在r+或a或a+等模式下測試效果
1.3.2.3 基於seek實現tail -f功能
with open('a.txt','r',encoding='utf-8') as f: data1=f.read() print('==1==>',data1) print(f.tell()) data2=f.read() print('==2==>',data2)
只有一種情況游標以字元為單位:文件以rt方式打開,read(3)
with open('c.txt','rt',encoding='utf-8') as f: print(f.read(6)) print(f.tell()) f.seek(0,0) print(f.read(6)) f.seek(6,0) f.seek(8,0) print(f.read())
with open('c.txt','rb',) as f: f.seek(6,0) # f.seek(8,0) print(f.read())
with open('c.txt','rb') as f: print(f.read(6)) f.seek(2,1) print(f.tell()) print(f.read().decode('utf-8'))
1.4 函數基礎
1.4.1 為什麼要有函數?沒有函數帶來的困擾?
Ø 組織結構不清晰,可讀性差
Ø 代碼冗餘
Ø 可擴展性差
1.4.2 什麼是函數
具備某一個功能的工具---》函數
事先準備工具-》函數的定義
拿來就用、重覆使用-》函數的調用
ps:先定義後調用
1.4.3 函數的分類:
內置函數:len,max(10,11),help(函數名)
自定義函數:def
語法:
def 函數名(參數1,參數2,...):
"""註釋"""
函數體
return 返回值
'''
#'函數即是變數'
def print_tag(): print('*'*20) def print_msg(): #print_msg=<function print_msg at 0x00000000027EA8C8> print('hello world') print(print_msg) print(print_tag) print_tag() print_msg() print_tag()
1.4.4 定義函數階段都發生了什麼事:只檢測語法,不執行代碼
1.4.4.1 定義階段
sex='male' def auth(): sex name=input('name>>: ').strip() password=input('password>>: ').strip() if name =='egon' and password == '123': print('login successfull') else: print('user or password err')
1.4.4.2 調用階段
auth()
1.4.5 函數的使用:先定義後調用
def bar(): print('from bar') def foo(): print('from foo') bar() foo()
定義階段 def foo(): print('from foo') bar() 定義階段 def bar(): print('from bar') 調用 def bar(): print('from bar')
1.4.6 定義函數的三種形式
1、無參:應用場景僅僅只是執行一些操作,比如與用戶交互,列印
2、有參:需要根據外部傳進來的參數,才能執行相應的邏輯,比如統計長度,求最大值最小值
3、空函數:設計代碼結構
1.4.6.1 第一種:無參函數
def auth(): name=input('name>>: ').strip() password=input('password>>: ').strip() if name =='egon' and password == '123': print('login successfull') else: print('user or password err')
1.4.6.2 第二種:有參函數
def my_max(x,y): if x >= y: print(x) else: print(y) my_max(1,2)
1.4.6.3 第三種:空函數
def auth(name,password): if name =='egon' and password == '123': print('login successfull') else: print('user or password err') def interactive(): name=input('name>>: ').strip() password=input('password>>: ').strip() auth(name,password) interactive()
1.4.7 結論:
1、定義時無參,意味著調用時也無需傳入參數
2、定義時有參,意味著調用時則必須傳入參數
1.4.8 程式的體繫結構
def auth(): pass def put(): pass def get(): pass def ls(): pass
1.5 函數的返回值
無return->None
return 1個值->返回1個值
return 逗號分隔多個值->元組
1.5.1 return的特點:
1、 函數內可以有多個return,但是只能執行一次return
2、 執行return函數就立刻結束,並且return的後值當做本次調用的結果返回
1.5.1.1 什麼時候該有返回值?
調用函數,經過一系列的操作,最後要拿到一個明確的結果,則必須要有返回值
通常有參函數需要有返回值,輸入參數,經過計算,得到一個最終的結果
1.5.1.2 什麼時候不需要有返回值?
調用函數,僅僅只是執行一系列的操作,最後不需要得到什麼結果,則無需有返回值
通常無參函數不需要有返回值
1.5.2 函數調用的三種形式
1.5.2.1 語句形式:foo()
def foo(x,y): return x+y res=foo(1,2) def my_max(x,y): if x >= y: return x else: return y res=my_max(1,2) print(res)
def foo(): print('first') return 1 print('second') return 2 print('third') return 3 res=foo() print(res)
1.6 函數的參數
1.6.1 函數的參數分類兩種:
形參:在定義階段括弧內指定的參數,相當於變數名
實參:在調用階段括弧內傳入的值稱之為實參,相當於值
1.6.2 在調用階段,實參的值會綁定給形參,在調用結束後解除綁定
def foo(x,y): #x=1,y=2 print(x,y) foo(1,2)
1.6.3 在python中參數的分類:
1.6.3.1 位置參數:按照從左到右的順序依次定義的參數
位置形參:必須被傳值,多一個少一個都不行
位置實參:與形參一一對應傳值
def foo(x,y): print(x,y) foo(2,1)
1.6.3.2 關鍵字參數:在函數調用時,按照key=value的形式定義的實參
特點:指名道姓地給形參傳值,不再依賴與位置
def foo(name,age,sex): print(name,age,sex) foo('egon',18,'male') foo(sex='male',age=18,name='egon',)
註意:
1、 關鍵字實參必須在位置實參的後面
2、 不能為同一個參數賦值多次
foo('egon',sex='male',age=18,name='egon')
1.6.3.3 預設參數:在函數定義階段,就已經為形參賦值了
特點:定義階段已經有值意味著調用階段可以不用傳值
位置參數通常用於經常變化的參數,而預設參數指的是大多數情況下都一樣的
def foo(x,y=1): print(x,y) foo(1,2) foo(y=3,x=1) foo(111) foo(x=1111)
def register(name,age,sex='male'): print(name,age,sex) register('egon1',18) register('egon2',18) register('egon3',18) register('alex',38,'female')
註意:
1、預設參數必須放到位置形參的後面
def register(name,sex='male',age,): print(name,age,sex)
2、預設參數的值只在定義時被賦值一次
3、預設的參數的值通常應該是不可變類型
res=1 def foo(x,y=res): print(x,y) res=10 foo('aaaaaaaa')
1.6.3.4 可變長參數:在調用函數時,實參值的個數不固定
實參的形式有:位置實參和關鍵字實參,
形參的解決方案:*,**
Ø *args的用法
def foo(x,y,*args): #z=(3,4,5,6) print(x,y) print(args) foo(1,2,3,4,5,6) foo(1,2,*[3,4,5,6]) #foo(1,2,3,4,5,6) foo(*[1,2,3,4,5,6]) #foo(1,2,3,4,5,6) def foo(x,y): print(x,y) foo(*(1,2)) #foo(1,2)
Ø **kwargs
def foo(x,y,**kwargs): #kwargs={'c':5,'a':3,'b':4} print(x,y) print(kwargs) foo(y=2,x=1,a=3,b=4,c=5) foo(y=2,**{'c':5,'x':1,'b':4,'a':3}) #foo(y=2,a=3,c=5,b=4) def foo(name,age): print(name,age) foo(**{'name':'egon','age':18}) foo({'name':'egon','age':18}) def bar(x,y,z): print(x,y,z)
def wrapper(*args,**kwargs): #args=(1,),kwargs={'z':2,'y':3} # print(args,kwargs) bar(*args,**kwargs) #bar(*(1,),**{'z':2,'y':3}) #bar(1,z=2,y=3,) wrapper(1,z=2,y=3)
1.6.3.5 命名關鍵字參數:指的是定義在*後的參數,該參數必須被傳值(除非有它有預設值),而且必須按照key=value的形式傳值
def foo(x,y,*args,m=100000,n): print(x,y) print(args) print(m,n) foo(1,2,3,n=4,)
1.7 函數的對象
1.7.1 函數是第一類對象:指的是函數可以當做數據傳遞
1.7.1.1 可以被引用 x=1,y=x
def func(x,y): print(x,y) f=func f(1,2)
1.7.1.2 可當做函數的參數傳入
def foo(): print('from foo') def bar(func): # print(func) func() bar(foo)
1.7.1.3 可以當做函數的返回值
def foo(): print('from foo') def bar(): return foo f=bar() f()
1.7.1.4 可以當做容器類型的元素
def foo(): print('from foo') def bar(): return foo l=[foo,bar] print(l) l[0]()
def get(): print('get') def put(): print('put') def ls(): print('ls') cmd=input('>>: ').strip() if cmd == 'get': get() elif cmd == 'put': put() elif cmd == 'ls': ls() def get(): print('get') def put(): print('put') def ls(): print('ls') def auth(): print('auth') func_dic={ 'get':get, 'put':put, 'ls':ls, 'auth':auth } # func_dic['put']() cmd = input('>>: ').strip() if cmd in func_dic: func_dic[cmd]()
1.8 函數的嵌套
1.8.1 函數的嵌套調用
def my_max(x,y): if x >= y: return x else: return y
def my_max4(a,b,c,d): res1=my_max(a,b) res2=my_max(res1,c) res3=my_max(res2,d) return res3
1.8.2 函數的嵌套定義
def f1(): def f2(): print('from f2') def f3(): print('from f3') f3() # print(f2) f2() f1()
1.9 名稱空間
名稱空間指的是:存放名字與值綁定關係的地方,
1.9.1 內置與全局名稱空間
內置名稱空間(python解釋器啟動就有):python解釋器內置的名字,max,len,print
全局名稱空間(執行python文件時生效):文件級別定義的名字
x=1 def func():pass import time if x == 1: y=2 #局部名稱空間(函數調用時生效,調用結束失效):函數內部定義的名字 func()
1.9.2 載入與訪問順序
載入順序:內置---》全局----》局部名稱空間
訪問名字的順序:局部名稱空間===》全局----》內置
x=1
print(x)
#print(max) max=2 def func(): # max=1 print(max)
func() x='gobal' def f1(): # x=1 def f2(): # x=2 def f3(): # x=3 print(x) f3() f2() f1()
1.9.3 全局與局部作用域
全局作用域(全局範圍):內置名稱空間與全局名稱空間的名字,全局存活,全局有效,globals()
局部作用域(局部範圍):局部名稱空間的名字,臨時存活,局部有效,locals()
#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=111111111111111111111 print(globals()) print(dir(globals()['__builtins__'])) print(locals() is globals()) def func(): # yyyyyyyyyyyyyyyyyyyyyyyy=22222222 print(globals()) print(locals()) func() x=100 def func(): global x x=1 func() print(x) x='global' def f1(): # x=1 def f2(): nonlocal x x=0 f2() print('===f1 innter--->',x) f1() print(x)
1.9.4 強調兩點:
1.9.4.1 打破函數層級限制來調用函數
def outter(): def inner(): print('inner') return inner f=outter() # print(f) def bar(): f() bar()
1.9.4.2 函數的作用域關係是在函數定義階段就已經固定了,與調用位置無關
x=1 def outter(): # x=2 def inner(): print('inner',x) return inner f=outter() # print(f) # x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111 def bar(): x=3 f() # x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111 bar() x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111
1.10 閉包函數
閉包函數:
1 定義在函數內部的函數
2 該函數的函數體代碼包含對外部作用域(而不是全局作用域)名字的引用
3 通常將閉包函數用return返回,然後可以在任意使用
z=1 def outer(): x=1 y=2 def inner(): print(x,y) # print(z) return inner f=outer() print(f.__closure__[0].cell_contents) print(f.__closure__[1].cell_contents) print(f.__closure__)
def bar(): x=111121 y=2222 f() bar()
-
適配器模式分為兩種:類適配器模式和對象適配器模式。廢話不多說,直接上代碼。 1、類適配器模式 2、對象適配器模式 ...
-
public interface Shape { public void outputShape(); } class Circle implements Shape { public void outputShape() { System.out.println("this is a circle... ...
-
全文檢索這個系列在幾前年寫過lucene的文章,而現在看來它確實已經老了,它的兒子孫子都出來了,已經成為現在檢索行列的主流,像solr,elasticsearch等,今天我們主要來看一個solr在aspnetcore里的使用,也就是增刪改查之類的,比較容易! nuget包:solrnet 註入方式: ...
-
Vivado是Xilinx(賽靈思)公司出品的開發軟體平臺,適用於Zedboard開發板。本文介紹了Vivado2017.3的在Win10安裝和可能遇到的問題。 ...
-
數據模型是開發軟體的最重要的部分,因為它們對應用程式有著深遠的影響:不僅是軟體的編寫方式,而且也影響我們如何解決的問題的方式。第二篇讀書筆記,我們聊一聊數據模型的設計。 1.數據模型的分層 作為一個開發者來說,在一個複雜的應用程式中,是存在很多 分層模型 的,但基本思想還是一樣的:每一層都提供了一個 ...
-
基於cookie做用戶驗證時, 敏感信息不適合放在cookie中. a. Session原理 cookie是保存在用戶瀏覽器端的鍵值對 session是保存在伺服器端的鍵值對 首先生成一個隨機字元串, 並只將隨機字元串通過cookie保存在瀏覽器端 在隨機字元串對應的字典中, 設置相應的字典 1 c ...
-
#函數定義def f(): print('love Q')f()##參數#形參和實參def add(a,b): print(a+b)add(7,5)def print_info(name,age): print('name:%s' % name) print('age:%d' % age)print ...
-
緩衝區,位元組將從中取出 作為一種數據源:將其與FilterInputStream對象相連以提供有用介面 字元串。底層實現實際使用的是StringBuffer 作為一種數據源:將其與FilterInputStream對象相連以提供有用介面 字元串,表示文件名、文件或FileDescriptor對象 作 ...