Python常忘的進階知識(上)
0.目錄
1.面向物件
- 1.1 函式與方法
- 1.2 類變數與例項變數
- 1.3 例項方法、類方法、靜態方法
- 1.4 公開和私有:沒有什麼是不能訪問的
1.5 繼承
2.正則表示式
- 2.1 Python內建函式與正則表示式
- 2.2 元字元、字符集、概括字符集
- 2.3 貪婪與非貪婪
- 2.4 匹配0次1次或者無限多次
- 2.5 邊界匹配符
- 2.6 匹配模式引數
- 2.7 re.sub正則替換
- 2.8 search與match函式
2.9 group分組
3.JSON
- 3.1 理解JSON
- 3.2 反序列化
3.3 序列化
4.列舉
- 4.1 列舉其實是一個類
- 4.2 列舉型別、列舉名稱與列舉值
- 4.3 列舉的比較運算
- 4.4 列舉的遍歷與轉換
4.5 限制列舉
5.閉包
- 5.1 一切皆物件
- 5.2 什麼是閉包
- 5.3 閉包的經典誤區
5.4 非閉包解決與閉包解決
6.函數語言程式設計
- 6.1 匿名函式與lambda表示式
- 6.2 map與lambda
- 6.3 reduce
6.4 filter
1.面向物件
1.1 函式與方法
類的方法必須含引數self:
函式與方法的區別:
- C、C++ 一般稱函式
- Java、C# 一般稱方法
- 方法:設計層面
- 函式:程式執行、過程式的一種稱謂
建構函式的定義:
可以顯式地呼叫建構函式:
顯式地呼叫建構函式返回了什麼?
ps:在建構函式中不能指定return的內容,只能返回None
1.2 類變數與例項變數
類變數與例項變數的區別:
類與物件的變數查詢順序:
__dict__ 變數儲存著當前物件所有的相關的變數:
當物件中不存在name的例項變數時,會去尋找類變數,還沒有的話會去父類中繼續尋找:
類的相關變數:
1.3 例項方法、類方法、靜態方法
self與例項方法:
- self 改成 this 也可以正常使用
- self 就是當前呼叫方法的物件
- self 代表著例項而不是類
在例項方法中訪問例項變數與類變數有兩種方法:
- 類.變數名
- self.__class__.變數名
定義和呼叫類方法的方法:
定義和呼叫靜態方法的方法:
ps:不需要引數self或者cls
pps:能用靜態方法的地方大都能用類方法代替,不建議使用靜態方法
1.4 公開和私有:沒有什麼是不能訪問的
定義私有的方法:
在資料成員名稱或者方法名稱之前加上 __ 即可
__name已經被置為私有了,此時訪問student1.__name由於Pyhton的動態性,實際上是動態建立了student1.__name,與物件的內建成員變數__name是不同的。
直接訪問student2.__name,果然報錯:
實際上__name儲存的是_Student__name:
所以說沒有什麼是不能訪問的:
1.5 繼承
繼承的方法:
子類呼叫父類的建構函式需要傳遞self(不推薦的方法):
子類方法呼叫父類方法:super關鍵字(推薦的方法)
2.正則表示式
2.1 Python內建函式與正則表示式
初識正則表示式:
1.正則表示式是一個特殊的字元序列,用來檢測一個字串是否與我們所設定的這樣的字元序列相匹配
2.快速檢索文字,實現一些替換文字的操作,比如:
- 檢查一串數字是否是電話號碼
- 檢測一個字串是否符合email
- 把一個文本里指定的單詞替換為另外一個單詞
判斷字串是否包含'Python'(使用Python內建函式):
判斷字串是否包含'Python'(使用正則表示式):
正則表示式的靈魂在於規則
2.2 元字元、字符集、概括字符集
元字元:
找出字串中的所有數字:
字符集:
1.找出中間字元是c或f的單詞
2.找出中間字元不是c也不是f的單詞
3.找出中間字元是c或d或e或f的單詞
概括字符集:
數字——\d —— 等價於[0-9]
非數字——\D —— 等價於[^0-9]
字母、數字、下劃線——\w——等價於[A-Za-z0-9_]
非字母、數字、下劃線——\W——等價於[^A-Za-z0-9_]
任何空白字元,包括空格、製表符、換頁符等等——\s——等價於[ \f\n\r\t\v]
任何非空白字元——\S——等價於[^ \f\n\r\t\v]
除換行符(\n、\r)之外的任何單個字元——.
2.3 貪婪與非貪婪
找出3個字母組成的單詞:
找出3至6個字母組成的單詞(預設是貪婪模式):
使用 ? 改為非貪婪模式:
2.4 匹配0次1次或者無限多次
匹配前面的子表示式0次或多次—— *
匹配前面的子表示式1次或多次—— +
匹配前面的子表示式0次或1次—— ?
2.5 邊界匹配符
判斷QQ號是不是4到8位的QQ號:
加入邊界控制符:
^ —— 表示從字串的開始位置匹配
$ —— 表示從字串的結束位置匹配
邊界控制符的作用:
2.6 匹配模式引數
re.I——忽略大小寫匹配:
ps:多個模式之間可以用 | 隔開,表示且關係
re.S——點號. 可以匹配包括換行符(\n、\r)在內的任何單個字元:
2.7 re.sub正則替換
用於查詢成功後替換:
sub第4個引數count預設為0,表示無限匹配。count表示所能替換的最大次數:
Python內建函式實現替換(replace()函式相當於正則表示式的簡化版,也有count):
sub強大之處在於第2個引數可以是函式:
1.可以看到C#消失了:
2.value的值:一個物件
3.用group()函式取出匹配值:
把函式作為引數傳遞:
2.8 search與match函式
match從字串的首字母開始匹配,如果沒有找到相應的匹配結果,將返回None:
search搜尋整個字串,直到找到第一個滿足正則表示式的結果,然後將匹配的結果返回:
search與match都只會匹配一次,找到後立馬停止搜尋
使用group返回值,使用span返回位置:
2.9 group分組
group(0)永遠記錄的是正則表示式完整的匹配結果,如果要訪問完整的匹配結果內部的某個分組的話,必須從1開始訪問:
使用findall()函式簡單得多:
可以有多個分組:
3.JSON
3.1 理解JSON
JSON:JavaScript Object Notation(JavaScript物件標記)
JSON是一種輕量級的資料交換格式:JSON是一種資料格式
字串是JSON的表現形式
符合JSON格式的字串叫做JSON字串
JSON優勢:
- 易於閱讀
- 易於解析
- 網路傳輸效率高
跨語言交換資料
3.2 反序列化
json中key和value必須用雙引號括起來,數字不需要:
JSON Object → Python dict或JSON array → Python list:
ps:JSON中布林值是小寫的,Python中布林值首字母大寫
反序列化—— 字串 → 某種語言中的某種資料結構
3.3 序列化
序列化—— 某種語言中的某種資料結構 → JSON字串
Python list → JSON字串:
4.列舉
4.1 列舉其實是一個類
定義VIP,輸出黃鑽:
列舉和普通類相比有什麼優勢:
普通類——可變,沒有防止相同標籤的功能
列舉——不能更改,有防止相同標籤的功能
4.2 列舉型別、列舉名稱與列舉值
取值:
取標籤名稱:
VIP.GREEN和VIP.GREEN.name的區別:
通過列舉名稱獲取列舉型別:
遍歷列舉:
4.3 列舉的比較運算
能做的比較:
4.4 列舉的遍歷與轉換
列舉注意事項:
可以有相同值,但是此時GREEN算作YELLOW的別名:
此時遍歷列舉:
如何遍歷包括別名的列舉:
不用items():
列舉轉換:
如何通過列舉值轉化為列舉型別?(並不是真正的型別轉換)
4.5 限制列舉
限制值為整數——IntEnum:
限制相同值——unique:
列舉在Python中實現的是單例模式,即對列舉型別不能例項化。
5.閉包
5.1 一切皆物件
在其他語言中:
- 函式只是一段可執行的程式碼,常駐於記憶體中,並不是物件
- 函式不能例項化
Python中一切皆物件:
- 把函式當作另外一個函式的引數,傳遞到另外的函式裡
- 把一個函式當作另外一個函式的返回結果
函式是物件
5.2 什麼是閉包
不可以直接呼叫curve():
間接呼叫curve():
求a*x*x
:
模組中呼叫curve()時,內部a的值不取模組中的變數a,而仍然是定義時的環境變數:(也就是說return curve時實際上不是返回一個函式,而是返回一個閉包)
閉包 = 函式 + 環境變數(函式定義時)
- 環境變數在定義函式的外部
- 環境變數不能是全域性變數
閉包的環境變數實質是儲存在內建變數 __closure__ 中:
取出閉包的環境變數:__closure__[0].cell_contents
5.3 閉包的經典誤區
這不是閉包:
這才是閉包:
環境變數應該被引用,且不能被當成一個變數進行賦值,否則就不是閉包!
5.4 非閉包解決與閉包解決
問題:編寫函式,傳入引數x代表旅行者走了x步,計算旅行者迄今為止已經走過的路程result,初始值result為0。
- 即傳入x=0得result=0
- 傳入x=1得result=1
- 傳入x=2得result=3
- 傳入x=5得result=8
非閉包解決:global宣告是全域性變數
閉包解決:nonlocal宣告不是區域性變數(origin這個全域性變數並沒有被改變)
通過閉包在模組中呼叫了局部變數(環境變數)
閉包的問題:環境變數常駐於記憶體中,容易造成記憶體洩漏
6.函數語言程式設計
6.1 匿名函式與lambda表示式
匿名函式——定義函式時不需要定義函式名
lambda定義函式:
三元表示式(如果x大於y,返回x,否則返回y):
其他語言中——x > y ? x : y
Python中——x if x > y else y
6.2 map與lambda
map是一個類,不是函式
求列表中每個數的平方(迴圈實現):
求列表中每個數的平方(map實現):
map將傳入序列的每一項都會執行傳入函式的操作。
map相當於數學上的對映。
map與lambda:
1.map的真正開啟方式
2.map可以傳遞多個引數
3.引數不相等時的結果
6.3 reduce
from functools import reduce
reduce是一個函式,不是類
reduce()裡面的第一個函式引數一定要有兩個引數:
reduce做的是連續的計算,每一次lambda表示式的計算結果將作為下一次的lambda表示式的引數進行運算!
reduce的第三個引數將作為初始值進行運算!
6.4 filter
filter(過濾):幫助我們過濾掉一些不需要的元素,或者是一些不符合規定的元素
過濾掉為0的元素:
filter要求lambda表示式必須返回可以代表真假的:
filter根據lambda表示式返回的結果判斷這個元素是否要保留在序列裡,如果返回的是False,那麼filter將過濾這個元素!