目錄
- 1 正則匹配
- 注意點1
- 1.1 正則匹配字符串寫法
- 1.2 創建re函數
- (1)re.search()--搜索第一個匹配項
- (2)re.match() - 從字符串開頭匹配
- (3)re.findall() - 返回所有匹配項的列表
- (4)re.finditer() - 返回匹配項的迭代器(適合大文本)
- (5)re.sub() - 替換匹配內容
- (6)re.split() - 按正則表達式分割字符串
- 2 參數數量/類型/默認值指定
- 3 引用傳遞和值傳遞說明
- 4 排列組合 itertools
- 5 內置變量/特殊變量
- 5.1 內置變量
- 5.2 類相關的特殊屬性
- 6 try-except-else-finally機制
- 6.1 基礎用法
- 6.2 else-finally
- 6.3 向上一級拋出錯誤
- 7 Threading - 線程(不是進程,創建進程我用的少)
- 7.1 講到線程,就不得不談線程通信
- 8 路徑操作及路徑索引 glob
以下資料參考官網及AI
1 正則匹配
re官網
python 的 re 庫能夠實現正則匹配功能。
注意點1
注意:在Python中使用正則表達式時要優先使用原始字符串。
(也就是說,字符串不會被python語言解析。而只會被re庫里的函數解析)
原因如下:
正則表達式本身用 \ 轉義特殊字符(如 \d 表示數字),但Python字符串中的 \ 也是轉義符。因此,在普通字符串中寫正則表達式時,需用 ?兩個反斜杠? 表示一個實際的反斜杠(如 \d)。
原始字符串(前綴 r)會忽略Python字符串的轉義規則,直接保留所有字符的字面值。例如,r"\d" 會直接傳遞給正則引擎 \d,而無需額外轉義。
以下為錯誤案例1:
import repattern = "\\" # 普通字符串:實際傳遞的是單個 \,但正則引擎會報錯(轉義不完整)
re.findall(pattern, "a\\b") # 報錯:因為正則收到的是單個 \
正確寫法:
pattern = "\\\\" # 普通字符串中,四個反斜杠 → Python轉義為兩個 \,正則引擎收到兩個 \
result = re.findall(pattern, "a\\b") # 成功匹配到 ["\\"]
使用原始字符串的寫法:
pattern = r"\\" # 原始字符串直接保留兩個 \,正則引擎收到兩個 \
result = re.findall(pattern, "a\\b") # 成功匹配到 ["\\"]
以下為錯誤案例2:
pattern = "\b" # 普通字符串中,\b 是退格符,正則引擎無法識別為單詞邊界
re.findall(pattern, "hello world") # 匹配失敗
正確寫法:
pattern = r"\b" # 原始字符串直接傳遞 \b,正則引擎識別為單詞邊界
result = re.findall(pattern, "hello world") # 匹配到單詞邊界的空字符
1.1 正則匹配字符串寫法
pattern = r'xxx'
匹配字符 | 含義 | 案例 |
---|---|---|
[ ] | 一個字符的集合,這寫字符可以單獨列出,也可以用范圍表示(范圍用- 分隔) | [abc],[a-c] |
$ | [akm$] 將會匹配以下任一字符 ‘a’, ‘k’, ‘m’ 或 ‘$’ | |
^ | 把 ^ 放在字符類的最開頭,集合取反來匹配字符類中未列出的字符。(如果放在字符類其他位置,則無意義) | [^5] 將匹配除 ‘5’ 之外的任何字符;[5^] 將匹配 ‘5’ 或 ‘^’ |
\w | 匹配任何字母數字字符 | 相當于字符類 [a-zA-Z0-9_] |
\d | 匹配任何十進制數字 | 等價于字符類 [0-9] |
\S | 匹配任何非空白字符 | 等價于字符類 [^ \t\n\r\f\v] |
\W | 匹配任何非字母與數字字符 | 等價于字符類 [^a-zA-Z0-9_] |
\s | 匹配任何空白字符 | [ \t\n\r\f\v] |
\D | 匹配任何非數字字符 | 等價于字符類 [^0-9] |
. | 匹配除換行符之外的任何字符 | |
* | 定前一個字符可以匹配零次或更多次,而不是只匹配一次 | ca*t 將匹配 ‘ct’ ( 0 個 ‘a’ )、‘cat’ ( 1 個 ‘a’ )、 ‘caaat’ ( 3 個 ‘a’ ) |
+ | 匹配一次或更多次 | ca+t 可以匹配 ‘cat’ ( 1 個 ‘a’ )或 ‘caaat’ ( 3 個 ‘a’),但不能匹配 ‘ct’ |
{m,n} | 其中 m 和 n 是十進制整數,該限定符意味著必須至少重復 m 次,最多重復 n 次。 | a/{1,3}b 可以匹配 ‘a/b’、‘a//b’ 或者 ‘a///b’ ,但不能匹配中間沒有斜桿的 ‘ab’,或者四個斜桿的 ‘ab’ |
() | 它們將包含在其中的表達式組合在一起,你可以使用重復限定符重復組的內容 | (ab)*,匹配ab 0到多次 |
1.2 創建re函數
(1)re.search()–搜索第一個匹配項
import retext = "Python is fun, Python is powerful"
pattern = r"Python"
match = re.search(pattern, text)
if match:print("Found:", match.group()) # 輸出: Found: Python
(2)re.match() - 從字符串開頭匹配
import re
text = "Python is awesome"
pattern = r"Python"
match = re.match(pattern, text)
if match:print("Match found:", match.group()) # 輸出: Match found: Python# 若 text = "I love Python",則 match 為 None
(3)re.findall() - 返回所有匹配項的列表
import re
text = "apple 12, banana 3, cherry 45"
numbers = re.findall(r'\d+', text)
print(numbers) # 輸出: ['12', '3', '45']
(4)re.finditer() - 返回匹配項的迭代器(適合大文本)
import re
text = "a=1, b=2, c=3"
matches = re.finditer(r'\w+=\d+', text)
for match in matches:print(match.group()) # 輸出: a=1, b=2, c=3
(5)re.sub() - 替換匹配內容
import re
text = "2023-10-05"
new_text = re.sub(r'-', '/', text)
print(new_text) # 輸出: 2023/10/05# 使用函數處理替換內容
def double_number(match):return str(int(match.group()) * 2)text = "Score: 5, Count: 3"
result = re.sub(r'\d+', double_number, text)
print(result) # 輸出: Score: 10, Count: 6
(6)re.split() - 按正則表達式分割字符串
import re
text = "one,two;three four"
parts = re.split(r'[,; ]+', text)
print(parts) # 輸出: ['one', 'two', 'three', 'four']
2 參數數量/類型/默認值指定
直接通過一個綜合案例說明:
from typing import Union, Optional, Anydef generate_user_card(username: str, # 必選參數(無默認值)age: int = 18, # 必選但有默認值(可省略)*hobbies: str, # 不定數量的位置參數(愛好)country: Optional[str] = "未知", # 可選關鍵字參數(允許None)**extra_info: Union[str, int, float] # 不定數量的關鍵字參數(擴展信息)
) -> dict[str, Any]:"""生成用戶信息卡,支持靈活參數輸入"""user_data = {"username": username,"age": age,"hobbies": hobbies if hobbies else ("無",),"country": country,"extra": extra_info}return user_data
(1)基礎調用:
result1 = generate_user_card("Alice")
print(result1)
# {'username': 'Alice', 'age': 18, 'hobbies': ('無',), 'country': '未知', 'extra': {}}
(2)額外信息傳入:
result3 = generate_user_card("Charlie",age=30,country=None, # 明確設置為Noneemail="charlie@example.com",score=95.5
)
print(result3["extra"])
# {'email': 'charlie@example.com', 'score': 95.5}
3 引用傳遞和值傳遞說明
在 Python 中,變量傳遞的本質是 對象引用的傳遞?,所有操作都是基于對象的引用(可以理解為“指針”)。
-
不可變對象?(int, float, str, tuple 等)
傳遞的是對象的引用,但修改時會創建新對象,原始對象不受影響(類似“值傳遞”的效果)。 -
?可變對象?(list, dict, set, 自定義類實例等)
傳遞的是對象的引用,修改內容時會影響原始對象(類似“引用傳遞”的效果)。
案例說明1
def modify_data(num: int, lst: list, obj: object):num += 10 # 不可變對象:創建新對象lst.append(4) # 可變對象:修改原對象obj.value = 5 # 可變對象:修改原對象# 初始化數據
original_num = 5
original_list = [1, 2, 3]
class MyClass:def __init__(self):self.value = 0
original_obj = MyClass()# 調用函數
modify_data(original_num, original_list, original_obj)print(original_num) # 輸出 5(未改變)
print(original_list) # 輸出 [1, 2, 3, 4](已改變)
print(original_obj.value) # 輸出 5(已改變)
案例2
class DataHolder:def __init__(self, data):self.data = data # data 是可變/不可變對象的引用# 不可變對象操作
holder1 = DataHolder(10)
temp = holder1.data
temp += 5 # 創建新對象,不影響原數據
print(holder1.data) # 輸出 10# 可變對象操作
holder2 = DataHolder([1, 2])
holder2.data.append(3) # 直接修改原對象
print(holder2.data) # 輸出 [1, 2, 3]
案例3:修改和賦值的本質區別
a = [1, 2]
b = a # 引用傳遞(指向同一對象)
b.append(3) # 修改原對象
print(a) # 輸出 [1, 2, 3]c = [4, 5]
d = c
d = [6, 7] # 創建新對象(重新綁定引用)
d.append(10)
print(c) # 輸出 [4, 5](原對象未變)
注意,這里:
lst = lst + (創建新列表,不影響原對象)
lst.append(4)(原地修改,影響原對象)
案例4:默認參數陷阱
# 錯誤示例:默認參數為可變對象
def buggy_func(data=[]): # 默認列表會持續保留data.append(1)return data# 正確做法
def safe_func(data=None):data = data if data is not None else []data.append(1)return data
錯誤案例的進一步測試:
def func(data=[]):data.append(1)return datafunc()
data = func()
data.append(10)
func()
print(data) # 輸出:[1, 1, 10, 1]
4 排列組合 itertools
tee 生成迭代器副本(副本的修改不影響原始數據)
islice 切片
zip_longest 合并多個迭代器
import itertoolsl = [1,2,3,4]
iter1, iter2 = itertools.tee(l, 2)
for x in iter1:
#
itertools.zip_longest()
5 內置變量/特殊變量
5.1 內置變量
python所有的內置變量:
dir(__builtins__)
__name__
如果當前運行的python文件為主文件,則該文件:
__name__ == __main__
如果當前文件被其他文件調用,則該文件:
__name__ == [文件名]
(不帶.py后綴)
參考文章
5.2 類相關的特殊屬性
__slots__
限制class可綁定的類的屬性。
__slots__ = ['屬性名1','屬性名2','屬性名3']
定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的。
除非在子類中也定義__slots__,這樣,子類實例允許定義的屬性就是自身的__slots__加上父類的__slots__。
__init__
類默認構造函數 ,第一個參入參數為self
__lt__
@property裝飾器
將方法變成屬性調用。
__str__
6 try-except-else-finally機制
6.1 基礎用法
try:with open('example.txt', 'r') as file:content = file.read()print(content)
except FileNotFoundError:print("文件未找到,請檢查文件路徑是否正確。")
except PermissionError:print("沒有權限讀取該文件。")
except Exception as e:# 捕獲所有其他類型的異常print(f"發生了一個錯誤:{e}")
try: 放置可能引發異常的代碼。‘
except:如果try中的代碼引發異常,會跳轉到指定的except 塊兒中
as: as e是可選的,允許你將異常實例賦值給變量e,這樣就可以在except塊中訪問到異常信息。
Exception :代表不指定異常類型(反之捕獲所有異常)
Python會按照except塊的順序檢查,一旦找到匹配的異常類型,就會執行該塊中的代碼,并且跳過后續的except塊。
6.2 else-finally
try:# 嘗試執行的代碼pass
except SomeException:# 處理異常的代碼pass
else:# 如果沒有異常發生,執行這里的代碼pass
finally:# 無論是否發生異常,都執行這里的代碼pass
else:如果你想要在沒有異常發生時執行一些代碼,可以使用else塊。它緊跟在所有的except塊之后,只有在try塊沒有引發任何異常時才會執行。
finally:無論是否發生異常,finally塊中的代碼都會被執行。這通常用于執行一些清理工作,比如關閉文件或釋放資源。
6.3 向上一級拋出錯誤
raise [error]
注意:如果不拋出錯誤,程序在執行換except后就會退出嗎?
當except塊內部的操作執行完成后,程序并不會自動退出,除非你在except塊中顯式地調用了sys.exit()、exit()、os._exit()等函數來終止程序,或者異常沒有被捕獲并且傳播到了程序的頂層(即沒有被任何try塊捕獲)。
7 Threading - 線程(不是進程,創建進程我用的少)
感謝大佬的總結:
https://liaoxuefeng.com/books/python/process-thread/thread/index.html
說實話,之前只用過C thread,沒用過python。
這里對大佬的 文章列出一些關鍵點:
(1)啟動一個線程就是把一個函數傳入并創建Thread實例,然后==調用start()==開始執行。
(2)在Python中,可以使用多線程,但不要指望能有效利用多核
有一些久遠的記憶似乎在逐漸復蘇
7.1 講到線程,就不得不談線程通信
線程的特點就是,共享資源,任務間需要頻繁通信。
線程的關鍵點就是:通信和同步。
要避免的問題:死鎖
(1)互斥鎖
(2)信號量
(3)條件變量
(4)事件
(5)消息隊列
(6)管道
8 路徑操作及路徑索引 glob
主要利用glob2庫
from glob2 import globpaths = glob(file_path) # 搜索文件file_path下所有文件,返回list變量# 返回該路徑下所有文件