模板網(wǎng)站 怎么做優(yōu)化凡科建站下載
目錄
1.?閉包
1.1?使用閉包注意事項(xiàng)
1.2?小結(jié)
2.?裝飾器:實(shí)際上也是一種閉包;
2.1?裝飾器的寫法(閉包寫法) :基礎(chǔ)寫法,只是解釋裝飾器是怎么寫的;
2.2?裝飾器的語法糖寫法:@函數(shù)注解 :可以說是,當(dāng)前函數(shù)沒有發(fā)生變動,但是功能增加了;
3.?什么是設(shè)計(jì)模式
4.?設(shè)計(jì)模式-單例模式
4.1?單例模式的作用
4.2?單例模式的實(shí)現(xiàn)
5.?設(shè)計(jì)模式-工廠模式:創(chuàng)建額外的工廠類,去獲得想要的對象
5.1?工廠模式的使用
5.2?工廠模式的優(yōu)點(diǎn)
6.?多線程:進(jìn)程-線程概念
7.?多線程編程-threading 模塊
7.1?threading 模塊使用
7.2?參數(shù)傳遞args(tuple), kwargs(dict)
8.?網(wǎng)絡(luò)編程:Socket服務(wù)端開發(fā)
8.1?Socket客戶端和Socket服務(wù)端
8.2?Socket編程(客戶端 & 服務(wù)端)
9.?正則表達(dá)式-基礎(chǔ)方法
9.1?正則表達(dá)式概念
9.2?正則的三個基礎(chǔ)方法
9.3?小結(jié)
10.?正則表達(dá)式-元字符匹配
10.1?元字符匹配
10.2?元字符匹配-數(shù)量匹配
10.3?元字符匹配-邊界匹配-分組匹配
10.4?練習(xí)習(xí)題
10.4.1 案例:匹配賬號,只能由字母和數(shù)字組成,長度限制6-10位
10.4.2 案例:匹配QQ號,要求純數(shù)字,長度5-11,第一位不為0
10.4.3 案例:匹配郵箱地址,只允許qq、163、gmail這三種郵箱地址
11.?遞歸算法
11.1?概念:即方法(函數(shù))自己調(diào)用自己的一種特殊編程寫法;
11.2?文件結(jié)構(gòu)
11.3?os模塊獲取文件操作
11.3.1?讀取文件夾中的內(nèi)容
11.3.2?判斷這個路徑是否是文件夾
11.3.3?判斷這個路徑是否存在
11.4?遞歸
導(dǎo)航:
Python第二語言(一、Python start)-CSDN博客
Python第二語言(二、Python語言基礎(chǔ))-CSDN博客
Python第二語言(三、Python函數(shù)def)-CSDN博客
Python第二語言(四、Python數(shù)據(jù)容器)-CSDN博客
Python第二語言(五、Python文件相關(guān)操作)-CSDN博客
Python第二語言(六、Python異常)-CSDN博客
Python第二語言(七、Python模塊)-CSDN博客
Python第二語言(八、Python包)-CSDN博客
Python第二語言(九、Python第一階段實(shí)操)-CSDN博客
Python第二語言(十、Python面向?qū)ο?#xff08;上))-CSDN博客
Python第二語言(十一、Python面向?qū)ο?#xff08;下))-CSDN博客
Python第二語言(十二、SQL入門和實(shí)戰(zhàn))-CSDN博客
Python第二語言(十三、PySpark實(shí)戰(zhàn))-CSDN博客
Python第二語言(十四、高階基礎(chǔ))-CSDN博客
1.?閉包
-
引言:
-
全局變量是可能被別的類import進(jìn)行篡改的;存在風(fēng)險;
-
- 序章:
- 在閉包中修改外部函數(shù)的值:需要使用
nonlocal
關(guān)鍵字修飾外部函數(shù)的變量才可以在內(nèi)部函數(shù)中修改它; - 閉包解決全局變量被篡改的可能性:
- 講解:大致就是說,initial_amount 是外部全局變量傳入,而內(nèi)部def可以調(diào)用到initial_amount ,也可以用到num,最終account_create返回的是一個函數(shù),函數(shù)是atm ,而
fn = account_create("xxx")
,fn("xxx")
實(shí)際代筆的是內(nèi)部函數(shù),實(shí)現(xiàn)閉包; - 實(shí)際上fn得到的是
retrun
的atm
函數(shù); - fn就是返回的函數(shù),一個函數(shù),而這個函數(shù)就是atm,所以解釋的通為什么fn輸出的內(nèi)容會是
存款:+xxx,賬戶余額:xxx
,因?yàn)閍tm調(diào)用了initial_amount和num; initial_amount=0
這相當(dāng)于是個變量,在整個程序account_create(xxx)
調(diào)用的過程中,他是一直有在更改的,但是可以看見在外界無法篡改到他,而是作為一個臨時變量被atm函數(shù)使用;-
def account_create(initial_amount=0): # 函數(shù)嵌套def atm(num, deposit=True):nonlocal initial_amount # 內(nèi)部函數(shù)使用外部函數(shù)變量if deposit:initial_amount += numprint(f"存款:+{num},賬戶余額:{initial_amount}")else:initial_amount -= numprint(f"取款:-{num},賬戶余額:{initial_amount}")return atm # 返回內(nèi)部函數(shù)fn = account_create() fn(300) fn(300) fn(100, False)
- 在閉包中修改外部函數(shù)的值:需要使用
1.1?使用閉包注意事項(xiàng)
-
優(yōu)點(diǎn):
無需定義全局變量即可實(shí)現(xiàn)通過函數(shù),持續(xù)的訪問、修改某個值;
閉包使用的變量的所用于在函數(shù)內(nèi),難以被錯誤的調(diào)用修改;
-
缺點(diǎn):
由于內(nèi)部函數(shù)持續(xù)引用外部函數(shù)的值,所以會導(dǎo)致這一部分內(nèi)存空間不被釋放,一直占用內(nèi)存;
1.2?小結(jié)
-
閉包:
定義雙層嵌套函數(shù)內(nèi)層函數(shù)可以訪問外層函數(shù)的變量;
將內(nèi)存函數(shù)作為外層函數(shù)的返回,此內(nèi)層函數(shù)就是閉包函數(shù);
-
閉包的好處和缺點(diǎn):
優(yōu)點(diǎn):不定義全局變量,也可以讓函數(shù)持續(xù)訪問和修改一個外部變量;
優(yōu)點(diǎn):閉包函數(shù)引用的外部變量,是外層函數(shù)的內(nèi)部變量。作用域封閉難以被誤操作修改;
缺點(diǎn):額外的內(nèi)存占用(基本可以忽略不記);
-
nonlocal關(guān)鍵字的作用:
在閉包函數(shù)(內(nèi)部函數(shù)中)想要修改外部函數(shù)的變量值需要用nonlocal聲明這個外部變量;
2.?裝飾器:實(shí)際上也是一種閉包;
- 裝飾器概念:
- 裝飾器具有裝飾器語法糖,與Spring的AOP思想很像,在調(diào)用某個函數(shù)時增強(qiáng)函數(shù)功能;
- 裝飾器其實(shí)也是一種閉包,其功能就是在不破壞目標(biāo)函數(shù)原有的代碼和功能的前提下,為目標(biāo)函數(shù)增加新功能;
2.1?裝飾器的寫法(閉包寫法) :基礎(chǔ)寫法,只是解釋裝飾器是怎么寫的;
就是在使用閉包時,調(diào)用outer函數(shù)時傳遞了一個函數(shù)實(shí)參,實(shí)現(xiàn)裝飾器sleep寫法;
def outer(func): # 裝飾器一般寫法(閉包)def inner():print("睡覺")func()print("起床")return innerdef sleep():import randomimport timeprint("ZZZ...")h = random.randint(1, 5)time.sleep(h)print(f"睡了:{h}小時")fn = outer(sleep)
fn()
2.2?裝飾器的語法糖寫法:@函數(shù)注解 :可以說是,當(dāng)前函數(shù)沒有發(fā)生變動,但是功能增加了;
????????在代碼中,@outer
這行代碼就是在使用裝飾器 outer
。它的作用是把 sleep
函數(shù)作為參數(shù)傳遞給 outer
函數(shù),并用 outer
函數(shù)返回的 inner
函數(shù)來替換 sleep
函數(shù)。使用 @
符號,裝飾器調(diào)用的方式非常簡潔,等效于:
雖然調(diào)用的是sleep
,但是,實(shí)際上調(diào)用是outer
的inner
;
sleep = outer(sleep)
????????這樣,在調(diào)用 sleep()
時,實(shí)際上是在調(diào)用 outer
返回的 inner
函數(shù)。這個函數(shù)會先打印 “睡覺”,然后調(diào)用原始的 sleep
函數(shù),最后再打印 “起床”。
def outer(func):def inner():print("睡覺")func()print("起床")return inner@outer
def sleep():import randomimport timeprint("ZZZ...")h = random.randint(1, 5)time.sleep(h)print(f"睡了:{h}小時")sleep()
3.?什么是設(shè)計(jì)模式
- 設(shè)計(jì)模式是一種編程套路,可以極大的方便程序的開發(fā);
- 最常見、最經(jīng)典的設(shè)計(jì)模式,是面向?qū)ο笤O(shè)計(jì)模式;
- 除了面向?qū)ο笸?#xff0c;在編程中也有很多既定的套路可以方便開發(fā),我們稱之為設(shè)計(jì)模式:單例、工廠模式、建造者、責(zé)任鏈、狀態(tài)、備忘錄、解釋器、訪問者、觀察者、中介、模板、代理模式等...
4.?設(shè)計(jì)模式-單例模式
4.1?單例模式的作用
- 創(chuàng)建類的實(shí)例后,通常都會得到一個完整的、獨(dú)立的類對象,但是在某些場景下,創(chuàng)建一個類,無論獲取多少次類對象,都僅僅提供一個具體的實(shí)例,用以節(jié)省創(chuàng)建類對象的開銷和內(nèi)存開銷;例如:工具類僅要1個實(shí)例,可以被用很多次;
4.2?單例模式的實(shí)現(xiàn)
- 保證類或方法函數(shù),只有一個,保證單例的使用;
- 看到控制臺,輸出的對象地址是相同的,說明他們是同一個對象;
from str_tools import str_tools1 = str_tool()
s2 = str_tool()print(id(s1))
print(id(s2))
5.?設(shè)計(jì)模式-工廠模式:創(chuàng)建額外的工廠類,去獲得想要的對象
5.1?工廠模式的使用
- 當(dāng)大量創(chuàng)建一個類的實(shí)例時,可以使用工廠模式來幫我們獲取到類對象;
- 與原始獲取類的基礎(chǔ)上多了一個工廠類,由原本的獲取對象方式變成了通過工廠來獲取到對象;
class Person:passclass Worker(Person):pass
class Student(Person):pass
class Teacher(Person):passclass Factory: # 工廠類def get_person(self, p_type):if p_type == 'w':return Worker()if p_type == 's':return Student()if p_type == 't':return Teacher()factory = Factory()
worker = factory.get_person('w')
student = factory.get_person('s')
teacher = factory.get_person('t')
5.2?工廠模式的優(yōu)點(diǎn)
- 大批量創(chuàng)建對象的時候有統(tǒng)一的入口,易于代碼維護(hù);
- 當(dāng)發(fā)生修改,僅修改工廠類的創(chuàng)建方法即可;
- 符合現(xiàn)實(shí)世界的模式,即由工廠來制作產(chǎn)品對象;
6.?多線程:進(jìn)程-線程概念
- 進(jìn)程:就是一個程序,運(yùn)行在系統(tǒng)之上。那么便稱之為這個程序?yàn)橐粋€運(yùn)行進(jìn)程,并分配進(jìn)程ID方便系統(tǒng)管理;
- 線程:線程是歸屬于進(jìn)程的,一個進(jìn)程可以開啟多個線程,執(zhí)行不同的工作,是基進(jìn)程的實(shí)際工作最小單位;
- 進(jìn)程之間是內(nèi)存隔離的,及不同的進(jìn)程擁有各自的內(nèi)存空間,這就類似于不同的公司擁有不同的辦公場所;
- 線程之間是內(nèi)存共享的,線程是屬于進(jìn)程的,一個進(jìn)程內(nèi)的多個線程之間是共享這個進(jìn)程所擁有的內(nèi)存空間的,這就好比,公司員工之間的共享公司的辦公場所;
- 并行執(zhí)行:在同一時間做不同的工作,進(jìn)程之間并行執(zhí)行,線程之間并行執(zhí)行;
7.?多線程編程-threading 模塊
7.1?threading 模塊使用
thread_obj = threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
group=None
: 預(yù)留參數(shù),目前未使用,保留默認(rèn)值。target=None
: 要在線程中執(zhí)行的目標(biāo)函數(shù),默認(rèn)為None
,需要提供一個可調(diào)用對象。args=()
: 傳遞給目標(biāo)函數(shù)的位置參數(shù),默認(rèn)為空元組。kwargs={}
: 傳遞給目標(biāo)函數(shù)的關(guān)鍵字參數(shù),默認(rèn)為空字典。name=None
: 線程名稱,默認(rèn)為None
,可以不設(shè)置,系統(tǒng)會自動生成。
參數(shù)名 | 類型 | 默認(rèn)值 | 說明 |
---|---|---|---|
group | None | None | 預(yù)留參數(shù) |
target | callable | None | 要執(zhí)行的函數(shù) |
args | tuple | () | 位置參數(shù) |
kwargs | dict | {} | 關(guān)鍵字參數(shù) |
name | str | None | 線程名稱 |
案例:
import threading
import time
from datetime import datetime
def sing():while True:print("唱歌,啦啦啦")time.sleep(1)print("唱歌停頓,1秒" + datetime.now().strftime("%H:%M:%S"))def dance():while True:print("跳舞,")time.sleep(1)print("跳舞停頓,1秒" + datetime.now().strftime("%H:%M:%S"))if __name__ == '__main__':sing_thread = threading.Thread(target=sing) # 創(chuàng)建唱歌任務(wù)線程dance_thread = threading.Thread(target=dance) # 創(chuàng)建跳舞任務(wù)線程sing_thread.start() # 唱歌線程開啟dance_thread.start()
7.2?參數(shù)傳遞args(tuple), kwargs(dict)
import threading
import time
from datetime import datetimedef sing(money):while True:print(f"唱歌,啦啦啦,這首歌賺了:{money}元")time.sleep(1)print("唱歌停頓,1秒 " + datetime.now().strftime("%H:%M:%S"))def dance(msg):while True:print(f"跳舞,{msg}")time.sleep(1)print("跳舞停頓,1秒 " + datetime.now().strftime("%H:%M:%S"))if __name__ == '__main__':sing_thread = threading.Thread(target=sing, args=(20,)) # 創(chuàng)建唱歌任務(wù)線程, target=sing傳遞函數(shù)本身dance_thread = threading.Thread(target=dance, kwargs={"msg": "跳舞讓我很開心"}) # 創(chuàng)建跳舞任務(wù)線程, target=dance傳遞函數(shù)本身sing_thread.start() # 唱歌線程開啟dance_thread.start()sing_thread.join() # 等待唱歌線程結(jié)束dance_thread.join() # 等待跳舞線程結(jié)束
8.?網(wǎng)絡(luò)編程:Socket服務(wù)端開發(fā)
- 概念:
- scoket(套接字)是進(jìn)程之間網(wǎng)絡(luò)通信的一個工具;
- 2個進(jìn)程之間通過Socket進(jìn)行相互通訊,就必須有服務(wù)端和客戶端;
- Socket服務(wù)端:等待其他進(jìn)程的連接、可接受發(fā)來的消息,可以回復(fù)消息;
- Socket客戶端:主動連接服務(wù)端、可以發(fā)送消息、可以接受回復(fù);
8.1?Socket客戶端和Socket服務(wù)端
Socket服務(wù)端:等待其它進(jìn)程的連接,可接收發(fā)來的消息,可以回復(fù)消息;
Socket客戶端:主動連接服務(wù)端,可以發(fā)送消息,可以接收回復(fù);
8.2?Socket編程(客戶端 & 服務(wù)端)
server:
import socket # 1.導(dǎo)包socket_server = socket.socket()socket_server.bind(('localhost', 8888)) # 2.綁定socket_server到指定IP和地址socket_server.listen(1) # 3.服務(wù)端開始監(jiān)聽端口,設(shè)置接收連接的數(shù)量# 4.接收客戶端連接,獲得連接對象; 返回的是元組(連接對象,客戶端地址信息); accept是阻塞,等待客戶端連接
conn, address = socket_server.accept()
print(f"接收到客戶端連接,連接來自:{address}")while True:# 5.客戶端連接后,通過recv方法,接收客戶端發(fā)送的消息; recv緩沖區(qū)大小; decode將bytes對象轉(zhuǎn)成字符串data = conn.recv(1024).decode("UTF-8")if data == 'exit':breakprint("接收到發(fā)送的數(shù)據(jù):", data)conn.send("你好".encode("UTF-8")) # 6.通過conn(客戶端當(dāng)次連接對象,調(diào)用send方法回復(fù)消息)conn.close() # 7.關(guān)閉連接
socket_server.close()
client:
import socketsocket_client = socket.socket()# 連接到服務(wù)器
socket_client.connect(('localhost', 8888))# 發(fā)送消息
while True:message = input("請輸入要發(fā)送的消息(輸入 'exit' 結(jié)束): ")socket_client.send(message.encode("UTF-8"))if message == 'exit':breakdata = socket_client.recv(1024).decode("UTF-8")# 接收到服務(wù)器返回的消息print("接收到服務(wù)器的消息:", data)# 關(guān)閉連接
socket_client.close()
兩個服務(wù)啟動后:
- 小結(jié):服務(wù)端是被動的,客戶端是主動的,服務(wù)端接受消息并回復(fù),客戶端發(fā)送消息,會并回復(fù);
9.?正則表達(dá)式-基礎(chǔ)方法
9.1?正則表達(dá)式概念
- 正則表達(dá)式,又稱規(guī)則表達(dá)式(Regular Expression)是使用單個字符串來描述、匹配某個句法規(guī)則的字符串,常被用來檢索、替換那些符合某個模式(規(guī)則)的文本;
- 正則表達(dá)式就是使用:字符串定義規(guī)則,并通過規(guī)則去驗(yàn)證字符串是否匹配;
- 比如,驗(yàn)證一個字符串是否是符合條件的電子郵箱地址,只需要配置好正則規(guī)則,即可匹配任意郵箱:
- 比如通過正則規(guī)則:
(^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)
即可匹配一個字符串是否是標(biāo)準(zhǔn)郵箱格式; - 但如果不使用正則,使用if else來對字符串做判斷就非常困難了;
- 比如通過正則規(guī)則:
9.2?正則的三個基礎(chǔ)方法
1.?re.match('字符單詞', 字符串變量):字符串匹配規(guī)則,從頭匹配,只從頭匹配一次符合條件的字符串;
import res = 'python zhangSan python nihao python wolai'result = re.match('python', s)print(result) # 顯示匹配對象或者 None
print(result.span()) # 打印了匹配子串在原始字符串 s 中的起始和結(jié)束索引
print(result.group()) # 打印了實(shí)際匹配到的子串s = '1python zhangSan python nihao python wolai'
result = re.match('python', s)
print('-----------------')
print(result)
2.?re.search('字符單詞', 字符串變量) :字符串匹配規(guī)則,搜索匹配,從所有字符串中匹配一次符合條件的字符串;
import res = '1python zhangSan python nihao wolai'result = re.search('python', s)print(result) # 顯示匹配對象或者 None
print(result.span()) # 打印了匹配子串在原始字符串 s 中的起始和結(jié)束索引
print(result.group()) # 打印了實(shí)際匹配到的子串s = 'nihao'
result = re.search('python', s)
print('-----------------')
print(result)
3.?re.findall('字符單詞', 字符串變量):字符串匹配規(guī)則,搜索全部匹配,從所有字符串中匹配所有符合條件的字符;
import res = '1python zhangSan python nihao wolai'result = re.findall('python', s)print(result) # 顯示匹配對象或者 []s = 'nihao'
result = re.findall('python', s)
print('-----------------')
print(result)
9.3?小結(jié)
- 什么是正則表達(dá)式:
- 是一種字符串驗(yàn)證的規(guī)則,通過特殊的字符串組合來確立規(guī)則;
- 用規(guī)則去匹配字符串是否滿足;
- 如
(^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)
可以表示為一個標(biāo)準(zhǔn)郵箱的格式;
- re模塊的三個主要方法:
re.match
從頭開始匹配,匹配第一個命中項(xiàng);re.search
全局匹配,匹配第一個命中項(xiàng);re.findall
全局匹配,匹配全部命中項(xiàng);
10.?正則表達(dá)式-元字符匹配
10.1?元字符匹配
注意在使用.
匹配的時候需要在匹配前面加上一個r
,因?yàn)?code>\.或者\d
在編碼中可能代表著其他的含義,不能被正則使用,所以r把他們標(biāo)記無效,所以要帶上r
;
元字符 | 含義 | 示例案例 |
---|---|---|
. | 匹配任意一個字符(除了換行符) | re.findall(r'he.t', 'hello hat heat') 匹配到 'heat' |
. | 匹配點(diǎn)本身 | re.findall(r'.com', 'example.com google.com') 匹配到 '.com' |
[] | 匹配[]中列舉的字符 | re.findall(r'[aeiou]', 'hello world') 匹配到 'e', 'o' |
\d | 匹配數(shù)字(0-9) | re.findall(r'\d', 'abc123def456') 匹配到 '1', '2', '3', '4', '5', '6' |
\D | 匹配非數(shù)字 | re.findall(r'\D', 'abc123def456') 匹配到 'a', 'b', 'c', 'd', 'e', 'f' |
\s | 匹配空白字符(空格、制表符等) | re.findall(r'\s', 'hello\tworld\n') 匹配到 '\t', '\n' |
\S | 匹配非空白字符 | 無 |
\w | 匹配單詞字符(字母、數(shù)字、下劃線) | re.findall(r'\w', 'hello123_world') 匹配到 'h', 'e', 'l', 'l', 'o', '1', '2', '3', '_', 'w', 'o', 'r', 'l', 'd' |
\W | 匹配非單詞字符 | re.findall(r'\W', 'hello123_world') 匹配到 '' (空字符串) |
10.2?元字符匹配-數(shù)量匹配
注意:{m,n}
單獨(dú)介紹,配置的是字符串長度,就是返回字符串的長度區(qū)間意思;比如123是3位,123qwe是6位,那么{m,n}
就應(yīng)該等于{3,6}
代表可以匹配的字符是3位數(shù)和6位數(shù)的;
字符 | 功能 | 描述 |
---|---|---|
* | 匹配前一個規(guī)則的字符出現(xiàn)0至無數(shù)次 | re.findall(r'ab*', 'a ab abb abbb') 匹配到 'a', 'ab', 'abb', 'abbb' |
+ | 匹配前一個規(guī)則的字符出現(xiàn)1至無數(shù)次 | re.findall(r'ab+', 'a ab abb abbb') 匹配到 'ab', 'abb', 'abbb' |
? | 匹配前一個規(guī)則的字符出現(xiàn)0次或1次 | re.findall(r'ab?', 'a ab abb abbb') 匹配到 'a', 'ab', 'ab', 'ab' |
{m} | 匹配前一個規(guī)則的字符出現(xiàn)m次 | re.findall(r'ab{2}', 'a ab abb abbb') 匹配到 'abb' |
{m,} | 匹配前一個規(guī)則的字符出現(xiàn)最少m次 | re.findall(r'ab{2,}', 'a ab abb abbb') 匹配到 'abb', 'abbb' |
{m,n} | 匹配前一個規(guī)則的字符出現(xiàn)m到n次 | re.findall(r'ab{1,2}', 'a ab abb abbb') 匹配到 'ab', 'abb' |
10.3?元字符匹配-邊界匹配-分組匹配
^
和$
的使用注意項(xiàng):如果要判斷字符串整體就需要在字符串前后加上,如果不要求整體的字符串就不用加上,整體字符串意思是abcdefg從a開始到g結(jié)束進(jìn)行匹配,而非整體就是0abcdefg1,也可以求出abcdefg的值,如果換成整體的就不會求出;
|
符號表示:(qq,|163|gmail)這三個都可以,其他的都不行;
- 邊界匹配:
字符 | 功能 | 示例 |
---|---|---|
^ | 匹配字符串開頭 | re.findall(r'^hello', 'hello world') 匹配到 'hello' |
$ | 匹配字符串結(jié)尾 | re.findall(r'world$', 'hello world') 匹配到 'world' |
\b | 匹配一個單詞的邊界 | re.findall(r'\bcat\b', 'The cat is black') 匹配到 'cat' |
\B | 匹配非單詞邊界 | re.findall(r'\Bcat\B', 'The cat is black') 匹配到 'cat' |
- 分組匹配:
字符 | 功能 | 示例 |
---|---|---|
() | 將括號中字符作為一個分組 | re.findall(r'(hello)+', 'hellohellohello world') 匹配到 'hellohellohello' |
| | 匹配左右任意一個表達(dá)式 | re.findall(r'cat|dog', 'I have a cat') 匹配到 'cat' |
10.4?練習(xí)習(xí)題
10.4.1 案例:匹配賬號,只能由字母和數(shù)字組成,長度限制6-10位
r = '^[0-9a-zA-Z]{6,10}$' :表示^從字符串頭開始,[0-9a-zA-Z]匹配的規(guī)則,{6,10}匹配的字符串長度,$匹配到字符串結(jié)尾;
import rer = '^[0-9a-zA-Z]{6,10}$'
s = '123456Ab'print(re.findall(r, s))
s = '123456Ab_'
print("------------")
print(re.findall(r, s))
10.4.2 案例:匹配QQ號,要求純數(shù)字,長度5-11,第一位不為0
r = '^[1-9][0-9]{4,10}$'
:表示^從頭開始匹配,[1-9]
第一位元素只能是1-9區(qū)間,[0-9]
后續(xù)的匹配規(guī)則只能在0-9之間,{4,10}
原規(guī)則是5-11長度,這里4-10是由于第一個元素[1-9]占據(jù)了,所有長度要減一,$匹配到結(jié)尾;
import rer = '^[1-9][0-9]{4,10}$'
s = '123a456'
print(re.findall(r, s)) # 數(shù)字中存在字母,不符合
print("------------------")
s = '123456'
print(re.findall(r, s)) # 純6位數(shù)字,符合
print("------------------")
s = '012345'
print(re.findall(r, s)) # 0開頭,不符合
10.4.3 案例:匹配郵箱地址,只允許qq、163、gmail這三種郵箱地址
r = r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
^
: 字符串的開始[\w-]+
: 匹配郵箱用戶名部分,包含一個或多個字母、數(shù)字、下劃線或連字符(\.[\w-]+)*
: 匹配可選的點(diǎn)號后跟一個或多個字母、數(shù)字、下劃線或連字符的部分,重復(fù)零次或多次@
: 匹配@
符號(qq|163|gmail)
: 匹配qq
、163
或gmail
這三個域名之一(\.[\w-]+)+
: 匹配至少一個點(diǎn)號后跟一個或多個字母、數(shù)字、下劃線或連字符的部分$
: 字符串的結(jié)尾
這個正則表達(dá)式整體上用于匹配 qq.com
、163.com
或 gmail.com
這些特定域名的電子郵件地址,例如 username@qq.com
、user.name@163.com
或 user-name@gmail.com;
import rer = r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
s = 'a.x.a.d.a@qq.com.cn'print(re.findall(r, s)) # 符合郵箱規(guī)則
print('-----------------')
s = 'a.x.a.d.a@q123q.com.cn'
print(re.findall(r, s)) # 不符合郵箱規(guī)則
11.?遞歸算法
11.1?概念:即方法(函數(shù))自己調(diào)用自己的一種特殊編程寫法;
函數(shù)調(diào)用自己,即稱之為遞歸調(diào)用;
def func():if ...:func()return ...
- 使用遞歸場景:遞歸找文件,找出一個文件夾匯總?cè)康奈募?#xff0c;用遞歸編程完成;
11.2?文件結(jié)構(gòu)
11.3?os模塊獲取文件操作
11.3.1?讀取文件夾中的內(nèi)容
import osdef test_os():print(os.listdir(r"C:\Users\Administrator\Desktop\file"))if __name__ == '__main__':test_os()
11.3.2?判斷這個路徑是否是文件夾
import osdef test_os():print(os.path.isdir(r"C:\Users\Administrator\Desktop\file"))if __name__ == '__main__':test_os()
11.3.3?判斷這個路徑是否存在
import osdef test_os():print(os.path.exists(r"C:\Users\Administrator\Desktop\file"))if __name__ == '__main__':test_os()
11.4?遞歸
實(shí)際上自己調(diào)用自己,不過在調(diào)用的外層有一個for循環(huán),最終將值累計(jì),實(shí)現(xiàn)遞歸操作;
主要理解return返回值,以及函數(shù)的調(diào)用方式,更容易理解遞歸;
import osdef get_files_recusion_dir(path):file_list = []if os.path.exists(path): # 1.判斷路徑是否存在for f in os.listdir(path):new_path = path + "/" + f # 2.將此路徑加上反斜杠/ + 當(dāng)前目錄下的其他文件或文本,再次判斷if os.path.isdir(new_path):file_list += get_files_recusion_dir(new_path) # 3.存在當(dāng)前文件夾即再次調(diào)用當(dāng)前函數(shù),并記錄用調(diào)用的函數(shù)返回值進(jìn)行累計(jì),實(shí)現(xiàn)自己調(diào)用自己else:file_list.append(new_path) # 4.沒有就追加文本文件else:print(f"指定目錄{path}不存在")return []return file_list # 最終返回所有的文本文件if __name__ == '__main__':print(get_files_recusion_dir(r"C:\Users\Administrator\Desktop\file"))