介紹
Python 是一門獨(dú)特的語(yǔ)言,快速瀏覽一下他的要點(diǎn):
- 面向?qū)ο螅好恳粋€(gè)變量都是一個(gè)類,有其自己的屬性(attribute)與方法(method)。
- 語(yǔ)法塊:用縮進(jìn)(四個(gè)空格)而不是分號(hào)、花括號(hào)等符號(hào)來(lái)標(biāo)記。因此,行首的空格不能隨意書寫。
- 注釋:行內(nèi)用“#”號(hào),行間注釋寫在兩組連續(xù)三單引號(hào)之間:’’’
- 續(xù)行:行尾輸入一個(gè)反斜杠加一個(gè)空格(’\ ‘),再換行。如果行尾語(yǔ)法明顯未完成(比如以逗號(hào)結(jié)尾),可以直接續(xù)行。
- 打印與輸入: 函數(shù) print() 與 input(),注意 print() 的 sep 與 end 參數(shù)。
-
變量:無(wú)需指定變量類型,也不需要提前聲明變量。
- 刪除變量:del()
- 復(fù)制變量:直接將變量a賦值給b,有時(shí)僅僅復(fù)制了一個(gè)“引用”。此后 b 與 a 的改動(dòng)仍會(huì)互相影響。必要時(shí)使用 a is b 來(lái)判斷是否同址。
- 模塊:通過(guò) import pandas 的方式加載模塊(或者 import pandas as pd),并用形如 pandas.DataFrame(或 pd.DataFrame)的方式調(diào)用模塊內(nèi)的方法。也可以使用 from pandas import DataFrame 的方式,這樣在下文可以直接使用 DataFrame 作為調(diào)用名。
- 幫助:配合使用 dir() 與 help() 命令;其中前者是輸出變量所有的成員。以及查閱 官網(wǎng)頁(yè)面。
變量復(fù)制的一個(gè)例子。
a = [1, 2] b = a print(id(a) - id(b)) # 地址差為 0,表示實(shí)質(zhì)是同址的 0
b.append(3) print(a) # 只改動(dòng)了 b,但 a 也跟著變動(dòng)了 [1, 2, 3] a is b True
使用切片來(lái)重新分配空間:
a is a[:] False
數(shù)據(jù)結(jié)構(gòu)
Python 原生的數(shù)據(jù)結(jié)構(gòu)包括:
數(shù)字(num)
細(xì)分為整數(shù)(int)與浮點(diǎn)數(shù)(float)兩種。
- 四則運(yùn)算:+, -,?, / ,乘方:?*
- 整除: 5 // 2 = 2,取余:5 % 2 = 1
- 自運(yùn)算: a += 1 (四則與乘方均可類似自運(yùn)算)
以及一些細(xì)節(jié): - 運(yùn)算兩數(shù)中只要有一個(gè)浮點(diǎn)數(shù),結(jié)果就是浮點(diǎn)數(shù);
- 整數(shù)相除,即使能除盡,結(jié)果也是浮點(diǎn)數(shù);
- Python 內(nèi)部的機(jī)制解決了整數(shù)溢出的問(wèn)題,不用擔(dān)心。
布爾(bool)與邏輯
首字母大寫 True / False.
- 邏輯運(yùn)算符:與 A and B,或 A or B,非 not A
- 邏輯關(guān)系符:等于 ==, 不等于 !=. 其他不贅述。
- 幾種邏輯判斷例子:
變量 x | x = [] | x = 0 | x = 2 |
---|---|---|---|
bool(x) | False | False | True |
if x: … | False | False | True |
if x is None: … | False | False | False |
序列(sequence)
序列主要包括字符串(str)、列表(list)與元祖(tuple)三類。
-
序列索引規(guī)則:
- 索引從0開始,到 N-1 結(jié)束。
-
切片:切片的索引是左閉右開的。
- seq[0:2](從 0 到 1)
- seq[2:](從 2 到尾)
- seq[:3] (從頭到 2)
- seq[:](全部)
- seq[:10:2](從頭到9,每?jī)蓚€(gè)取一個(gè))
- seq[::2](全部,每?jī)蓚€(gè)取一個(gè))
- 索引允許負(fù)數(shù):seq(-1) 與 seq(N - 1) 等同,seq(-3:-1)與 seq(N-3:N-1) 等同。
-
序列通用函數(shù):
- len():返回序列長(zhǎng)度。
- +/* :加號(hào)用于連接兩個(gè)序列,乘號(hào)重復(fù)排列若干次再連接。
- seq1 in seq2:如果 seq1 這個(gè)片段可以在 seq2 中被找到,返回 True.
- index:在 seq1 in seq2 為 True 時(shí)使用,seq2.index(seq1) 表示 seq1 首次出現(xiàn)于 seq2 中的位置。
- max()/min():返回序列中的最值。如果不是數(shù)字,則按 ASCII 碼順序返回。
- cmp(seq1, seq2):比較大小。結(jié)果為負(fù),則表示 seq1 較小。
字符串(str)
寫于一對(duì)雙引號(hào)或單引號(hào)內(nèi)。用 str() 可以強(qiáng)制轉(zhuǎn)換為字符串。
- 轉(zhuǎn)義:反斜杠。如果強(qiáng)制不解釋字符串,在左引號(hào)前加字母 r 即可:?
r"c:\new"
. -
分割與連接:
**.split()
?與?**.join()
.s = " I love Python" # 首位是空格 lst = s.split(' ') lst1 = '-'.join(lst) print(lst, '\n', lst1) ['', 'I', 'love', 'Python'] -I-love-Python
-
緊切:
strip()
?去掉字符串首尾兩端的空格。方法?lstrip()/rstrip()
?則只切除首端/尾端的空格。s.strip() 'I love Python'
-
大小寫轉(zhuǎn)換:如下幾個(gè)方法:
- 首字母大寫:s.title()
- 全大寫:s.upper()
- 全小寫:s.lower()
- 句首大寫:s.capitalize()
-
格式化:字符串格式化是一種實(shí)用功能。通過(guò) .format() 成員函數(shù)完成。
'I like {} and {}'.format('Python', 'you') 'I like Python and you' '{0} + {2} = {1}'.format (10, 20, 'Python ') # 按順序引用 '10 + Python = 20' '{0} * {1} = {0}'.format (10, 'Python ') # 編號(hào)反復(fù)引用 '10 * Python = 10'
格式化控制碼:
控制碼 | 含義 | 控制碼 | 含義 |
---|---|---|---|
:s | 字符串 | :c | 單個(gè)字符 |
:b/o/x/d | 二、八、十六、十進(jìn)制數(shù) | :e/f | 科學(xué)計(jì)數(shù)法/浮點(diǎn)數(shù) |
一些復(fù)雜控制的例子:
例子 | 含義 | 例子 | 含義 |
---|---|---|---|
:.2f/:+.2f | 兩位小數(shù)/帶符號(hào)兩位小數(shù) | : .2f | 正數(shù)前補(bǔ)空格的兩位小數(shù) |
:, | 逗號(hào)分隔符 | :.2% | 百分比兩位小數(shù) |
:.2e | 科學(xué)計(jì)數(shù)法兩位小數(shù) | :^4d | 總寬四位居中對(duì)齊 |
:>4d/<4d | 總寬四位左/右對(duì)齊 | :0>4d | 總寬四位左側(cè)補(bǔ)零 |
舉例:
"{:0>7.2f} is an odd number".format(123.4) # 總寬 7 位小數(shù)點(diǎn)后 2 位,左側(cè)補(bǔ)零 '0123.40 is an odd number'
其他實(shí)用的字符串函數(shù):
- str.replace(old, new[, times]):將字符串中前 times 個(gè) old 子串替換為 new。Times 不指定時(shí)默認(rèn)替換全部。
- str.isdigit():判斷字符串是否每一位都是數(shù)字,返回 True 或者 False。
字符串中正則表達(dá)式的內(nèi)容參見本文附錄。
列表(list)
中括號(hào)式的結(jié)構(gòu)。list()
?用于強(qiáng)制轉(zhuǎn)換類型。
lst = [1, 2, 3] print(lst) [1, 2, 3] # 【反轉(zhuǎn)】:其中第二種方式會(huì)更改現(xiàn)有的列表 lst1 = list(reversed(lst)) lst.reverse() print(lst1, lst) [3, 2, 1] [3, 2, 1] # 【追加】:元素 append(),另一個(gè)列表:extend() lst.append(4) print(lst) [3, 2, 1, 4] lst.extend(lst1) print(lst) [3, 2, 1, 4, 3, 2, 1] # 【插入】:lst.insert(idx, obj) 會(huì)在 lst[idx] 處插入 obj,然后依次后移原有項(xiàng) lst.insert(1, 100) print(lst) [3, 100, 2, 1, 4, 3, 2, 1] # 【刪除】:lst.remove(obj) 會(huì)刪除首個(gè)匹配值,若無(wú)匹配會(huì)報(bào)錯(cuò); # lst.pop(idx) 會(huì)返回 lst[idx],并將其刪除。如果不指定 idx,默認(rèn)為列表尾 lst.remove(2) print(lst) [3, 100, 1, 4, 3, 2, 1] tmp = lst.pop() print(lst, "\n", tmp) [3, 100, 1, 4, 3, 2] 1 # 【搜索】:使用序列通用函數(shù)即可。用 count(obj) 可以計(jì)算頻數(shù)。 # 【排序】:sort() 方法。如果指定 reverse 參數(shù),可降序排序。 lst.sort(reverse=True) print(lst) [100, 4, 3, 3, 2, 1] # 【清空】:clear() lst.clear() print(lst) []
元組(tuple)
圓括號(hào)式的結(jié)構(gòu),是一種不可變序列。
a = (1, 'string ', [1 ,2]) print(a) (1, 'string ', [1, 2])
Note: 定義一個(gè)空的元組用()
,定義只有一個(gè)元組的元組,需要加,
,否則就不是元組了,如下:
>>> tuple1 = () >>> type(tuple1) <type 'tuple'> >>> tuple2 = (1) >>> type(tuple2) <type 'int'> >>> tuple3 = (1,) >>> type(tuple3) <type 'tuple'>
字典(dict)
字典是一種類哈希表的數(shù)據(jù)結(jié)構(gòu),內(nèi)部無(wú)序,通過(guò)鍵值對(duì)(key: value)的形式存儲(chǔ)數(shù)據(jù)。幾種字典初始化的方式:
# 小字典直接賦值 d1 = {"name": "wklchris", "gender": "male"} # 利用字典增加鍵值對(duì)的方法 d2 = {} d2['name'] = 'wklchris' # 一個(gè)值賦給多個(gè)鍵 d3 = {}.fromkeys(("name", "gender"), "NA") # 強(qiáng)制格式轉(zhuǎn)換 d4 = dict(name="wklchris", gender="male") print(d1, d2, d3, d4, sep="\n") {'name': 'wklchris', 'gender': 'male'} {'name': 'wklchris'} {'name': 'NA', 'gender': 'NA'} {'name': 'wklchris', 'gender': 'male'}
字典的操作方法:
len(d1) 2 # 【復(fù)制】: dd = d1.copy() dd is d1 False # 【查找鍵名稱】: "name" in dd True # 【刪除鍵值對(duì)】 del(dd["name"]) # 【get】 dd.get("name", "Nothing") # 如果鍵不存在,返回“Nothing” 'Nothing' # 【setdefault】 dd.setdefault("name", "wklchris") # 如果鍵不存在,就新建該鍵,并賦值 'wklchris' print(dd) {'name': 'wklchris', 'gender': 'male'} # 【輸出鍵值】: list(dd.items()) [('name', 'wklchris'), ('gender', 'male')] list(dd.keys()) ['name', 'gender'] list(dd.values()) ['wklchris', 'male'] # 【彈出鍵值對(duì)】:pop(key) / popitem(key) # 其中,后者會(huì)隨機(jī)彈出一個(gè)鍵值對(duì) tmp = dd.pop("gender") print(dd, tmp) {'name': 'wklchris'} male # 【更新】:update(ref_dict) 以 ref_dict 為準(zhǔn),更新當(dāng)前字典 d4 = {"name": "Test", "Age": 3} dd.update(d4) print(dd) {'name': 'Test', 'Age': 3}
集合(set)
本文只討論可變集合,關(guān)于不可變集合的內(nèi)容,參考 help(frozenset)。
集合是一種無(wú)序的數(shù)據(jù)存儲(chǔ)方式,且內(nèi)部元素具有唯一性。集合與字典一樣都可以用花括號(hào)的形式創(chuàng)立。但在書寫 a={} 時(shí),Python 會(huì)將其識(shí)別為字典類型。
- 增添:add() / update()
- 刪除:remove() / discard(),區(qū)別在于后者搜索無(wú)結(jié)果會(huì)報(bào)錯(cuò)。
- 從屬:a.issubset(b) 集合 a 是否是 b 的子集;a.issuperset(b) 集合 a 是否是 b 的父集。a == b 兩集合是否全等。
-
集合運(yùn)算:集合運(yùn)算不會(huì)改變參與運(yùn)算的集合本身。
- 并集: a | b 或者 a.union(b)
- 交集: a & b 或者 a.intersection(b)
-
補(bǔ)集: a - b 或者 a.difference(b)
注意:在字符串強(qiáng)制轉(zhuǎn)換為集合時(shí),必要時(shí)使用中括號(hào)先轉(zhuǎn)為列表(否則字符串會(huì)被拆分為單個(gè)字符后再進(jìn)行轉(zhuǎn)換)。例如:ss = {"a", "b", "c"} ss | set("de") {'a', 'b', 'c', 'd', 'e'} ss | set(["de"]) {'a', 'b', 'c', 'de'}
基本語(yǔ)句
同大多數(shù)程序語(yǔ)言一樣,Python 擁有?if, for, while
語(yǔ)句。什么?switch
?語(yǔ)句?使用字典就好。
if 語(yǔ)句與三元操作
在 Python 中,else if
?被縮寫為單個(gè)關(guān)鍵詞?elif
.
if 1.0 > 1: a = 1 elif 1.0 < 1: a = 2 else: a = 3 a 3
值得一提的是,Python 中的 if 語(yǔ)句支持鏈?zhǔn)奖容^,形如?a < x < b, a < x >= b
?等:
a = 0 if 1 < 2 > 1.5: a = 1 a 1
三元操作實(shí)質(zhì)是高度簡(jiǎn)化的 if 環(huán)境,形如?X = a if flag else b
:
a = 1 if 2 < 1 else 2 a 2
for 語(yǔ)句
Python 的循環(huán)語(yǔ)句中,像其他語(yǔ)言一樣,有?break
(跳出循環(huán)體) 與?continue
(循環(huán)步進(jìn)) 關(guān)鍵詞可以使用。
for 語(yǔ)句借助關(guān)鍵詞 in 使用:(函數(shù)?range(N, M=0, s=1)
?是一個(gè)生成等差數(shù)列的函數(shù),位于左閉右開區(qū)間[M,N)
上且公差為 s)。
for i in range(3): print(i) 0 1 2
注意到字典的 d.items(), d.keys(), d.values() 命令也常常用于 for 語(yǔ)句:
d = {"a": 1, "b": 2, "c": 3} for k, v in d.items(): print(k, v) b 2 c 3 a 1
以上等價(jià)于:
for k in d.keys(): print(k, d[k]) b 2 c 3 a 1
Python 中的?for
?語(yǔ)句可選?else
?語(yǔ)法塊,表示?for
?語(yǔ)句正常結(jié)束后執(zhí)行的內(nèi)容(中途?break
?不屬于正常結(jié)束)。這對(duì)于處理一些 break 操作很有幫助。例如:
a = 0 flag = 0 for i in range(5): if i > 2: flag = 1 break if flag == 1: a = 1 a 1
這在 Python 中顯得太復(fù)雜了,直接使用?for…else…
即可:
a = 1 for i in range(5): if i > 1: break else: a = 0 a 1
while 語(yǔ)句
while 語(yǔ)句的?else
?語(yǔ)法塊,指明了退出 while 循環(huán)后立刻執(zhí)行的內(nèi)容;它不是必需的。
如果你想要將 while 語(yǔ)句內(nèi)部的參數(shù)傳出(比如下例的計(jì)數(shù)器終值),這是一個(gè)不錯(cuò)的方案。
count = 1 while count < 5: a = count count *= 2 else: b = count print(a, b) 4 8
列表解析
列表解析是一種創(chuàng)建列表的高度縮寫方式:
lst = [x ** 2 for x in range(4)] lst [0, 1, 4, 9]
也可以配合 if 語(yǔ)句:
lst = [x ** 2 for x in range(4) if x > 0] lst [1, 4, 9]
類似的,也有字典解析,以及下文會(huì)介紹的生成器,也有生成器解析(把外圍的括號(hào)換成圓括號(hào)即可):
{n: n ** 2 for n in range(3)} {0: 0, 1: 1, 2: 4}
函數(shù)
本節(jié)介紹 Python 函數(shù)的基礎(chǔ)特點(diǎn),以及一些實(shí)用函數(shù)。
函數(shù)定義與判斷
使用?def
?關(guān)鍵字。三連雙引號(hào)間的內(nèi)容被視為函數(shù)的幫助字符串,可以通過(guò)?help()
?命令查看。
def func(a, b=0): """ This is a function that can meow. """ return " ".join(["meow"] * (a + b))
調(diào)用函數(shù):
func(2) # 單參數(shù),僅 a 'meow meow' func(2, 3) # 雙參數(shù), a 與 b 都被傳入 'meow meow meow meow meow' help(func) Help on function func in module __main__: func(a, b=0) This is a function that can meow.
通過(guò)?callable()
?可以判斷一個(gè)對(duì)象是否是一個(gè)可調(diào)用的函數(shù):
callable(func) True
不定參函數(shù)
利用序列(或元組)與字典,向函數(shù)傳參。前者在傳入時(shí)需要加上一個(gè)星號(hào),后者需要兩個(gè)。
lst = [1, 3, 4] d = {"a": 2, "b": 3, "c": 5} print("{}+{}={}".format(*lst), "{a}+={c}".format(**d)) 1+3=4 2+3=5
zip 函數(shù)
zip() 函數(shù)的作用是“合并”多個(gè)列表為一個(gè)。其返回值是一個(gè)列表,列表內(nèi)的元素類型是元組。如果待合并的列表長(zhǎng)度不同,以最短的為準(zhǔn)。
a = [1, 2, 3, 4] b = [5 ,6, 7] c = "abcd" list(zip(a, b, c)) [(1, 5, 'a'), (2, 6, 'b'), (3, 7, 'c')]
它比較常用于交換字典的鍵與值:
dict(zip(d.values(), d.keys())) {2: 'a', 3: 'b', 5: 'c'}
lambda 函數(shù)
一種匿名函數(shù)的聲明方式。如果你使用過(guò)?MATLAB
,你可能熟悉這一類概念。
func = lambda x, y: x + y func(2, 5) 7
map 函數(shù)
map()
?能夠?qū)魅氲男蛄羞M(jìn)行依次操作,并將結(jié)果返回為一個(gè)可轉(zhuǎn)換為列表的?map
?對(duì)象。通常列表解析(或生成器解析)可以實(shí)現(xiàn)與其同樣的工作。
lst = list(map(lambda x: x + 1, range (5))) print(lst) [1, 2, 3, 4, 5] f = lambda x: x + 1 [f(x) for x in range(5)] [1, 2, 3, 4, 5]
filter 函數(shù)
給定序列,對(duì)于滿足某規(guī)則的部分(即 True),予以返回。
list(filter(lambda x: x > 0, range(-3, 3))) [1, 2]
reduce 函數(shù)
該函數(shù)在 Python 2 中是可以直接調(diào)用的,但在 Python 3 中需要從?functools
?模塊進(jìn)行調(diào)用。
from functools import reduce reduce(lambda x, y: x + y, range (5)) # 0+1+2+3+4 10
enumerate 函數(shù)
它允許你像 d.items() 那樣,用類似的方式操作列表:
a = [1, 3, 5] for i, v in enumerate(a): print("lst[{}] = {}".format(i, v)) lst[0] = 1 lst[1] = 3 lst[2] = 5
裝飾器:算子
裝飾器是函數(shù)的函數(shù)——傳入的參數(shù)是一個(gè)函數(shù),返回的值也是一個(gè)函數(shù)。相當(dāng)于一個(gè)函數(shù)集到另一個(gè)函數(shù)集的映射,可以理解為數(shù)學(xué)意義上的算子。
首先來(lái)看一個(gè)簡(jiǎn)單的例子:函數(shù)可以被賦值給一個(gè)變量。
def pyrint(data="Python"): return data.upper() f = pyrint f() 'PYTHON'
還可以通過(guò)?__name__
?來(lái)得到當(dāng)前函數(shù)的名稱:
f.__name__ 'pyrint'
那什么時(shí)候需要裝飾器呢?比如在函數(shù)需要被重用、但又不能直接改寫?def?
的場(chǎng)合(在維護(hù)中應(yīng)該不少見吧?。?。例如,我們希望在返回值之前,把函數(shù)名也打印出來(lái):
def showname(func): def subfunc(*args, **kwarg): print("FUNCTION {} called.".format(func.__name__)) return func(*args, **kwarg) return subfunc
這樣如果我們通過(guò)?showname(pyrint)
?這種形式,就能夠在?pyrint
?函數(shù)被調(diào)用之前,額外打印一行內(nèi)容。
想要改動(dòng)該函數(shù),不需要改動(dòng) def 語(yǔ)句以下的內(nèi)容,只需要用?@showname
?命令來(lái)應(yīng)用這個(gè)裝飾器:
@showname def pyrint(data="Python"): return data.upper() pyrint() FUNCTION pyrint called. 'PYTHON'
如果裝飾器需要傳遞參數(shù),那么,需要在定義時(shí),外層再嵌套一個(gè)函數(shù):
def showname(num=1): def decorator(func): def subfunc(*args, **kwarg): print("Call time: {}. FUNCTION {} called.".format(num, func.__name__)) return func(*args, **kwarg) return subfunc return decorator @showname(2) def pyrint(data="Python"): return data.upper() pyrint() Call time: 2. FUNCTION pyrint called. 'PYTHON'
不過(guò)裝飾器被應(yīng)用于函數(shù)定義之前時(shí),函數(shù)的?__name__
?屬性會(huì)改變。比如上例:
pyrint.__name__ 'subfunc' 使用模塊 functools 來(lái)解決這一問(wèn)題: import functools def showname(num=1): def decorator(func): @functools.wraps(func) # 加上這一行 def subfunc(*args, **kwarg): print("Call time: {}. FUNCTION {} called.".format(num, func.__name__)) return func(*args, **kwarg) return subfunc return decorator @showname(2) def pyrint(data="Python"): return data.upper() pyrint.__name__ 'pyrint'
迭代器 [itertools]
迭代器與生成器在內(nèi)存優(yōu)化上很有意義。
迭代器
迭代器最顯著的特征是擁有?__iter__()
?和?__next__()
?方法;它像一個(gè)鏈表。如果它指向末尾,那么再次執(zhí)行?__next__()
?時(shí)會(huì)報(bào)錯(cuò)。一個(gè)例子:
a = [1, 2, 3] b = iter(a) print(b.__next__(), b.__next__()) # 或者使用 next(b) 1 2
實(shí)際上,Python 3 內(nèi)置了一個(gè)?itertools
?的庫(kù),里面有諸如?cycle
?和?count
?等適用于迭代器的函數(shù):
import itertools # count: 給定首項(xiàng)與公差的無(wú)窮等差數(shù)列 p = itertools.count(start = 1, step = 0.5) print(p.__next__(), p.__next__()) # cycle: 周期循環(huán)的無(wú)窮序列 p = itertools.cycle(list("AB")) print(next(p), next(p), next(p)) # islice: 從無(wú)窮序列中切片 p = itertools.cycle(list("AB")) print(list(itertools.islice(p, 0, 4))) 1 1.5 A B A ['A', 'B', 'A', 'B']
請(qǐng)時(shí)刻注意當(dāng)前指向的迭代器位置——失之毫厘,謬以千里。
生成器
生成器是迭代器的一種,其實(shí)質(zhì)是定義中含有 yield 關(guān)鍵詞的函數(shù)。它沒有 return() 語(yǔ)句。
生成器可以直接使用類似列表解析的方式,稱為生成器解析。例如:(i for i in range(10)。
def Fib(N): # 斐波那契數(shù)列 n, former, later = 0, 0, 1 while n < N: yield later former, later = later, later + former n += 1 list(Fib(5)) [1, 1, 2, 3, 5]
上例與普通的寫法看上去差別不大,但實(shí)際上可以將 while 語(yǔ)句改寫為?while True
,刪除變量 n,在外部借助 itertools 的?islice
?函數(shù)來(lái)截取。這在函數(shù)定義時(shí)對(duì)代碼的壓縮是顯然的。
def iterFib(): former, later = 0, 1 while True: yield later former, later = later, later + former list(itertools.islice(iterFib(), 0, 5)) [1, 1, 2, 3, 5]
錯(cuò)誤:try()?語(yǔ)句
常見的錯(cuò)誤有以下幾種:
- ZeroDivisionError: 除數(shù)為 0.
- SyntaxError:語(yǔ)法錯(cuò)誤。
- IndexError:索引超界。
- KeyError:字典鍵不存在。
-
IOError:讀寫錯(cuò)誤。
try() 語(yǔ)句的常見寫法:try: a = 1 except ZeroDivisionError as e: print(e) exit() else: # 如果無(wú)錯(cuò)誤,執(zhí)行 print(a) finally: # 不管有無(wú)錯(cuò)誤均執(zhí)行 print("-- End --") 1 -- End --
其中,
else
?與?finally
?語(yǔ)句都不是必需的。如果不想輸出錯(cuò)誤信息、或不能預(yù)先判斷可能的錯(cuò)誤類型,可以使用僅含 exit() 語(yǔ)句的?except
?塊。
多個(gè) except 塊
一個(gè) try 語(yǔ)法塊是可以跟著多個(gè)?except
?的;如果靠前的 except 捕獲了錯(cuò)誤,之后的就不會(huì)運(yùn)行。 這也就是說(shuō),如果錯(cuò)誤之間有繼承關(guān)系時(shí),子錯(cuò)誤需要放在父錯(cuò)誤之前嘗試 except,否則子錯(cuò)誤永遠(yuǎn)也不可能被捕獲。
比如上一節(jié)的例子中,ZeroDivisionError
?是?ArithmeticError
?下的子錯(cuò)誤,而?ArithmeticError
?又是 Exception 下的子錯(cuò)誤(當(dāng)不清楚錯(cuò)誤的類型時(shí),Exception 可以捕獲絕大多數(shù)錯(cuò)誤)。關(guān)于錯(cuò)誤的繼承關(guān)系,參考:Python - Exception Hierarchy 官方頁(yè)面。
一個(gè)例子:
try: a = 1 / 0 except Exception: print("Exception") exit() except ZeroDivisionError: print("ZeroDivisionError") exit() else: print("No error.") finally: print("-- End --") 輸出 Exception 與 – End –。
錯(cuò)誤的捕獲
錯(cuò)誤在很多地方都可能發(fā)生,那是否需要在可能的地方都加上 try 語(yǔ)句呢?當(dāng)然不是。建議只在主代碼中加入 try 語(yǔ)句,因?yàn)?Python 會(huì)自動(dòng)跟蹤到錯(cuò)誤產(chǎn)生的源頭何在。
錯(cuò)誤的拋出及上拋
有時(shí)候我們想人為拋出一個(gè)錯(cuò)誤,這是使用?raise
?即可:
# raise TypeError("Wrong type.")
如果在函數(shù)中沒有處理錯(cuò)誤的語(yǔ)句,可能在捕獲錯(cuò)誤后將其上拋。記住,捕獲錯(cuò)誤只是為了記錄錯(cuò)誤的產(chǎn)生,并不意味者必須原地解決錯(cuò)誤。
def makeerror(n): if n == 0: raise ValueError("Divided by zero.") return 1 / n def callerror(): try: makeerror(0) except ValueError as e: print("ValueError detected.") raise # 輸出 "ValueError detected." 并打印錯(cuò)誤日志 # callerror()
上面的?raise
?命令沒有緊跟任何參數(shù),表示將錯(cuò)誤原樣上拋。你也可以手動(dòng)指定上拋的錯(cuò)誤類型,并不需要與原錯(cuò)誤類型一致。甚至你可以定義一個(gè)錯(cuò)誤(繼承某一錯(cuò)誤類):
class MyError(ValueError): print("This is MyError.") # raise MyError This is MyError.
文件讀寫
open() 函數(shù)用于文件的讀寫操作。一般我們會(huì)在操作文件時(shí),引入 os 模塊(os 模塊的用法參考“常用模塊”一節(jié)的內(nèi)容)。
import os
open()
?函數(shù)常常配合?with
?語(yǔ)法塊進(jìn)行使用,它會(huì)在語(yǔ)法塊結(jié)束時(shí)自動(dòng)關(guān)閉文件。該函數(shù):
open(file, mode="r", encoding=None)
第一參數(shù)是包含文件名的路徑(傳入基于當(dāng)前目錄的相對(duì)路徑,傳入或者絕對(duì)路徑),mode 參數(shù)是讀寫操作方式;encoding
?是編碼類型,一般取”utf8”
。其中,讀寫操作方式常用的有:
參數(shù) | 含義 |
---|---|
“r” | (默認(rèn))讀。 |
“w” | 寫。該模式會(huì)覆蓋原有內(nèi)容;如文件不存在,會(huì)自動(dòng)新建。 |
“x” | 創(chuàng)建新文件并寫入。 |
“a” | 在已有文件的尾部追加。 |
一般讀寫操作:read() / readlines()
函數(shù)?read()
?將整個(gè)文件讀為一個(gè)字符串,來(lái)看一個(gè)例子:
datapath = os.path.join(os.getcwd(), "data", "iris.data.csv") with open(datapath, "r", encoding="utf8") as f: rawtext = f.read() rawtext[:200] '5.1,3.5,1.4,0.2,Iris-setosa\n4.9,3.0,1.4,0.2,Iris-setosa\n4.7,3.2,1.3,0.2,Iris-setosa\n4.6,3.1,1.5,0.2,Iris-setosa\n5.0,3.6,1.4,0.2,Iris-setosa\n5.4,3.9,1.7,0.4,Iris-setosa\n4.6,3.4,1.4,0.3,Iris-setosa\n5.0,'
函數(shù)?readlines()
?將整個(gè)文件讀為一個(gè)列表,文件的每一行對(duì)應(yīng)列表的一個(gè)元素。
with open(datapath, "r", encoding="utf8") as f: rawtext = f.readlines() rawtext[:3] ['5.1,3.5,1.4,0.2,Iris-setosa\n', '4.9,3.0,1.4,0.2,Iris-setosa\n', '4.7,3.2,1.3,0.2,Iris-setosa\n']
上述的?readlines()
?函數(shù)實(shí)質(zhì)等同于列表解析:
with open(datapath, "r", encoding="utf8") as f: rawtext = [line for line in f] rawtext[:3] ['5.1,3.5,1.4,0.2,Iris-setosa\n', '4.9,3.0,1.4,0.2,Iris-setosa\n', '4.7,3.2,1.3,0.2,Iris-setosa\n']
文件寫入,使用?write()
?函數(shù)。一個(gè)簡(jiǎn)單的例子:
with open(datapath, "w") as f: f.write("Sometimes naive.")
大文件讀取:readline()
如果文件比較大,使用?read()/readlines()
?函數(shù)直接讀入可能會(huì)占用太多內(nèi)存。推薦使用函數(shù)?readline()
,一種迭代器式的讀取方法。
with open(datapath, "r", encoding="utf8") as f: print(f.readline().strip()) print(f.readline().strip()) 5.1,3.5,1.4,0.2,Iris-setosa 4.9,3.0,1.4,0.2,Iris-setosa
你會(huì)發(fā)現(xiàn)兩次結(jié)果是不同的,這是因?yàn)榈鲀?nèi)部的“指針”向后移動(dòng)了。
怎樣獲取 / 移動(dòng)“指針”的位置呢?使用 tell() / seek() 命令。
with open(datapath, "r", encoding="utf8") as f: print(f.tell(), f.readline().strip()) print(f.tell(), f.readline().strip()) f.seek(0) # 回到文件頭 print(f.tell(), f.readline().strip()) 0 5.1,3.5,1.4,0.2,Iris-setosa 28 4.9,3.0,1.4,0.2,Iris-setosa 0 5.1,3.5,1.4,0.2,Iris-setosa
類
類的成員包括屬性(attribute
)與方法(method
)兩種。例子:
class MyClass: """ This is a class that can meow! """ animal = "cat" # An attribute def talk(self): # A method return "Meow" # An instance of the class a = MyClass() print(a.animal, a.talk()) cat Meow
上例中的?self
?表示類的實(shí)例,所有類內(nèi)部的方法都需要把該參數(shù)放在首位(你也不可不用 self 而使用 this 等,但是?self
?是慣例)。例如,self.animal
?就表示了實(shí)例的 animal 屬性。這與 C# 等語(yǔ)言中的“this.animal”是類似的。
下例證明了?self
?代表的實(shí)質(zhì)是類的實(shí)例,而不是類本身。
class EgClass: def __init__(self): print(self) # 實(shí)例,有對(duì)應(yīng)地址 print(self.__class__) # 類 a = EgClass() <__main__.EgClass object at 0x000002531C0AF860> <class '__main__.EgClass'>
構(gòu)造函數(shù):__init__()
類的構(gòu)造函數(shù)是?__init__()
?(左右均為雙下劃線),用于初始化實(shí)例。在聲明實(shí)例時(shí),該函數(shù)自動(dòng)被調(diào)用。
class MyClass2: def __init__(self, animal="cat"): self.animal = animal a = MyClass2("dog") a.animal 'dog'
封裝
類的重要特性是封裝性,即部分變量只能在其內(nèi)部修改或訪問(wèn),不能從類的外部進(jìn)行處理。Python 中的封裝非常簡(jiǎn)單,只要把屬性或方法的名稱前綴設(shè)置為雙下劃線即可。
由此可見,構(gòu)造函數(shù)?__init__()
?是最基本的一個(gè)私有方法。一個(gè)例子:
class MyClass3: def __init__(self, animal="cat"): self.__animal = animal self.__foo() def __foo(self): self.__animal = "rabbit" def show(self): print(self.__animal) a = MyClass3("dog") a.show() rabbit
如果想直接調(diào)用?__foo() 或者 __animal
,都會(huì)被禁止,產(chǎn)生?AttributeError
。
# a.__animal # AttributeError
要注意,前后均添加了雙下劃線的屬性,如?name?,表示特殊屬性而不是私有屬性,是可以從外部訪問(wèn)的。
繼承
下面是一個(gè)著名的貓與狗的例子;類 Cat 與 Dog 都繼承自 Animal,同時(shí)也都重載了方法 talk()。
class Animal: def talk(self): pass # 表示定義留空 class Cat(Animal): # 從Animal 繼承 def talk(self): # 重寫talk() print('Meow') class Dog(Animal): def talk(self): print('Woof') a, b = Cat(), Dog() a.talk() # 'Meow' b.talk() # 'Woof' Meow Woof
通過(guò)?isinstance()
?函數(shù)可以判斷一個(gè)對(duì)象是否是某個(gè)類(或其子類)的實(shí)例:
print(isinstance(a, Cat), isinstance(a, Animal)) True True 或者: type(a).__name__ 'Cat'
當(dāng)然,類也可以多繼承。寫在左側(cè)的類的屬性與方法,在繼承時(shí)會(huì)被優(yōu)先采用。例如:
class Pet: def talk(self): print("Pet") class Cat2(Pet, Cat): pass a = Cat2() a.talk() Pet
@property 裝飾器
裝飾器?@property?
可以被用于限制類屬性的讀寫行為。比如,一個(gè)普通的類,如果想封裝一個(gè)屬性,卻允許從外部讀取它的值,一般我們用?getter
?函數(shù)實(shí)現(xiàn):
class Person: def __init__(self): self.__name = "Py" def get_name(self): return self.__name a = Person() a.get_name() 'Py'
不得不說(shuō)這實(shí)在是麻煩了,代碼里一堆 get 函數(shù)滿天飛并不令人愉快。而且還不能忘記它是一個(gè)函數(shù),需要在尾部加上括號(hào)。
裝飾器?@property
?可以將一個(gè)方法偽裝成同名的屬性,因此裝飾了?getter
?函數(shù)后,調(diào)用時(shí)就不用加上尾部的括號(hào)了:
class Person: def __init__(self): self.__name = "Py" @property def name(self): return self.__name a = Person() a.name 'Py'
而且,如果你想從外部修改該屬性的值,會(huì)產(chǎn)生錯(cuò)誤:
a.name = 1 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-97-8c607f2aa25b> in <module>() ----> 1 a.name = 1 AttributeError: can't set attribute
但同時(shí),我們也可以指定其 setter 函數(shù)(該裝飾器 @age.setter 在用 @property 裝飾 age 方法后會(huì)自動(dòng)生成),讓屬性修改成為可能,甚至附加修改條件:
class Person: def __init__(self): self.__age = 20 @property def age(self): return self.__age @age.setter def age(self, value): if not isinstance(value, int): raise ValueError("Age should be an integer.") else: self.__age = value a = Person() a.age = 30 a.age 30
不傳入整數(shù)會(huì)報(bào)錯(cuò):
a.age = 0.5 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-100-001bfa8fe26b> in <module>() ----> 1 a.age = 0.5 <ipython-input-98-83364d5faa13> in age(self, value) 10 def age(self, value): 11 if not isinstance(value, int): ---> 12 raise ValueError("Age should be an integer.") 13 else: 14 self.__age = value ValueError: Age should be an integer.
類的特殊屬性與方法
屬性?__dict__
首先是?__dict__
屬性,用于查看類的屬性與方法,返回一個(gè)字典。
a = MyClass() MyClass.__dict__ mappingproxy({'__dict__': <attribute '__dict__' of 'MyClass' objects>, '__doc__': '\n This is a class that can meow!\n ', '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 'animal': 'cat', 'talk': <function __main__.MyClass.talk>})
需要注意的是,此時(shí)實(shí)例 a 的屬性沒有被更改過(guò),實(shí)例的?dict?是一個(gè)空字典:
print(a.__dict__, a.animal) {} cat
類的?__dict__
?方法下的同名鍵,與實(shí)例具有相同值。
MyClass.__dict__["animal"] 'cat'
一旦被從外部更改,實(shí)例 a 的?dict?字典就不再為空。
a.animal = "dog" print(a.__dict__, a.animal) {'animal': 'dog'} dog
屬性?__slots__
從上面可以看到,非私有的類屬性可以從外部更改值,而且屬性還能直接從外部增加。__slots__ 屬性的作用就在于使類的屬性不能從外部進(jìn)行更改、追加。它能夠限制屬性濫用,并在優(yōu)化內(nèi)存上也有意義。
class MySlotClass(): __slots__ = ("meow", "woof") def __init__(self): self.meow = "Meow" self.woof = "Woof" a = MySlotClass() MySlotClass.__dict__ mappingproxy({'__doc__': None, '__init__': <function __main__.MySlotClass.__init__>, '__module__': '__main__', '__slots__': ('meow', 'woof'), 'meow': <member 'meow' of 'MySlotClass' objects>, 'woof': <member 'woof' of 'MySlotClass' objects>})
此時(shí),如果使用?a.__dict__
,結(jié)果不會(huì)返回空字典,而是會(huì)報(bào)錯(cuò)。
運(yùn)算符重載
特別地,Python 提供了運(yùn)算符重載的功能。常用的對(duì)應(yīng)如下(參考 官方頁(yè)面):
方法 含義 應(yīng)用
一元運(yùn)算符
len?長(zhǎng)度 len(a)
bool?邏輯值 bool(a)
neg?取負(fù)值 -a
str?/?repr?字符串形式 repr(a) / str(a), print(a)
二元運(yùn)算符
add?加 a + b, a += b
sub?減 a - b, a -= b
mul?乘 a?b, a?= b
div?除 a / b, a /= b
pow?乘方 a?b, a?= b
radd?左加 … + a
二元關(guān)系符
lt?/?le?小于 / 小于等于 a < b, a <= b
gt?/?ge?大于 / 大于等于 a > b, a >= b
eq?/?ne?等于 / 不等于 a == b, a != b
比如下例中,對(duì)多個(gè)運(yùn)算進(jìn)行了重載,完成了二維向量在加減法上與向量、與數(shù)運(yùn)算的基本定義。
class Vector: def __init__(self, a, b): self.a = a self.b = b def __add__(self, another): if isinstance(another, Vector): c, d = another.a, another.b else: c, d = another, another return Vector(self.a + c, self.b + d) def __radd__(self, another): return self.__add__(another) def __neg__(self): return Vector(-self.a, -self.b) def __sub__(self, another): return self.__add__(-another) def __str__(self): return "Vector({},{})".format(self.a, self.b) v1 = Vector(0,3) v2 = Vector(5,-2) print(v1 - 1, -v2, v1 + v2, v1 - v2) Vector(-1,2) Vector(-5,2) Vector(5,1) Vector(-5,5)
其中,__repr__()
?與?__str__()
?的主要區(qū)別在于,前者在交互式步驟中顯示結(jié)果,后者在 print 函數(shù)中顯示結(jié)果。
例如上例,如果直接輸入 v1,不會(huì)以 “Vector(0,3)”的形式顯示。
v1 # 在類中附加定義: __repr__ = __str__ 即可解決問(wèn)題。 <__main__.Vector at 0x2531c129c88>
迭代行為
在類中也能定義迭代行為,需要 __iter__() 與 __next__() 方法。
# 該例改編自官方文檔 class MyClass4: def __init__(self, lst): self.data = lst self.__index = len(lst) def __iter__(self): return self def __next__(self): if self.__index == 0: raise StopIteration self.__index -= 1 return self.data[self.__index] a = MyClass4("Meow") for char in a: print(char) w o e M
常用模塊
下面介紹幾個(gè)常用的 Python 標(biāo)準(zhǔn)模塊(即隨 Python 安裝的模塊)。更多的第三方模塊,例如 NumPy, pandas, matplotlib,可以參考本系列博文的其他文章。
os 模塊
這個(gè)模塊應(yīng)該是 Python 自帶模塊中使用率最高的一個(gè)了。一些例子:
# import os # # ----- 文件操作 ----- # os.rename("old.py", "new.py") # 重命名 # os.remove("a.py") # 刪除 # os.stat("b.py") # 查看文件屬性 # # ----- 路徑操作 ----- # os.getcwd() # 獲取當(dāng)前目錄 # os.chdir(r"d:\list") # 更改當(dāng)前目錄為 # os.chdir(os.pardir) # 返回上一級(jí)目錄 # os.mkdir('newfolder ') # 在當(dāng)前目錄新建一個(gè)文件夾 # os.listdir('c:\list') # 列出文件夾下所有文件的列表 # os.removedirs('thefolder ') # 刪除空文件夾 # os.path.isfile/ispath("f") # 檢查路徑是文件或是目錄 # os.path.exists("f") # 檢查路徑是否存在 # # ----- 操作平臺(tái)相關(guān) ----- # os.sep # 當(dāng)前操作系統(tǒng)的路徑分隔符 # os.linesep # 當(dāng)前操作系統(tǒng)的換行符 # os.path.join(r"c:\abc", "d") # 連接字串成為路徑
sys 模塊
一般我很少用到這個(gè)模塊??赡苡羞@么幾個(gè)命令會(huì)用到:
- sys.argv:能夠傳遞從命令行接受的參數(shù)到代碼內(nèi)。
- sys.platform:當(dāng)前操作系統(tǒng)平臺(tái)。
-
sys.exit():無(wú)參數(shù)時(shí)拋出 SystemExit 錯(cuò)誤并退出;有參數(shù)時(shí)會(huì)在退出前輸出對(duì)應(yīng)的字符串到屏幕。
import sys sys.platform 'win32'
一個(gè)?
sys.argv
?的例子:sys.argv ['e:\\python\\lib\\site-packages\\ipykernel_launcher.py', '-f', 'C:\\Users\\wklchris\\AppData\\Roaming\\jupyter\\runtime\\kernel-3724c4c9-2130-485d-b388-7a84379fd043.json']
以上不是典型的例子,因?yàn)椴⒉皇窃诿钚邢逻\(yùn)行的。命令行下通常有如下格式:
python test.py hello
此時(shí),sys.argv[0] = test.py,sys.argv[1] = hello.
re 模塊:正則表達(dá)式
參考本文附錄。
其他模塊
-
collection 模塊:
- 提供了一種雙端列表 deque,可以用 appendleft, extendleft, popleft 等方法從 deque 的左側(cè)(也就是lst[0])進(jìn)行操作。注意,deque 的更新操作比 list 更快,但讀取操作比 list 慢。
- 提供了一種缺省字典
defaultdict
,可以直接操作鍵值(即使這個(gè)鍵先前未定義);首次操作時(shí)會(huì)賦一個(gè)合理的初值,比如首次調(diào)用 d["a"] += 1 而字典本身沒有 “a” 鍵時(shí),會(huì)自動(dòng)初始化 “a” 鍵并賦初值 0。
- calendar 模塊:判斷星期、閏年,輸出日歷等等。
- itertools 模塊:在本文“迭代器”小節(jié)已進(jìn)行了簡(jiǎn)要介紹。
- logging 模塊:在調(diào)試中可能會(huì)使用。
- urllib 模塊:這是一個(gè) HTML 請(qǐng)求模塊,常用于爬蟲。
調(diào)試與測(cè)試
Python 中有一些內(nèi)置的辦法進(jìn)行調(diào)試與測(cè)試。
斷言:assert
斷言的含義在于,如果斷言失?。‵alse),那么代碼會(huì)被終止(拋出一個(gè)AssertionError
)。比如:
n = 0 assert(n != 0) 1 / n --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-112-e53f92f6c644> in <module>() 1 n = 0 ----> 2 assert(n != 0) 3 1 / n AssertionError:
與大家一貫喜歡使用的 print 調(diào)試法相比,斷言語(yǔ)句可以用命令行參數(shù) -O 忽略。這樣所有的 assert() 語(yǔ)句都不會(huì)被執(zhí)行。
$ python -O main.py
日志調(diào)試:logging 模塊
logging 模塊支持將錯(cuò)誤日志輸出(到控制臺(tái)或者到文件)。
此乃調(diào)試神器。延伸閱讀: logging 官方基礎(chǔ)教程。
import logging # 該行也可能通過(guò)控制臺(tái):$ python main.py --log=WARNING 的方式實(shí)現(xiàn) logging.basicConfig(level=logging.WARNING) n = 0 logging.warning("n = {}".format(n)) WARNING:root:n = 0
logging 模塊的靈活之處在于你可以記錄信息的級(jí)別(DEBUG,INFO,WARNING,ERROR,CRITICAL
),各級(jí)別的作用如下:
- DEBUG:最詳細(xì)的級(jí)別,所有詳細(xì)日志都會(huì)被輸出。
- INFO:檢測(cè)代碼是否按照預(yù)期執(zhí)行。
- WARNING:非預(yù)期的事件發(fā)生了,或者可能在近期發(fā)生(例如:低磁盤空間)。但代碼仍然執(zhí)行。
- ERROR:發(fā)生了級(jí)別更高的問(wèn)題,某些功能無(wú)法正常實(shí)現(xiàn)。
-
CRITICAL:嚴(yán)重錯(cuò)誤,代碼可能無(wú)法繼續(xù)運(yùn)行。
通過(guò)?filename
?參數(shù),可以將日志寫入到文件。一般使用?DEBUG
?級(jí)別,即輸出所有信息。# logging.basicConfig(filename="log.log", level=logging.DEBUG)
默認(rèn)會(huì)將日志追加到文件末尾,如果想要覆寫文件而不是追加,使用 filemode 參數(shù):
# logging.basicConfig(filename="log.log", filemode="w", level=logging.DEBUG)
更改日志格格式,使用 format 參數(shù)。一般來(lái)說(shuō),常用的格式碼(格式碼后加 s 表示字符串)有:
-
%(levelname)
:當(dāng)前日志字串級(jí)別。 -
%(message)
:當(dāng)前日志字串。 -
%(asctime)
:當(dāng)前時(shí)間。默認(rèn) datefmt 參數(shù)為?%Y-%m-%d %I:%M:%S
例子。下例會(huì)輸出形如:”01/23/1900 08:05:05 PM is when this event was logged.” 這樣的格式。# logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') # logging.warning('is when this event was logged.') # 常用的格式: # logging.basicConfig(format="%(levelname)s: %(message)s")
還可以通過(guò)配置文件來(lái)代替 basicConfig 命令,并進(jìn)行設(shè)置 logger 等更高級(jí)的配置。這部分可以參考:此處。
# import logging.config # logging.config.fileConfig('logging.conf')
附錄:正則表達(dá)式
正則表達(dá)式的基礎(chǔ)內(nèi)容參考本博客的這篇博文:正則表達(dá)式。注意:如果要保存一個(gè)正則表達(dá)式供多次使用,請(qǐng)存儲(chǔ)其?compile
?后的結(jié)果,避免反復(fù)編譯。
- re.compile(exp):編譯正則表達(dá)式。
-
re.compile(exp).match(str):判斷正則表達(dá)式能否匹配一個(gè)字串。可以 bool() 結(jié)果來(lái)獲知是否匹配。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-421771.html
- re.compile(exp).match(str).groups():將匹配結(jié)果返回為單個(gè)字符串(無(wú)子組時(shí))或元組(有子組時(shí))。
- re.compile(exp).findall(str):找出字符串中所有匹配表達(dá)式的子串。返回列表。
-
re.split(exp, str):用表達(dá)式來(lái)分割字符串,相當(dāng)于 str.split() 的增強(qiáng)版。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-421771.html
import re bool(re.match(r"\d", "1")) True phone_re = re.compile(r'\d{3,4}-\d{7,8}') phone_re.match('010-12345678').group() '010-12345678' # 如果在正則表達(dá)式中添加了子組(小括號(hào)),那么會(huì)返回子組依順序組成的一個(gè)元組 phone_re = re.compile(r'(\d{3,4})-(\d{7,8})') phone_re.match('010-12345678').groups() ('010', '12345678') phone_re = re.compile(r'\d{3,4}-\d{7,8}') # 尋找所有子串 phone_set = '010-12345678, 021-65439876 ' phone_re.findall(phone_set) ['010-12345678', '021-65439876'] s = 'a b c' # 用 re.split() 處理連續(xù)的空格 print(s.split(' '), re.split(r"\s+", s)) ['a', 'b', '', '', 'c'] ['a', 'b', 'c']
到了這里,關(guān)于Python常用基礎(chǔ)語(yǔ)法知識(shí)點(diǎn)大全合集,看完這一篇文章就夠了的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!