最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

入門初學(xué)者短期內(nèi)快速掌握Python的經(jīng)典全面教程(專家學(xué)習(xí)筆記)

 更新時(shí)間:2026年01月02日 10:45:29   作者:張彥峰ZYF  
本文從工程實(shí)踐視角出發(fā),對(duì)Python基礎(chǔ)知識(shí)進(jìn)行了系統(tǒng)梳理與總結(jié),內(nèi)容涵蓋運(yùn)行環(huán)境、基礎(chǔ)語(yǔ)法、控制流、函數(shù)、字符串處理以及列表、字典、集合等常用數(shù)據(jù)結(jié)構(gòu),并結(jié)合可運(yùn)行示例,幫助讀者建立清晰、連貫的語(yǔ)言認(rèn)知體系,適合初學(xué)者入門,為后續(xù)學(xué)習(xí)與實(shí)際應(yīng)用打下穩(wěn)定基礎(chǔ)

本博客將自己初步學(xué)習(xí)Python過(guò)程中的階段性整理與沉淀。難免存在理解不夠嚴(yán)謹(jǐn)或表述不夠完善之處,歡迎各位讀者在評(píng)論區(qū)留言指正、交流探討,這對(duì)我和后續(xù)讀者都會(huì)非常有價(jià)值。

同時(shí)說(shuō)明一下:從當(dāng)前基礎(chǔ)學(xué)習(xí)和實(shí)踐驗(yàn)證來(lái)看,當(dāng)前準(zhǔn)備的這些分享內(nèi)容,確實(shí)是可以在一天半的時(shí)間內(nèi)就可以快速學(xué)習(xí)完成并可以理解的,希望對(duì)我們彼此都有所收獲?。?!

一、快速了解 Python 和 環(huán)境準(zhǔn)備

(一)Python 快速介紹

Python 是一種 簡(jiǎn)潔、強(qiáng)大、易讀 的編程語(yǔ)言,廣泛應(yīng)用于 Web 開發(fā)、數(shù)據(jù)分析、人工智能、自動(dòng)化運(yùn)維領(lǐng)域。它由 Guido van Rossum 在 1991 年設(shè)計(jì),因其清晰的語(yǔ)法和強(qiáng)大的生態(tài)系統(tǒng),迅速成為全球最受歡迎的編程語(yǔ)言之一。

2017 年底,Stack Overflow 發(fā)布的數(shù)據(jù)顯示,Python 已經(jīng)超越 JavaScript 成為了該平臺(tái)上提問(wèn)流量最多的編程語(yǔ)言。

(二)Jupyter Notebook:從夢(mèng)想到行業(yè)標(biāo)配

Jupyter Notebook 的誕生源于創(chuàng)始人 Fernando Pérez一個(gè)大膽的想法:打造一個(gè)能整合 Julia(Ju)、Python(Py)和 R(ter) 這三種科學(xué)計(jì)算語(yǔ)言的通用計(jì)算平臺(tái)。但目前Jupyter 早已超越最初的設(shè)想,成為一個(gè)支持幾乎所有編程語(yǔ)言的多功能計(jì)算環(huán)境。

2017 年起,北美頂尖高校紛紛全面擁抱 Jupyter Notebook:

  • 學(xué)術(shù)界:斯坦福的 CS231N《計(jì)算機(jī)視覺與神經(jīng)網(wǎng)絡(luò)》 課程2017 年便完全遷移到 Jupyter Notebook、UC Berkeley 的 《數(shù)據(jù)科學(xué)基礎(chǔ)》 課程也在同年改用 Jupyter 作為唯一的作業(yè)平臺(tái)。
  • 工業(yè)界: Facebook盡管大型后端開發(fā)仍依賴傳統(tǒng) IDE,但幾乎所有 內(nèi)部分析、機(jī)器學(xué)習(xí)訓(xùn)練和數(shù)據(jù)探索 都基于 Jupyter Notebook 運(yùn)行。同時(shí) Google 的 AI Research 部門 Google Brain,也是清一色地全部使用 Jupyter Notebook(改進(jìn)定制版,叫 Google Colab)。

(三)Mac 上安裝 Python 和 Jupyter Notebook 的步驟

步驟命令說(shuō)明
1. 安裝 Homebrew/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Mac 的包管理工具(如果未安裝)
2. 安裝 Python 3brew install python安裝最新的 Python 3
3. 驗(yàn)證 Python 版本python3 --version確保安裝成功,顯示 Python 3.x.x
4. 安裝 Jupyter Notebookpip3 install jupyter通過(guò) pip3 安裝 Jupyter
5. 檢查 Jupyter 是否可用jupyter --version確保 Jupyter 已正確安裝
6. 啟動(dòng) Jupyter Notebookjupyter notebook打開 Jupyter Notebook,瀏覽器自動(dòng)打開

這樣,我們就可以在 Mac 上使用 Jupyter Notebook 進(jìn)行 Python 開發(fā)了!

備注:

  • 如果你不習(xí)慣也可以直接idea,畢竟這么多年習(xí)慣了java開發(fā),我就是兩個(gè)都安裝了,無(wú)所謂!
  • 如果不想安裝也可以在線使用:Jupyter 官方在線工具

二、Python 基礎(chǔ):變量、數(shù)據(jù)類型與輸入輸出

Python 以其 簡(jiǎn)潔、易讀 的語(yǔ)法受到歡迎,而理解變量、數(shù)據(jù)類型和輸入輸出是學(xué)習(xí) Python 的第一步。這部分內(nèi)容構(gòu)成了 Python 編程的基石。這部分代碼我寫的時(shí)候都是直接在idea中,網(wǎng)絡(luò)版本有時(shí)很慢。Jupyter 官方在線工具

(一)變量:數(shù)據(jù)的存儲(chǔ)與引用

變量(Variable是用于存儲(chǔ)數(shù)據(jù)的容器,在 Python 中變量不需聲明類型,直接賦值即可創(chuàng)建。

1. 變量的定義與賦值

x = 10  # 整數(shù)變量
name = "Alice"  # 字符串變量
pi = 3.14159  # 浮點(diǎn)數(shù)變量
is_python_fun = True  # 布爾變量

Python 是動(dòng)態(tài)類型語(yǔ)言,變量的類型是根據(jù)賦值內(nèi)容自動(dòng)推導(dǎo)的。

2. 變量命名規(guī)則

  • 變量名必須 以字母或下劃線(_)開頭,不能以數(shù)字開頭。

  • 變量名只能包含 字母、數(shù)字和下劃線,不能包含空格或特殊符號(hào)。

  • 變量名區(qū)分大小寫(ageAge 是不同的變量)。

  • 推薦使用 小寫字母+下劃線snake_case)風(fēng)格,如 user_name,符合 Python 代碼規(guī)范(PEP 8)。

示例:正確與錯(cuò)誤的變量命名

valid_name = "OK"  # 正確
_valid_123 = 42  # 正確
2nd_value = "wrong"  # ? 錯(cuò)誤:不能以數(shù)字開頭
user-name = "error"  # ? 錯(cuò)誤:不能包含 `-`

(二)數(shù)據(jù)類型(Data Types)

Python 具有豐富的數(shù)據(jù)類型,主要包括:

數(shù)據(jù)類型示例說(shuō)明
整數(shù)(int)x = 42存儲(chǔ)整數(shù),如 10, -5, 1000
浮點(diǎn)數(shù)(float)pi = 3.14存儲(chǔ)小數(shù),如 3.1415, -0.5
字符串(str)name = "ZYF"存儲(chǔ)文本,如 "hello"
布爾值(bool)is_valid = True只有 TrueFalse
列表(list)nums = [1, 2, 3]有序可變的集合
元組(tuple)colors = ('red', 'blue')有序不可變的集合
字典(dict)person = {"name": "Alice", "age": 25}鍵值對(duì)存儲(chǔ)
集合(set)unique_nums = {1, 2, 3}無(wú)序不重復(fù)元素集合

Python 提供 type() 函數(shù)來(lái)查看變量的數(shù)據(jù)類型:

x = 42
print(type(x))  # 輸出:<class 'int'>

Python 允許不同類型之間的轉(zhuǎn)換:

age = "25"  
age = int(age)  # 將字符串轉(zhuǎn)換為整數(shù)
pi = 3.14
pi_str = str(pi)  # 將浮點(diǎn)數(shù)轉(zhuǎn)換為字符串

(三)輸入與輸出(Input & Output)

1. 標(biāo)準(zhǔn)輸入(input)

input() 用于從用戶獲取輸入,所有輸入默認(rèn)是 字符串類型

name = input("請(qǐng)輸入你的名字: ")
print("你好,", name)

如果需要數(shù)值類型,需要進(jìn)行 類型轉(zhuǎn)換

age = int(input("請(qǐng)輸入你的年齡: "))  # 輸入默認(rèn)是字符串,需要轉(zhuǎn)換成整數(shù)
print("你明年就", age + 1, "歲了!")

基本驗(yàn)證:

2. 標(biāo)準(zhǔn)輸出(print)

print() 用于向控制臺(tái)輸出內(nèi)容:

name = "Alice"
age = 25
print("姓名:", name, "年齡:", age)  # 多個(gè)參數(shù)用逗號(hào)分隔

格式化輸出(推薦使用 f-string,Python 3.6+ 支持):

print(f"姓名: {name}, 年齡: {age}") # 推薦的寫法

? 小練習(xí)題

嘗試自己編寫代碼練習(xí)以下問(wèn)題:

  1. 定義一個(gè)變量 temperature,存儲(chǔ) 36.6,并使用 print() 輸出 "體溫: 36.6 攝氏度"。

  2. 編寫一個(gè)程序,提示用戶輸入姓名和年齡,并打印 "你好,XX!你今年 YY 歲"(其中 XXYY 由用戶輸入)。

Python 的變量、數(shù)據(jù)類型和輸入輸出構(gòu)成了編程的基礎(chǔ),熟練掌握這些概念后,就可以進(jìn)行更復(fù)雜的邏輯編寫了!

三、控制流:讓代碼具備決策能力

在編程中,控制流 決定了代碼的執(zhí)行順序,使程序能夠做出決策(條件判斷),或重復(fù)執(zhí)行任務(wù)(循環(huán))。通過(guò) 布爾值、邏輯運(yùn)算、if 語(yǔ)句、for 和 while 循環(huán),我們可以讓 Python 代碼變得更加智能和高效。這部分我會(huì)總結(jié)下這些關(guān)鍵概念,其是構(gòu)建更具邏輯性程序的基礎(chǔ)。

(一)布爾值與邏輯判斷

在 Python 中,布爾值(Boolean) 是控制程序邏輯的基礎(chǔ)。它用于 條件判斷、循環(huán)控制和邏輯運(yùn)算,讓代碼具備決策能力。

1. 布爾值(Boolean)

布爾值只有兩個(gè)取值:

True  # 代表 "真"
False  # 代表 "假"

布爾值本質(zhì)上是整數(shù)的特殊形式,其中:

True == 1  # 結(jié)果為 True
False == 0  # 結(jié)果為 True
布爾值的基本使用
is_python_fun = True
is_raining = False

print(is_python_fun)  # 輸出:True
print(type(is_python_fun))  # 輸出:<class 'bool'>

2. 比較運(yùn)算符(Comparison Operators)

比較運(yùn)算符用于比較兩個(gè)值,返回 TrueFalse。

運(yùn)算符含義示例結(jié)果
==等于5 == 5True
!=不等于5 != 3True
>大于10 > 3True
<小于2 < 8True
>=大于等于5 >= 5True
<=小于等于3 <= 2False
代碼示例
a = 10
b = 5

print(a > b)   # True
print(a == b)  # False
print(a != b)  # True

3. 布爾運(yùn)算符(Boolean Operators)

Python 提供了 and、ornot 三種邏輯運(yùn)算符,用于組合多個(gè)布爾表達(dá)式。

運(yùn)算符含義示例結(jié)果
and邏輯與(都為 True 時(shí)才為 TrueTrue and FalseFalse
or邏輯或(只要一個(gè)為 True 就是 TrueTrue or FalseTrue
not邏輯非(取反)not TrueFalse
3.1and邏輯與
x = 5
y = 10
print(x > 0 and y > 5)  # True,因?yàn)閮蓚€(gè)條件都成立
print(x > 0 and y < 5)  # False,因第二個(gè)條件不成立
3.2or邏輯或
x = 5
y = 10
print(x > 0 or y < 5)  # True,只要有一個(gè)條件為 True 即可
print(x < 0 or y < 5)  # False,兩個(gè)條件都為 False
3.3not邏輯非
is_python_fun = True
print(not is_python_fun)  # False,因?yàn)槿》戳?

4. 混合布爾運(yùn)算(優(yōu)先級(jí))

運(yùn)算符的 優(yōu)先級(jí) 從高到低依次為:not(最高)、and、or(最低)

知道黃曉明的“鬧太套”英文梗,這里直接記成“鬧安套”就好了

print(True or False and False)  
# 等價(jià)于 True or (False and False) → True or False → True

print(not True or False)  
# 等價(jià)于 (not True) or False → False or False → False

5. 布爾值與其他數(shù)據(jù)類型的轉(zhuǎn)換

在 Python 中,所有數(shù)據(jù)類型 都可以轉(zhuǎn)換為布爾值:

  • 以下情況視為 False

    • 0(整數(shù) 0)

    • 0.0(浮點(diǎn)數(shù) 0)

    • ""(空字符串)

    • [](空列表)

    • {}(空字典)

    • None(特殊值,表示“空”)

  • 其他情況均為 True。

5.1 使用bool()進(jìn)行類型轉(zhuǎn)換
print(bool(0))       # False
print(bool(""))      # False
print(bool([]))      # False
print(bool(42))      # True
print(bool("hello")) # True
5.2 在if語(yǔ)句中使用
name = "Alice"

if name:  # 相當(dāng)于 if bool(name) == True
    print("名字有效")  
else:
    print("名字為空")

輸出:

名字有效

? 小練習(xí)題

練習(xí) 1:布爾運(yùn)算

判斷以下表達(dá)式的結(jié)果:

  • True and False or True

  • not (False or True)

  • (10 > 5) and (3 != 3)

練習(xí) 2:用戶輸入比較

讓用戶輸入兩個(gè)數(shù)字,比較它們的大小,并輸出 "第一個(gè)數(shù)字更大""第二個(gè)數(shù)字更大"。

# 提示:使用 input() 和 if 語(yǔ)句

布爾值和邏輯判斷是 條件判斷和循環(huán) 的基礎(chǔ),熟練掌握它們后,代碼將更加智能化! ??

(二)?? 條件判斷(if語(yǔ)句)

在編程中,我們經(jīng)常需要根據(jù)不同條件來(lái)執(zhí)行不同的代碼。這就要用到 條件判斷語(yǔ)句(if statement)。Python 中使用 if、elifelse 關(guān)鍵字來(lái)實(shí)現(xiàn)條件分支。

1. 基本 if 語(yǔ)句

語(yǔ)法結(jié)構(gòu):

if 條件:
    語(yǔ)句塊

? 當(dāng)“條件”為 True 時(shí),語(yǔ)句塊才會(huì)被執(zhí)行。

示例:

age = 20

if age >= 18:
    print("你已經(jīng)成年了")

輸出:

你已經(jīng)成年了

2. if-else 結(jié)構(gòu)(兩分支選擇)

用于處理“要么這樣,要么那樣”的情況。

語(yǔ)法結(jié)構(gòu):

if 條件:
    語(yǔ)句塊1
else:
    語(yǔ)句塊2

示例:

temperature = 15

if temperature > 20:
    print("北京天氣今天很暖和")
else:
    print("北京天氣今天有點(diǎn)冷")

輸出:

北京天氣今天有點(diǎn)冷

3. if-elif-else 結(jié)構(gòu)(多分支選擇)

用于處理多個(gè)條件判斷的情況(相當(dāng)于“多項(xiàng)選擇”)。

語(yǔ)法結(jié)構(gòu):

if 條件1:
    語(yǔ)句塊1
elif 條件2:
    語(yǔ)句塊2
elif 條件3:
    語(yǔ)句塊3
else:
    默認(rèn)語(yǔ)句塊

示例:

score = 85

if score >= 90:
    print("優(yōu)秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

輸出:

良好

?? elif 是 "else if" 的縮寫。Python 中沒(méi)有 switch 語(yǔ)句,if-elif-else 是推薦的替代方案。

4. 嵌套 if 語(yǔ)句

嵌套 指的是在一個(gè) if 塊內(nèi)部再寫 if 判斷??梢杂脕?lái)表示更復(fù)雜的邏輯結(jié)構(gòu)。

示例:

age = 25
is_student = True

if age < 30:
    if is_student:
        print("你是年輕的學(xué)生")
    else:
        print("你是年輕的上班族")

輸出:

你是年輕的學(xué)生

?? 注意縮進(jìn)層級(jí),Python 是靠縮進(jìn)來(lái)識(shí)別代碼塊的!

5. 條件表達(dá)式(三元運(yùn)算符)

Python 支持一種簡(jiǎn)潔的寫法:在一行中完成 if-else 判斷。

語(yǔ)法:

變量 = 值1 if 條件 else 值2

示例:

age = 16
status = "成年" if age >= 18 else "未成年"
print(status)

輸出:

未成年

適合用于 根據(jù)條件選擇一個(gè)值賦給變量 的情況。

小結(jié)一下吧

類型場(chǎng)景示例
if只有一個(gè)條件
if-else兩種可能,二選一
if-elif-else多種情況,依次判斷
嵌套 if條件套條件,多層判斷
三元表達(dá)式簡(jiǎn)潔地賦值,適合一行判斷

? 小練習(xí)題

練習(xí) 1:分?jǐn)?shù)等級(jí)判斷器

讓用戶輸入一個(gè) 0~100 的整數(shù),判斷其屬于哪個(gè)等級(jí):

  • 90 以上:優(yōu)秀

  • 80~89:良好

  • 70~79:中等

  • 60~69:及格

  • 低于 60:不及格

  • 其他情況提示“輸入有誤”

練習(xí) 2:三角形合法性判斷

輸入三條邊的長(zhǎng)度,判斷是否能組成一個(gè)三角形(任意兩邊之和大于第三邊),并進(jìn)一步判斷:

  • 是等邊三角形

  • 是等腰三角形

  • 是普通三角形

  • 否則輸出“不合法的三角形”

練習(xí) 3:模擬 ATM 登錄與權(quán)限檢查(嵌套)

假設(shè)用戶名為 admin,密碼為 8888,登錄成功后再檢查是否為管理員(管理員輸入 "yes" 才能繼續(xù)操作)。

練習(xí) 4:三元運(yùn)算小測(cè)試

輸入一個(gè)數(shù)字,輸出 "正數(shù)""負(fù)數(shù)""零",用三元運(yùn)算符 實(shí)現(xiàn)。

(三)循環(huán)(Loops)

在編程中,我們常常需要重復(fù)執(zhí)行某些操作,比如遍歷列表、處理每一行數(shù)據(jù)、執(zhí)行某個(gè)動(dòng)作直到滿足條件等等。Python 提供了兩種主要的循環(huán)結(jié)構(gòu):while 循環(huán)和 for 循環(huán),配合控制語(yǔ)句(如 break、continue可以構(gòu)建出豐富的循環(huán)邏輯。

1. while循環(huán)(基于條件重復(fù)執(zhí)行)

? 基本語(yǔ)法
while 條件表達(dá)式:
    循環(huán)體
  • 每次循環(huán)前都會(huì)檢查“條件表達(dá)式”的值;

  • 條件為 True → 執(zhí)行循環(huán)體;

  • 條件為 False → 結(jié)束循環(huán)。

?? 示例:打印 1 到 5 的數(shù)字
i = 1
while i <= 5:
    print(i)
    i += 1
??break語(yǔ)句(提前終止循環(huán))

break 用于立即跳出整個(gè)循環(huán)結(jié)構(gòu),不管循環(huán)條件是否還為 True

i = 1
while True:
    print(i)
    if i == 3:
        break
    i += 1

輸出:1, 2, 3,然后退出循環(huán)

??continue語(yǔ)句(跳過(guò)當(dāng)前迭代)

continue 用于跳過(guò)本次循環(huán)中剩下的語(yǔ)句,直接進(jìn)入下一次判斷。

i = 0
while i < 5:
    i += 1
    if i == 3:
        continue
    print(i)

輸出:1, 2, 4, 5(跳過(guò)了 3)

2.for循環(huán)(用于遍歷序列)

? 基本語(yǔ)法
for 變量 in 可迭代對(duì)象:
    循環(huán)體

可迭代對(duì)象包括:字符串、列表、字典、集合、元組等。

?? 遍歷字符串
for ch in "hello":
    print(ch)
?? 遍歷列表
fruits = ['apple', 'banana', 'orange']
for fruit in fruits:
    print(fruit)
?? 遍歷字典
info = {"name": "Tom", "age": 20}
for key in info:
    print(key, "=>", info[key])

或使用 .items() 遍歷鍵值對(duì):

for key, value in info.items():
    print(f"{key}: {value}")
?? 遍歷集合
s = {"apple", "banana", "cherry"}
for item in s:
    print(item)
??range()函數(shù)與數(shù)值循環(huán)
for i in range(1, 6):
    print(i)
  • range(n):0 到 n-1

  • range(start, end):start 到 end-1

  • range(start, end, step):按步長(zhǎng)生成

??enumerate()結(jié)合索引遍歷

想同時(shí)獲取元素和下標(biāo)時(shí)使用 enumerate()

colors = ['red', 'green', 'blue']
for index, color in enumerate(colors):
    print(f"{index}: {color}")

3. 循環(huán)控制語(yǔ)句

?break:提前終止整個(gè)循環(huán)

通常與 if 配合使用,用于在滿足某個(gè)條件時(shí)立即退出循環(huán)。

for i in range(1, 10):
    if i == 5:
        break
    print(i)
?continue:跳過(guò)當(dāng)前迭代

用于跳過(guò)某些不符合條件的值。

for i in range(1, 6):
    if i % 2 == 0:
        continue
    print(i)  # 輸出 1 3 5(跳過(guò)偶數(shù))
?else語(yǔ)句在循環(huán)中的作用

else 可以與 forwhile 循環(huán)一起使用:

  • 當(dāng)循環(huán)沒(méi)有被 break 中斷時(shí),else 中的語(yǔ)句會(huì)執(zhí)行。

    for i in range(1, 5):
        if i == 10:
            break
    else:
        print("未被 break,循環(huán)正常結(jié)束")
    

    這在處理搜索類問(wèn)題時(shí)特別有用:

    nums = [1, 3, 5, 7]
    target = 4
    for num in nums:
        if num == target:
            print("找到目標(biāo)")
            break
    else:
        print("未找到目標(biāo)")
    

小結(jié)一下吧

循環(huán)類型用途特點(diǎn)
while條件控制循環(huán)不確定次數(shù)時(shí)使用
for遍歷序列更簡(jiǎn)潔,適合固定結(jié)構(gòu)
break跳出循環(huán)終止整個(gè)循環(huán)體
continue跳過(guò)本次迭代繼續(xù)下一輪
else循環(huán)結(jié)構(gòu)補(bǔ)充僅在循環(huán)未被 break時(shí)執(zhí)行

? 小練習(xí)題

?? 練習(xí)題 1:打印 1~100 中所有能被 7 整除的數(shù)
?? 練習(xí)題 2:使用while計(jì)算從 1 累加到 n 的和(n 由用戶輸入)
?? 練習(xí)題 3:找出列表中第一個(gè)大于 50 的元素,并輸出其值和索引
?? 練習(xí)題 4:輸出 1~30 中除了能被 3 整除的數(shù)(使用 continue)
?? 練習(xí)題 5:統(tǒng)計(jì)一段字符串中元音字母的個(gè)數(shù)(不區(qū)分大小寫)
?? 練習(xí)題 6:使用for和else實(shí)現(xiàn)一個(gè)猜數(shù)字小游戲

四、函數(shù)與相關(guān)基礎(chǔ)知識(shí):讓代碼會(huì)“思考”的魔法工具

在編程的世界里,函數(shù)就像是程序的“積木”:它們能把一段可復(fù)用的操作封裝起來(lái),想用就調(diào)用,修改也方便,堪稱優(yōu)雅代碼的起點(diǎn)。

無(wú)論是打印一行文字,計(jì)算一個(gè)數(shù)列的和,還是訓(xùn)練一個(gè) AI 模型,本質(zhì)上你做的都是“定義功能 + 調(diào)用功能” —— 這正是函數(shù)的使命。

(一)函數(shù)基礎(chǔ)

1. 什么是函數(shù)?為什么要使用函數(shù)?

在編程中,函數(shù)是一個(gè)非常重要的概念,它可以被理解為“功能塊”,用來(lái)封裝一段代碼,供其他地方調(diào)用。通過(guò)函數(shù),開發(fā)者可以:

  • 提高代碼復(fù)用性:避免重復(fù)寫相同的代碼,簡(jiǎn)化開發(fā)和維護(hù)。

  • 增強(qiáng)可讀性:將復(fù)雜的任務(wù)拆解成小的、獨(dú)立的單元,便于理解。

  • 分隔邏輯:函數(shù)讓代碼的邏輯結(jié)構(gòu)更加清晰和模塊化,有助于團(tuán)隊(duì)協(xié)作開發(fā)。

例如,我們可以定義一個(gè)函數(shù)來(lái)計(jì)算兩個(gè)數(shù)字的和,而不需要每次都重復(fù)寫加法的操作。只要定義一次,后續(xù)就可以隨時(shí)調(diào)用。

2. 使用def定義函數(shù)

在 Python 中,函數(shù)是通過(guò) def 關(guān)鍵字來(lái)定義的。它的基本語(yǔ)法如下:

def function_name(parameters):
    # 函數(shù)體
    return result
  • def 是 Python 中定義函數(shù)的關(guān)鍵字

  • function_name 是你給函數(shù)命名的名稱,符合命名規(guī)則

  • parameters 是函數(shù)的輸入(可以沒(méi)有)

  • return 是返回結(jié)果的關(guān)鍵字(如果不返回任何值,則默認(rèn)為 None

示例:一個(gè)簡(jiǎn)單的加法函數(shù)
def add(a, b):
    return a + b

# 調(diào)用函數(shù)
result = add(3, 5)
print(result)  # 輸出: 8

這里我們定義了一個(gè) add 函數(shù),輸入?yún)?shù)是 ab,它們會(huì)被加在一起并返回結(jié)果。

3. 函數(shù)的調(diào)用和執(zhí)行流程

定義函數(shù)后,調(diào)用函數(shù)就能執(zhí)行該函數(shù)的代碼。Python 會(huì)根據(jù)函數(shù)調(diào)用的順序進(jìn)入函數(shù)體,并執(zhí)行其中的代碼。

  • 當(dāng)函數(shù)被調(diào)用時(shí),程序會(huì)暫停當(dāng)前位置,跳轉(zhuǎn)到函數(shù)體執(zhí)行代碼,直到遇到 return 語(yǔ)句(或者函數(shù)執(zhí)行完畢)才返回。

  • 如果沒(méi)有 return 語(yǔ)句,則返回 None

示例:簡(jiǎn)單的函數(shù)調(diào)用與返回值
def greet(name):
    return f"Hello, {name}!"

message = greet("Alice")
print(message)  # 輸出: Hello, Alice!

這里的 greet 函數(shù)通過(guò) return 語(yǔ)句返回了一個(gè)字符串,調(diào)用時(shí)傳入了參數(shù) "Alice",最終返回 "Hello, Alice!"。

4.print()與return的區(qū)別與使用場(chǎng)景

在 Python 中,print()return 都用于輸出數(shù)據(jù),但它們有顯著的不同:

  • print() 用于將信息輸出到控制臺(tái),主要用于調(diào)試、輸出中間結(jié)果或與用戶交互。

  • return 用于函數(shù)的輸出,它將值返回給調(diào)用者,可以被其他代碼再次使用。

示例:print()和return對(duì)比
# 使用 print()
def greet_print(name):
    print(f"Hello, {name}!")

greet_print("Alice")  # 輸出: Hello, Alice!

# 使用 return
def greet_return(name):
    return f"Hello, {name}!"

message = greet_return("Alice")
print(message)  # 輸出: Hello, Alice!
  • greet_print 使用 print() 輸出值,但無(wú)法把它傳遞給其他部分的代碼。

  • greet_return 使用 return 返回結(jié)果,這個(gè)返回值可以在代碼的其他地方使用或存儲(chǔ)。

小結(jié)一下吧

  • 函數(shù)是代碼復(fù)用、模塊化的核心工具。

  • 使用 def 定義函數(shù),return 返回值。

  • print() 用于輸出調(diào)試信息,return 用于返回計(jì)算結(jié)果。

(二)函數(shù)參數(shù)

函數(shù)參數(shù)是函數(shù)接收外部輸入的方式。理解和掌握函數(shù)參數(shù)的使用,不僅能幫助你編寫更靈活的代碼,還能讓你的程序更具擴(kuò)展性和可維護(hù)性。

1. 位置參數(shù)

位置參數(shù)是最常見的函數(shù)參數(shù)類型,它是指參數(shù)傳遞時(shí)位置的順序決定了每個(gè)參數(shù)的含義。

例如,在函數(shù)定義時(shí),參數(shù) ab 的位置決定了它們的意義。當(dāng)調(diào)用函數(shù)時(shí),傳遞的參數(shù)值會(huì)根據(jù)位置匹配到相應(yīng)的參數(shù)。

示例:位置參數(shù)
def add(a, b):
    return a + b

result = add(3, 5)  # 位置參數(shù):3 被賦值給 a,5 被賦值給 b
print(result)  # 輸出: 8

這里的 add 函數(shù)有兩個(gè)位置參數(shù):ab。我們調(diào)用 add(3, 5) 時(shí),3 會(huì)賦值給 a5 會(huì)賦值給 b,最終返回它們的和。

2. 關(guān)鍵字參數(shù)

關(guān)鍵字參數(shù)允許你在調(diào)用函數(shù)時(shí)顯式地指定每個(gè)參數(shù)的名稱。這樣可以不關(guān)心參數(shù)的順序,只需要知道參數(shù)名。

示例:關(guān)鍵字參數(shù)
def greet(name, age):
    return f"Hello, {name}! You are {age} years old."

message = greet(age=25, name="Alice")  # 參數(shù)順序不重要
print(message)  # 輸出: Hello, Alice! You are 25 years old.

在調(diào)用 greet 函數(shù)時(shí),agename 的順序不再重要,關(guān)鍵字參數(shù)通過(guò)指定 age=25name="Alice" 來(lái)傳遞值。

3. 默認(rèn)參數(shù)

默認(rèn)參數(shù)是指在定義函數(shù)時(shí),為某些參數(shù)提供默認(rèn)值。如果調(diào)用時(shí)沒(méi)有提供這些參數(shù)的值,Python 會(huì)使用默認(rèn)值。

示例:默認(rèn)參數(shù)
def greet(name, age=18):  # age 有默認(rèn)值
    return f"Hello, {name}! You are {age} years old."

message1 = greet("Alice")  # 調(diào)用時(shí)沒(méi)有提供 age,使用默認(rèn)值
message2 = greet("Bob", 30)  # 調(diào)用時(shí)提供了 age,覆蓋默認(rèn)值

print(message1)  # 輸出: Hello, Alice! You are 18 years old.
print(message2)  # 輸出: Hello, Bob! You are 30 years old.

greet 函數(shù)中,age 有默認(rèn)值 18。如果調(diào)用時(shí)沒(méi)有傳入 age,就會(huì)使用默認(rèn)值;如果傳入了 age,則會(huì)覆蓋默認(rèn)值。

4. 可變參數(shù):*args與**kwargs

有時(shí)候我們不知道函數(shù)需要接收多少個(gè)參數(shù),這時(shí)可以使用 可變參數(shù)

  • *args 用于接收位置參數(shù),它將接收多余的位置參數(shù)并將其打包成一個(gè)元組。

  • **kwargs 用于接收關(guān)鍵字參數(shù),它將接收多余的關(guān)鍵字參數(shù)并將其打包成一個(gè)字典。

示例:*args和**kwargs
def example(*args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

# 調(diào)用函數(shù)時(shí)傳入不同數(shù)量的參數(shù)
example(1, 2, 3, name="Alice", age=25)

# 輸出:
# args: (1, 2, 3)
# kwargs: {'name': 'Alice', 'age': 25}
  • *args 將所有位置參數(shù)(1, 2, 3)打包成一個(gè)元組 (1, 2, 3)

  • **kwargs 將所有關(guān)鍵字參數(shù)(name="Alice", age=25)打包成一個(gè)字典 {'name': 'Alice', 'age': 25}。

5. 參數(shù)順序規(guī)范

當(dāng)一個(gè)函數(shù)同時(shí)使用位置參數(shù)、默認(rèn)參數(shù)和可變參數(shù)時(shí),有一定的順序規(guī)范,必須遵循以下順序:

  • 位置參數(shù)

  • 默認(rèn)參數(shù)

  • *args

  • **kwargs

示例:參數(shù)順序
def function(a, b=2, *args, c, **kwargs):
    print(a, b, args, c, kwargs)

# 調(diào)用時(shí),按照順序傳遞參數(shù)
function(1, c=3, d=4, e=5)
# 輸出: 1 2 () 3 {'d': 4, 'e': 5}
  • a 是位置參數(shù),必須最先提供。

  • b 是默認(rèn)參數(shù),如果不提供則使用默認(rèn)值。

  • *args 用于接收多余的所有位置參數(shù)。

  • c 是一個(gè)關(guān)鍵字參數(shù),調(diào)用時(shí)必須顯式指定。

  • **kwargs 用于接收多余的所有關(guān)鍵字參數(shù)。

小結(jié)一下吧

  • 位置參數(shù):根據(jù)參數(shù)順序傳遞值。

  • 關(guān)鍵字參數(shù):顯式指定參數(shù)名和值。

  • 默認(rèn)參數(shù):函數(shù)定義時(shí)為參數(shù)提供默認(rèn)值。

  • 可變參數(shù):*args 用于接收多位置參數(shù),**kwargs 用于接收多關(guān)鍵字參數(shù)。

  • 參數(shù)順序:位置參數(shù) > 默認(rèn)參數(shù) > *args > **kwargs

(三)函數(shù)返回值

在 Python 中,函數(shù)不僅可以執(zhí)行某些操作,還可以將結(jié)果“返回”給調(diào)用者。這就是 返回值(Return Value) 的概念。

通過(guò) return 語(yǔ)句,函數(shù)可以把處理的結(jié)果交給外部使用。如果函數(shù)沒(méi)有 return,那它默認(rèn)返回的是 None。

1. 使用return返回結(jié)果

基本語(yǔ)法:

def function_name(...):
    ...
    return result

示例:

def square(x):
    return x * x

result = square(5)
print(result)  # 輸出: 25

函數(shù) square 返回的是 x 的平方,調(diào)用后我們可以拿到這個(gè)結(jié)果并繼續(xù)使用。

2. 返回多個(gè)值(元組)

Python 支持從一個(gè)函數(shù)中返回多個(gè)值,這些值實(shí)際上被打包成一個(gè)元組返回。

示例:

def get_name_and_age():
    name = "Alice"
    age = 30
    return name, age

n, a = get_name_and_age()
print(n)  # Alice
print(a)  # 30

多值返回的本質(zhì)是:return name, age 等價(jià)于 return (name, age),然后通過(guò)拆包語(yǔ)法接收。

3. 函數(shù)無(wú)返回值時(shí)的表現(xiàn)

如果函數(shù)中沒(méi)有 return 語(yǔ)句,或者只是 return 而沒(méi)有值,那默認(rèn)返回的是 None

示例:

def say_hello():
    print("Hello!")

result = say_hello()
print(result)  # 輸出: None

這個(gè)函數(shù) say_hello() 雖然做了事情(打?。珱](méi)有 return,因此返回值是 None。

4. 提前終止函數(shù)執(zhí)行

return 不僅能返回值,還能用來(lái)提前終止函數(shù)的執(zhí)行。

示例:

def divide(a, b):
    if b == 0:
        return "除數(shù)不能為 0"
    return a / b

print(divide(10, 0))  # 輸出: 除數(shù)不能為 0
print(divide(10, 2))  # 輸出: 5.0

當(dāng) b 是 0 時(shí),函數(shù)遇到第一個(gè) return 后立即終止執(zhí)行,不會(huì)繼續(xù)往下運(yùn)行。

5. 將返回值作為表達(dá)式使用

函數(shù)返回值可以被用在其他表達(dá)式或函數(shù)中,像這樣:

def add(a, b):
    return a + b

print(add(2, 3) * 10)  # 輸出: 50

add(2, 3) 會(huì)返回 5,然后再與 10 相乘。

小結(jié)一下吧

內(nèi)容示例返回值說(shuō)明
返回單個(gè)值return x返回一個(gè)對(duì)象
返回多個(gè)值return x, y返回一個(gè)元組
無(wú) return 或 return Nonereturn / 無(wú) return返回 None
提前結(jié)束函數(shù)if ...: return ...直接退出函數(shù)
返回值可以參與表達(dá)式add(1, 2) * 3函數(shù)結(jié)果用于計(jì)算

(四)函數(shù)返回值類型注解(Type Hint / Type Annotation)

1. Python 3 引入的類型注解(Type Hints)

先用一句話理解:

def add(a: int, b: int) -> int:
    return a + b

?? -> int 的意思是:

這個(gè)函數(shù)“設(shè)計(jì)上”應(yīng)該返回一個(gè) int

不是強(qiáng)制,只是“聲明”。這是 給“人”和“工具”看的,不是給 Python 解釋器強(qiáng)制執(zhí)行的。

注意Python 不會(huì)強(qiáng)制檢查!下面的代碼 是合法的

def add(a: int, b: int) -> int:
    return "not a number"

Python 不會(huì)報(bào)錯(cuò)。?類型注解的作用在于:

  • IDE(PyCharm)

  • 靜態(tài)檢查工具(mypy、pyright)

  • 閱讀代碼的人(包括未來(lái)的你)

2. 為什么現(xiàn)在的 Python 項(xiàng)目都強(qiáng)烈推薦用?

2.1 PyCharm 會(huì)變得非常聰明

def foo() -> dict[str, int]:
    return {"a": 1}

你輸入:

result = foo()
result["a"].

PyCharm 會(huì)自動(dòng)提示:?? 這是 int,有哪些方法

2.2 提前發(fā)現(xiàn) bug(不用等運(yùn)行)

def get_age() -> int:
    return "18"

PyCharm / mypy 會(huì)直接警告你:

Expected int, got str

3. 常見的返回值寫法(你一定會(huì)遇到)

3.1 返回多個(gè)類型(Union)

from typing import Union

def parse(s: str) -> Union[int, None]:
    if s.isdigit():
        return int(s)
    return None

Python 3.10+ 更推薦:

def parse(s: str) -> int | None:
    ...

3.2 返回列表 / 字典

def get_names() -> list[str]:
    return ["Alice", "Bob"]

def get_scores() -> dict[str, int]:
    return {"math": 90}

3.3 返回自定義對(duì)象

class User:
    ...

def get_user() -> User:
    return User()

五、字符串操作模塊

在 Python 中,字符串(str)是最常用、最重要的數(shù)據(jù)類型之一。無(wú)論你是在處理用戶輸入、讀取文件、構(gòu)建網(wǎng)頁(yè)內(nèi)容、分析文本數(shù)據(jù),幾乎都繞不開對(duì)字符串的處理。

現(xiàn)在我們總結(jié)掌握 Python 字符串的各種操作方法,從最基本的創(chuàng)建與訪問(wèn),到復(fù)雜的格式化,我們需要學(xué)會(huì)如何清洗、切割、替換、判斷和重組字符串,并為后續(xù)的數(shù)據(jù)處理與文本分析打下堅(jiān)實(shí)基礎(chǔ)。

(一)字符串基礎(chǔ)

在 Python 中,字符串(str)是用來(lái)表示文本的數(shù)據(jù)類型。本部分介紹字符串的創(chuàng)建方式、基本特性、訪問(wèn)技巧以及常見的基本操作。

1. 字符串的定義與創(chuàng)建

字符串可以用 單引號(hào) '、雙引號(hào) "三引號(hào) ''' / """ 括起來(lái)。

# 單引號(hào)
s1 = 'hello'

# 雙引號(hào)
s2 = "world"

# 三引號(hào)(支持多行)
s3 = '''This is
a multi-line
string.'''

?? Python 中單引號(hào)和雙引號(hào)作用相同,主要用于避免轉(zhuǎn)義沖突。

2. 字符串是不可變對(duì)象

字符串是 不可變的(immutable):創(chuàng)建后無(wú)法修改,只能重新賦值。

s = "hello"
# s[0] = 'H'  # ? 錯(cuò)誤!字符串不能直接修改
s = "Hello"   # ? 只能重新賦值

3. 字符串的索引與切片

字符串可以看作字符的序列,可以通過(guò)索引或切片訪問(wèn)其部分內(nèi)容。

s = "Python"

# 索引(從 0 開始)
print(s[0])   # P
print(s[-1])  # n(最后一個(gè)字符)

# 切片 [start:end:step]
print(s[0:2])     # Py(不包括 end)
print(s[::2])     # Pto(每隔1個(gè))
print(s[::-1])    # nohytP(反轉(zhuǎn)字符串)

? 切片非常強(qiáng)大,是字符串處理中不可或缺的工具。

4. 字符串的連接與重復(fù)

# 拼接字符串
a = "Hello"
b = "World"
c = a + " " + b
print(c)  # Hello World

# 重復(fù)字符串
print("ha" * 3)   # hahaha

5. 字符串的成員運(yùn)算

s = "python"
print("p" in s)      # True
print("z" not in s)  # True

6. 字符串與類型轉(zhuǎn)換

num = 123
text = str(num)  # 數(shù)字轉(zhuǎn)字符串
print("數(shù)字是:" + text)

# 也可以使用 f-string(推薦)
print(f"數(shù)字是:{num}")

小結(jié)一下吧

操作類型常用方法 / 語(yǔ)法
創(chuàng)建字符串'abc', "abc", '''abc'''
索引s[0], s[-1]
切片s[1:4], s[::-1]
拼接與重復(fù)+, *
判斷是否存在in, not in
類型轉(zhuǎn)換str(x), f"{x}"

(二)字符串常見操作方法

Python 的字符串類型(str)內(nèi)建了大量實(shí)用的方法,幫助我們完成查找、替換、對(duì)齊、大小寫轉(zhuǎn)換、格式化等各類文本處理任務(wù)。本節(jié)將系統(tǒng)講解所有主流、實(shí)用的方法,并配合用例說(shuō)明。

1. 大小寫轉(zhuǎn)換

方法作用
.lower()轉(zhuǎn)為小寫
.upper()轉(zhuǎn)為大寫
.capitalize()首字母大寫,其余小寫
.title()每個(gè)單詞首字母大寫
.swapcase()大小寫互換
s = "hello World"
print(s.lower())       # hello world
print(s.upper())       # HELLO WORLD
print(s.capitalize())  # Hello world
print(s.title())       # Hello World
print(s.swapcase())    # HELLO wORLD

2. 查找與判斷

方法功能
.find(sub)找到子串首次出現(xiàn)的位置(找不到返回 -1)
.rfind(sub)從右側(cè)開始查找
.index(sub)與 find 類似,但找不到拋出異常
.startswith(prefix)是否以某前綴開頭
.endswith(suffix)是否以某后綴結(jié)尾
.in判斷子串是否存在
s = "hello python"
print(s.find("py"))       # 6
print(s.startswith("he")) # True
print(s.endswith("on"))   # True
print("py" in s)          # True

3. 刪除空白符與字符清洗

方法功能
.strip()刪除兩端空白符
.lstrip()刪除左側(cè)空白符
.rstrip()刪除右側(cè)空白符
.replace(old, new)替換子串
s = "  hello world  "
print(s.strip())     # "hello world"

s2 = "python,java,c"
print(s2.replace(",", " | "))  # python | java | c

4. 字符串對(duì)齊與填充

方法說(shuō)明
.center(width, char)居中填充
.ljust(width, char)左對(duì)齊填充
.rjust(width, char)右對(duì)齊填充
.zfill(width)用 0 填充左側(cè)數(shù)字部分
print("hi".center(10, "-"))  # ----hi----
print("hi".ljust(10, "."))   # hi........
print("hi".rjust(10, "*"))   # ********hi
print("42".zfill(5))         # 00042

5. 拆分與連接

方法功能
.split(sep)拆分為列表
.rsplit(sep)從右拆分
.splitlines()拆分多行字符串
'sep'.join(list)用分隔符連接列表為字符串
s = "apple,banana,grape"
print(s.split(","))         # ['apple', 'banana', 'grape']

lines = "line1\nline2\nline3"
print(lines.splitlines())   # ['line1', 'line2', 'line3']

words = ['one', 'two', 'three']
print("-".join(words))      # one-two-three

6. 內(nèi)容判斷類方法(返回布爾值)

方法判斷類型
.isalpha()是否全字母
.isdigit()是否全數(shù)字
.isalnum()是否全是字母或數(shù)字
.isspace()是否全是空白符
.isupper()是否全為大寫
.islower()是否全為小寫
.istitle()是否符合標(biāo)題規(guī)范(首字母大寫)
print("abc".isalpha())     # True
print("123".isdigit())     # True
print("abc123".isalnum())  # True
print("   ".isspace())     # True

7. 高級(jí)字符串格式化(f-string)

name = "Alice"
age = 30

# 推薦方式:f-string(Python 3.6+)
print(f"{name} is {age} years old.")  # Alice is 30 years old

# 老式:format()
print("{} is {} years old.".format(name, age))

# 占位對(duì)齊控制
print(f"|{name:^10}|{age:>3}|")  # 居中+右對(duì)齊:|  Alice   | 30|

8. 轉(zhuǎn)義字符與原始字符串

字符含義
\n換行
\t制表符
\\反斜杠
r""原始字符串,不轉(zhuǎn)義
print("hello\nworld")     # 換行
print(r"c:\new\folder")   # c:\new\folder

9. 其他實(shí)用技巧

  • 長(zhǎng)字符串拼接:

    s = (
        "This is a very long string "
        "split across multiple lines "
        "but still valid."
    )
    
  • 字符串比較支持 <, >, == 等字典序?qū)Ρ龋?/p>

    print("apple" < "banana")  # True

小結(jié):常用字符串方法分類對(duì)照表

類型常用方法
查找判斷find(), startswith(), in
修改清洗strip(), replace()
大小寫處理lower(), capitalize()
對(duì)齊填充center(), zfill()
格式化f"", format()
判斷內(nèi)容isdigit(), isalpha()
分割拼接split(), join()
其他len(), 轉(zhuǎn)義、比較等

(三)字符串切片與索引

1. 字符串索引(正向索引 / 負(fù)向索引)

Python 字符串是序列類型,每個(gè)字符都有對(duì)應(yīng)的索引位置。我們可以通過(guò)索引訪問(wèn)字符串中的單個(gè)字符。

?? 正向索引(從 0 開始)
s = "python"
print(s[0])  # p
print(s[1])  # y
print(s[5])  # n
字符python
索引012345
?? 負(fù)向索引(從 -1 開始,表示從右往左)
s = "python"
print(s[-1])  # n
print(s[-2])  # o
print(s[-6])  # p
字符python
索引-6-5-4-3-2-1

注意

  • 超出索引范圍(如 s[10])會(huì)拋出 IndexError

  • 字符串是 不可變對(duì)象,不能通過(guò)索引修改某個(gè)字符。

2. 字符串切片([start:stop:step])

切片(slice)是從字符串中提取子串的一種方式,語(yǔ)法格式為:

s[start : stop : step]
  • start:起始索引(包含)

  • stop:終止索引(不包含)

  • step:步長(zhǎng)(默認(rèn)為 1)

基礎(chǔ)切片
s = "Hello, Python!"

print(s[0:5])   # Hello
print(s[7:13])  # Python
print(s[:5])    # Hello(從頭開始)
print(s[7:])    # Python!(直到結(jié)尾)
使用負(fù)數(shù)索引切片
s = "abcdefg"
print(s[-4:-1])  # def
print(s[-7:-4])  # abc
添加步長(zhǎng)(step)
s = "0123456789"
print(s[::2])     # 02468(每?jī)蓚€(gè)字符取一個(gè))
print(s[1::3])    # 147(從索引 1 開始,每隔 3 個(gè)取)
反向切片(步長(zhǎng)為負(fù)數(shù))
s = "abcdef"
print(s[::-1])   # fedcba(字符串反轉(zhuǎn))
print(s[-1:-7:-1]) # fedcba(等同上行)
切片邊界記憶口訣
  • 包頭不包尾:起始位置包含,結(jié)束位置不包含。

  • 步長(zhǎng)方向一致:正數(shù)步長(zhǎng)從左到右,負(fù)數(shù)步長(zhǎng)從右到左。

  • 索引可以為負(fù):負(fù)索引從末尾向前數(shù)。

3. 字符串的遍歷

遍歷字符串可以逐個(gè)訪問(wèn)其字符,常用于統(tǒng)計(jì)、查找、生成新字符串等任務(wù)。

基礎(chǔ)遍歷
s = "hello"
for c in s:
    print(c)

輸出:

h
e
l
l
o
帶索引遍歷(推薦:使用 enumerate)
s = "hello"
for index, char in enumerate(s):
    print(f"{index} -> {char}")

輸出:

0 -> h
1 -> e
2 -> l
3 -> l
4 -> o

經(jīng)典應(yīng)用場(chǎng)景小結(jié)

場(chǎng)景示例
提取子串s[3:7]
字符串反轉(zhuǎn)s[::-1]
判斷回文s == s[::-1]
截取前綴/后綴s[:3]s[-3:]
每隔一個(gè)字符取s[::2]

(四)字符串格式化

Python 提供了三種主要的字符串格式化方式:

  • % 占位符格式化(經(jīng)典寫法)

  • str.format() 方法格式化(兼容寫法)

  • f-string 格式化(推薦方式,Python 3.6+)

1.%占位符格式化(C 風(fēng)格)

這是最早期的格式化方式,語(yǔ)法類似于 C 語(yǔ)言:

name = "Alice"
age = 25
print("My name is %s and I am %d years old." % (name, age))
占位符含義
%s字符串
%d整數(shù)
%f浮點(diǎn)數(shù)(默認(rèn)小數(shù)點(diǎn)后 6 位)
%.2f浮點(diǎn)數(shù)保留 2 位小數(shù)

缺點(diǎn):可讀性差、容易出錯(cuò),不推薦用于新代碼。

2.str.format()方法格式化

引入于 Python 2.7 / 3.0,支持位置參數(shù)、關(guān)鍵字參數(shù),更靈活:

name = "Alice"
age = 25
print("My name is {} and I am {} years old.".format(name, age))
?? 支持位置參數(shù) / 關(guān)鍵字參數(shù)
print("Hello, {0}. You are {1}.".format("Bob", 30))
print("Hello, {name}. You are {age}.".format(name="Bob", age=30))
?? 支持格式控制
pi = 3.1415926
print("Pi is {:.2f}".format(pi))  # Pi is 3.14

缺點(diǎn):寫法較冗長(zhǎng),推薦 f-string 替代。

3.f-string 格式化(Python 3.6+,推薦?)

最現(xiàn)代、最簡(jiǎn)潔的格式化方式,代碼更清晰,推薦作為首選寫法。

name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")
?? 支持表達(dá)式
a = 5
b = 3
print(f"{a} +  = {a + b}")
?? 支持格式化控制
pi = 3.1415926
print(f"Pi rounded to 2 digits: {pi:.2f}")
?? 與函數(shù)、數(shù)據(jù)結(jié)構(gòu)結(jié)合
user = {"name": "Bob", "score": 88}
print(f"{user['name']} scored {user['score']}")

三種方式對(duì)比

特性% 格式化str.format()f-string
可讀性?????
功能強(qiáng)大一般?????
寫法簡(jiǎn)潔一般????
推薦程度? 不推薦? 過(guò)渡用法??? 首選

小結(jié)一下吧

  • 新代碼推薦 f-string,語(yǔ)法簡(jiǎn)潔、表達(dá)能力強(qiáng)。

  • str.format() 適用于兼容舊版本 Python。

  • % 占位符方式適合了解,不建議用于正式項(xiàng)目中。

六、列表、字典與集合 —— Python 中的數(shù)據(jù)組織能力

(一)為什么需要“數(shù)據(jù)結(jié)構(gòu)”

在前面的章節(jié)中,我們已經(jīng)學(xué)習(xí)了 變量、基本數(shù)據(jù)類型、控制流和函數(shù)以及字符串。這些知識(shí)可以幫助我們描述一個(gè)值、處理一次邏輯、完成一個(gè)功能

但在真實(shí)的程序中,我們面對(duì)的往往不是“一個(gè)值”,而是:

  • 一組數(shù)據(jù)

  • 多條記錄

  • 多個(gè)對(duì)象

  • 一批狀態(tài)或配置項(xiàng)

這正是 “數(shù)據(jù)結(jié)構(gòu)”存在的意義

1. 單個(gè)變量的局限性

先看一個(gè)最簡(jiǎn)單的例子。如果我們只需要保存一個(gè)人的名字,用一個(gè)變量就足夠:

name = "張彥峰"

但如果現(xiàn)在要保存 10 個(gè)、100 個(gè)、甚至更多名字 呢?你顯然不可能這樣寫:

name1 = "盧政伯" name2 = "呂鴻昌" name3 = "秦學(xué)磊"

這種寫法存在明顯問(wèn)題:

  • 變量數(shù)量不可控

  • 無(wú)法方便地進(jìn)行循環(huán)處理

  • 代碼幾乎不可維護(hù)

這時(shí),我們需要一種方式,把“一組相關(guān)的數(shù)據(jù)”組織在一起。

2. 從“一個(gè)值”到“一組值”

繼續(xù)剛才的例子,如果我們希望把多個(gè)名字放在一起,Python 提供了 列表(list) 這樣的數(shù)據(jù)結(jié)構(gòu):

names = ["張彥峰","盧政伯","呂鴻昌","秦學(xué)磊"]

這樣做的好處是:

  • 所有名字屬于同一個(gè)整體

  • 可以通過(guò)循環(huán)統(tǒng)一處理

  • 可以按順序訪問(wèn)、修改、刪除

這一步,本質(zhì)上是從:“一個(gè)變量保存一個(gè)值”升級(jí)為:“一個(gè)變量保存一組有結(jié)構(gòu)的數(shù)據(jù)”

3. 一條記錄 vs 多條記錄

再看一個(gè)更貼近實(shí)際開發(fā)的例子。假設(shè)我們要表示一個(gè)用戶的信息:

user_name = "張彥峰" user_age = 18 user_email = "zyf@alibaba.com"

這種寫法的問(wèn)題在于:

  • 信息是分散的

  • 很難整體傳遞或管理

  • 字段之間缺乏明確的“歸屬關(guān)系”

這時(shí),更合理的做法是使用 字典(dict)

user = {
    "name": "張彥峰",
    "age": 18,
    "email": "zyf@alibaba.com"
}

字典的特點(diǎn)是:

  • 通過(guò) key(鍵) 來(lái)訪問(wèn)數(shù)據(jù)

  • 每個(gè)字段都有清晰的含義

  • 非常適合描述“一條記錄”

如果現(xiàn)在有 多條用戶記錄,我們就可以把多個(gè)字典放進(jìn)一個(gè)列表中:

users = [
    {"name": "張彥峰", "age": 18},
    {"name": "張琴", "age": 18}
]

你可以看到:數(shù)據(jù)結(jié)構(gòu)是可以組合使用的,這正是后面處理嵌套數(shù)據(jù)(如 JSON)的基礎(chǔ)。

4. 最常用的幾種數(shù)據(jù)結(jié)構(gòu)

在本章中,我們將系統(tǒng)學(xué)習(xí) Python 中最常用的幾種數(shù)據(jù)結(jié)構(gòu):

  • 列表(list):用于存儲(chǔ)有序、可變的一組數(shù)據(jù)

  • 字典(dict):用于存儲(chǔ)鍵值映射關(guān)系

  • 集合(set):用于去重和集合運(yùn)算

  • 元組(tuple):用于表示不可變的數(shù)據(jù)組合

通過(guò)這一章,你將逐步建立起這樣的能力:

根據(jù)問(wèn)題特點(diǎn),選擇合適的數(shù)據(jù)結(jié)構(gòu),并高效地操作它們

這也是后續(xù)學(xué)習(xí) 嵌套結(jié)構(gòu)、JSON 數(shù)據(jù)解析、配置處理 的必要基礎(chǔ)。

(二)列表(List):有序數(shù)據(jù)的容器

列表是 Python 中最常用且強(qiáng)大的數(shù)據(jù)結(jié)構(gòu)之一,廣泛用于存儲(chǔ)有序、可變的數(shù)據(jù)。作為一個(gè)容器類型,它不僅能存儲(chǔ)多種數(shù)據(jù)類型,還能高效支持?jǐn)?shù)據(jù)的添加、刪除、修改和訪問(wèn)。掌握列表的使用是理解 Python 數(shù)據(jù)處理能力的重要基礎(chǔ)。

1. 列表的基本概念

列表(list)是一個(gè)有序的容器,可以存儲(chǔ)任意類型的數(shù)據(jù),包括整數(shù)、字符串、布爾值,甚至是其他列表。列表的核心特點(diǎn)包括:

  • 有序性:列表中的元素是按順序排列的,每個(gè)元素都有一個(gè)對(duì)應(yīng)的索引,索引從 0 開始。

  • 可變性:列表是可變的,可以在原地修改列表的內(nèi)容,例如添加、刪除或更新元素。

  • 支持多種數(shù)據(jù)類型:列表可以包含不同類型的元素,甚至可以存儲(chǔ)其他容器類型(如列表、字典等)。

# 示例:包含整數(shù)的列表
numbers = [1, 2, 3, 4, 5]

# 示例:包含不同數(shù)據(jù)類型的列表
info = ["Alice", 18, True, 3.14, ["nested", "list"]]

關(guān)鍵點(diǎn)與字符串(str)類似,列表也支持通過(guò)索引訪問(wèn)和切片操作,但字符串是不可變的,而列表可以直接修改。

2. 列表的創(chuàng)建與訪問(wèn)

創(chuàng)建列表

列表的創(chuàng)建非常簡(jiǎn)便,可以通過(guò)方括號(hào) [] 來(lái)定義??梢詣?chuàng)建空列表、包含多個(gè)元素的列表,或是包含混合類型元素的列表。

# 空列表
empty_list = []

# 含有多個(gè)整數(shù)的列表
numbers = [1, 2, 3, 4, 5]

# 含有不同類型的元素的列表
mixed = [1, "Alice", True, 3.14]
訪問(wèn)列表元素

通過(guò)索引訪問(wèn)列表中的元素,索引從 0 開始。列表還支持負(fù)索引,允許從列表的末尾開始訪問(wèn)元素。

numbers = [10, 20, 30, 40]

# 正向索引
print(numbers[0])  # 10
print(numbers[3])  # 40

# 負(fù)向索引
print(numbers[-1])  # 40
print(numbers[-2])  # 30

此外,列表支持切片操作,可以通過(guò)指定起始和結(jié)束索引來(lái)獲取子列表。

# 切片示例
print(numbers[1:3])  # [20, 30]
print(numbers[:2])   # [10, 20]
print(numbers[2:])   # [30, 40]

注意:切片操作返回的是新列表,原列表內(nèi)容不受影響。

3. 列表的常用修改操作

列表是可變的,意味著可以在原地修改其內(nèi)容。常見的修改操作包括添加元素刪除元素修改元素。

添加元素
  • append():將元素添加到列表的末尾。

  • insert():將元素插入到指定的索引位置。

  • extend():批量追加

# 示例:添加元素
nums = [1, 2, 3]
nums.append(4)  # 在末尾添加元素
nums.insert(1, 1.5)  # 在索引 1 處插入元素
nums.extend([3, 4])   # [1, 2, 3, 4]

print(nums)  # 輸出: [1, 1.5, 2, 3, 4, 3, 4]
刪除元素
  • remove():刪除第一個(gè)匹配到的元素。

  • pop():刪除并返回指定索引位置的元素(默認(rèn)刪除最后一個(gè)元素)。

  • del:根據(jù)索引刪除元素。

  • clear():清空列表

# 示例:刪除元素
nums.remove(1.5)  # 刪除元素 1.5
popped_element = nums.pop()  # 刪除并返回最后一個(gè)元素
del nums[0]  # 刪除索引 0 處的元素

print(nums)  # 輸出: [2, 3, 4, 3]
修改元素

通過(guò)索引可以直接修改列表中的元素:

nums[0] = 10  # 將索引 0 處的元素修改為 10
print(nums)    # 輸出: [10, 3]

4. 列表的遍歷與循環(huán)配合

遍歷列表元素

遍歷列表元素時(shí),最常用的是 for 循環(huán)。可以直接遍歷列表的每個(gè)元素,或者使用 range() 函數(shù)配合索引來(lái)遍歷列表。

# 直接遍歷元素
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)  # 輸出每個(gè)水果

# 使用索引遍歷
for i in range(len(fruits)):
    print(i, fruits[i])  # 輸出索引和值

# 使用 enumerate 獲取索引和值
for idx, fruit in enumerate(fruits):
    print(idx, fruit)  # 輸出索引和值

應(yīng)用場(chǎng)景

  • 只關(guān)心值:直接遍歷元素。

  • 需要索引:使用 range()enumerate()。

5. 列表的常用內(nèi)置操作與函數(shù)

Python 提供了豐富的內(nèi)置函數(shù)和方法來(lái)操作列表。以下是一些常用操作:

  • len():返回列表的長(zhǎng)度。

  • in:檢查元素是否存在于列表中。

  • count():統(tǒng)計(jì)元素在列表中出現(xiàn)的次數(shù)。

  • index():查找元素首次出現(xiàn)的位置。

  • sort():原地排序。

  • sorted():返回一個(gè)新排序的列表。

  • reverse():原地反轉(zhuǎn)列表。

nums = [4, 2, 7, 1]

print(len(nums))     # 輸出: 4
print(2 in nums)     # 輸出: True
print(nums.count(2)) # 輸出: 1
print(nums.index(7)) # 輸出: 2

nums.sort()          # 原地排序
sorted_nums = sorted(nums)  # 返回新列表
nums.reverse()       # 原地反轉(zhuǎn)

注意sort()reverse() 會(huì)改變?cè)斜?,?sorted() 返回新列表。

6. 列表推導(dǎo)式(List Comprehension)

列表推導(dǎo)式是 Python 中非常強(qiáng)大且簡(jiǎn)潔的語(yǔ)法,它允許在一行代碼內(nèi)創(chuàng)建一個(gè)新的列表。相比于傳統(tǒng)的 for 循環(huán),列表推導(dǎo)式更加簡(jiǎn)潔且執(zhí)行效率高。

# 基本語(yǔ)法:生成平方數(shù)列表
squares = [x**2 for x in range(5)]
print(squares)  # 輸出: [0, 1, 4, 9, 16]

# 帶條件的推導(dǎo)式:生成偶數(shù)的平方數(shù)列表
even_squares = [x**2 for x in range(5) if x % 2 == 0]
print(even_squares)  # 輸出: [0, 4, 16]

列表推導(dǎo)式的優(yōu)勢(shì):

  • 簡(jiǎn)潔性:可以用一行代碼替代多行。

  • 可讀性:語(yǔ)法清晰、易懂。

  • 性能:避免了手動(dòng)使用 append()。

7. 淺拷貝(Shallow Copy)與深拷貝(Deep Copy)

在 Python 中,理解淺拷貝與深拷貝的前提,是理解一個(gè)核心事實(shí):

Python 中的變量,本質(zhì)上保存的是對(duì)象的引用(reference),而不是對(duì)象本身。

因此,“拷貝”并不等價(jià)于“生成一個(gè)完全獨(dú)立的新對(duì)象”,是否真正獨(dú)立,取決于拷貝的層級(jí)。

7.1 對(duì)象、引用與容器的關(guān)系模型

先從一個(gè)最小示例理解引用關(guān)系:

a = [1, 2, 3]
b = a

此時(shí):

  • ab 指向 同一個(gè) list 對(duì)象

  • 對(duì) a 的任何修改,都會(huì)體現(xiàn)在 b

a[0] = 100
print(b)  # [100, 2, 3]

這不是拷貝,而是 引用綁定(aliasing)。

7.2 淺拷貝(Shallow Copy)

淺拷貝的定義:創(chuàng)建一個(gè)新的容器對(duì)象,但容器中保存的元素仍然是對(duì)原對(duì)象中元素的引用。

換句話說(shuō):

  • 外層容器是新的

  • 內(nèi)層對(duì)象是共享的

常見的淺拷貝方式

以下方式都會(huì)產(chǎn)生淺拷貝:

b = a.copy()
b = a[:]
b = list(a)

淺拷貝的行為示意

a = [[1, 2], [3, 4]]
b = a.copy()

內(nèi)存關(guān)系可以抽象為:

a ──? list ──? [ L1 , L2 ]
b ──? list ──? [ L1 , L2 ]
  • ab 是兩個(gè)不同的列表對(duì)象

  • 但它們內(nèi)部的 L1、L2 指向同一個(gè)子列表對(duì)象

淺拷貝的典型“坑”

a = [[1, 2], [3, 4]]
b = a.copy()

b[0][0] = 100
print(a)  # [[100, 2], [3, 4]]

原因分析:

  • b[0]a[0] 指向同一子列表

  • 修改子列表,會(huì)影響所有引用它的容器

淺拷貝何時(shí)是安全的

列表中包含 不可變對(duì)象,后續(xù)操作只涉及 整體替換,不修改內(nèi)部對(duì)象

a = [1, 2, 3, "abc"]
b = a.copy()

b[0] = 100  # 不影響 a

print(a) # [1, 2, 3, 'abc']
print(b) # [100, 2, 3, 'abc']
7.3 深拷貝(Deep Copy)

深拷貝的定義:遞歸地復(fù)制對(duì)象本身以及其內(nèi)部引用的所有子對(duì)象,生成完全獨(dú)立的對(duì)象樹。

特點(diǎn):

  • 外層容器獨(dú)立

  • 內(nèi)層對(duì)象也完全獨(dú)立

  • 修改任何層級(jí)都不會(huì)相互影響

深拷貝的標(biāo)準(zhǔn)方式

import copy

b = copy.deepcopy(a)

深拷貝的行為示意

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)

內(nèi)存模型:

a ──? list ──? [ L1 , L2 ]
b ──? list ──? [ L1' , L2' ]
  • L1 ≠ L1'

  • L2 ≠ L2'

深拷貝示例驗(yàn)證

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)

b[0][0] = 100
print(a)  # [[1, 2], [3, 4]]
7.4 淺拷貝 vs 深拷貝的核心對(duì)比
維度淺拷貝深拷貝
外層容器新對(duì)象新對(duì)象
內(nèi)層對(duì)象共享引用完全獨(dú)立
性能相對(duì)較低
內(nèi)存占用
修改風(fēng)險(xiǎn)高(嵌套結(jié)構(gòu))極低

8. list * n與淺拷貝的本質(zhì)關(guān)系

a = [[0]] * 3

等價(jià)于:

sub = [0]
a = [sub, sub, sub]

因此:

a[0][0] = 1
print(a)  # [[1], [1], [1]]

這是淺拷貝的一種極端形式:

  • 外層列表新建

  • 內(nèi)層對(duì)象全部指向同一個(gè)引用

正確構(gòu)造獨(dú)立子列表的方式

a = [[0] for _ in range(3)]

9. 列表的常見坑

淺拷貝問(wèn)題

當(dāng)使用 * 運(yùn)算符復(fù)制包含可變?cè)氐牧斜頃r(shí),可能會(huì)發(fā)生意外的引用問(wèn)題。例如:

a = [[1, 2]] * 3
a[0][0] = 100
print(a)  # 輸出: [[100, 2], [100, 2], [100, 2]]

原因:所有子列表都引用了同一個(gè)內(nèi)存地址,修改一個(gè)元素會(huì)影響所有子列表??梢允褂?copy.deepcopy() 來(lái)避免這種問(wèn)題。

遍歷時(shí)修改列表

直接在遍歷列表時(shí)修改列表,可能會(huì)導(dǎo)致不預(yù)期的結(jié)果。例如:

nums = [1, 2, 3, 4]
for n in nums:
    if n % 2 == 0:
        nums.remove(n)  # 刪除偶數(shù)元素
print(nums)  # 輸出: [1, 3]

解決辦法:遍歷列表的副本,如 nums[:],或者使用列表推導(dǎo)式來(lái)過(guò)濾元素。

# 解決方法:遍歷副本
for n in nums[:]:
    if n % 2 == 0:
        nums.remove(n)

小結(jié)一下吧

  • 列表是 有序、可變 的數(shù)據(jù)容器,是 Python 數(shù)據(jù)結(jié)構(gòu)的核心之一

  • 支持索引訪問(wèn)、切片操作、原地修改和高效遍歷

  • 提供大量?jī)?nèi)置方法,配合列表推導(dǎo)式可以寫出高效、優(yōu)雅的代碼

  • 常見風(fēng)險(xiǎn)點(diǎn)主要集中在:

    • 淺拷貝與引用共享

    • 遍歷過(guò)程中修改列表

    • 誤用 list * n 構(gòu)造嵌套結(jié)構(gòu)

熟練掌握列表,將為后續(xù)學(xué)習(xí)字典、集合、嵌套數(shù)據(jù)結(jié)構(gòu)以及 JSON / 數(shù)據(jù)分析場(chǎng)景打下堅(jiān)實(shí)基礎(chǔ)。

(三)字典(dict):鍵值映射的數(shù)據(jù)結(jié)構(gòu)

字典(dict)是 Python 中最核心、使用頻率極高的一種內(nèi)置數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ) 鍵值對(duì)(key-value)映射關(guān)系。它通過(guò) key 直接定位 value,而不是像列表那樣依賴下標(biāo)位置,因此在表達(dá)“記錄型數(shù)據(jù)”“配置數(shù)據(jù)”“映射關(guān)系”時(shí)具有不可替代的優(yōu)勢(shì)。

從底層實(shí)現(xiàn)角度看,Python 字典基于 哈希表(Hash Table) 實(shí)現(xiàn),在絕大多數(shù)場(chǎng)景下,其查找、插入、刪除操作的時(shí)間復(fù)雜度都接近 O(1)。

1. 字典的設(shè)計(jì)思想

為什么需要字典?

列表適合解決以下問(wèn)題:

  • 數(shù)據(jù) 有明確順序

  • 主要通過(guò) 位置(索引) 訪問(wèn)

但在很多真實(shí)業(yè)務(wù)中,我們更關(guān)心的是:

  • “這個(gè)人的 年齡 是多少?”

  • “這個(gè)配置項(xiàng) timeout 對(duì)應(yīng)的值是多少?”

此時(shí),如果仍然依賴下標(biāo)訪問(wèn):

  • 可讀性差

  • 容易出錯(cuò)

  • 不利于擴(kuò)展和維護(hù)

字典的核心思想是:

用有意義的 key,直接映射到對(duì)應(yīng)的 value

對(duì)比示例

# 使用列表表示用戶信息(語(yǔ)義不清晰)
user_list = ["Alice", 18, "alice@example.com"]

# 使用字典表示用戶信息(結(jié)構(gòu)清晰)
user_dict = {
    "name": "Alice",
    "age": 18,
    "email": "alice@example.com"
}

字典的優(yōu)勢(shì)

  • 字段含義清晰,代碼自解釋

  • 不依賴順序,結(jié)構(gòu)穩(wěn)定

  • 便于新增、刪除字段

  • 非常貼近 JSON / 配置文件 / 數(shù)據(jù)庫(kù)記錄的結(jié)構(gòu)

2. 字典的基本使用

創(chuàng)建字典
# 使用花括號(hào)(最常見)
user = {"name": "Alice", "age": 18}

# 使用 dict 構(gòu)造函數(shù)
user2 = dict(name="Bob", age=20)

# 從鍵值對(duì)列表創(chuàng)建
pairs = [("name", "Charlie"), ("age", 22)]
user3 = dict(pairs)
訪問(wèn) value
print(user["name"])        # Alice
print(user.get("age"))     # 18
重要約束說(shuō)明
  • key 必須唯一:后定義的 key 會(huì)覆蓋之前的值

  • key 必須是不可變類型

    • 合法:str、int、float、tuple

    • 非法:list、dict、set

# 合法
d = {(1, 2): "ok"}

# 非法(會(huì)拋出 TypeError)
d = {[1, 2]: "error"}

3. 字典的增刪改查(CRUD)

新增 / 修改(統(tǒng)一語(yǔ)法)
user["email"] = "alice@example.com"  # 新增
user["age"] = 19                       # 修改

字典不會(huì)區(qū)分“新增”和“修改”,是否存在 key 決定行為。

刪除元素
# 刪除指定 key
del user["email"]

# 刪除并返回 value
age = user.pop("age")
# 指定默認(rèn)值,避免 KeyError
age = user.pop("age", None)
查詢
user["name"]                 # 不存在會(huì)拋 KeyError
user.get("email")             # 不存在返回 None
user.get("email", "N/A")     # 返回默認(rèn)值
是否存在某個(gè) key
"name" in user      # True / False
"email" not in user # True / False

4. 字典的遍歷方式

遍歷 key(默認(rèn)行為)
for key in user:
    print(key, user[key])
遍歷 value
for value in user.values():
    print(value)
遍歷 key-value 對(duì)(最常用)
for key, value in user.items():
    print(key, value)
遍歷時(shí)的注意事項(xiàng)
  • 遍歷過(guò)程中 不建議修改字典結(jié)構(gòu)(增刪 key)

  • 若需要修改,可先遍歷 list(user.keys())

5. 字典的常用方法與典型模式

常用方法速覽
user.keys()        # 所有 key(視圖對(duì)象)
user.values()      # 所有 value
user.items()       # (key, value) 對(duì)
user.clear()       # 清空字典
user.copy()        # 淺拷貝
setdefault:安全設(shè)置默認(rèn)值
user.setdefault("age", 18)

等價(jià)于:

if "age" not in user:
    user["age"] = 18
update:批量更新
user.update({"email": "alice@example.com", "age": 20})
典型模式一:計(jì)數(shù)器
words = ["apple", "banana", "apple", "cherry"]
counter = {}

for word in words:
    counter[word] = counter.get(word, 0) + 1

print(counter)
典型模式二:分組
students = [
    ("Alice", "A"),
    ("Bob", "B"),
    ("Charlie", "A")
]

groups = {}
for name, grade in students:
    groups.setdefault(grade, []).append(name)

print(groups) #{'A': ['Alice', 'Charlie'], 'B': ['Bob']}

6. 字典的拷貝與可變性

淺拷貝(Shallow Copy)
d1 = {"a": [1, 2]}
d2 = d1.copy()

d2["a"].append(3)
print(d1)  # {'a': [1, 2, 3]}

淺拷貝只復(fù)制“引用”,不會(huì)復(fù)制內(nèi)部的可變對(duì)象。

深拷貝(Deep Copy)
import copy

d1 = {"a": [1, 2]}
d2 = copy.deepcopy(d1)

d2["a"].append(3)
print(d1)  # {'a': [1, 2]}

7. 字典與列表的組合(復(fù)雜結(jié)構(gòu)建模)

列表中放字典
users = [
    {"name": "Alice", "age": 18},
    {"name": "Bob", "age": 20}
]

for user in users:
    print(user["name"], user["age"])
字典中放列表
grades = {
    "Alice": [90, 95, 88],
    "Bob": [75, 80, 82]
}

for name, scores in grades.items():
    avg = sum(scores) / len(scores)
    print(name, avg)
多層嵌套字典
users = {
    "Alice": {"age": 18, "email": "alice@example.com"},
    "Bob": {"age": 20, "email": "bob@example.com"}
}

print(users["Alice"]["email"])

小結(jié)一下吧

  • 字典是 鍵值映射容器,核心優(yōu)勢(shì)是按 key 快速訪問(wèn)

  • 基于哈希表實(shí)現(xiàn),查找效率高

  • 支持完整的增刪改查操作

  • 提供豐富的方法與常見編程模式

  • 可與列表自由組合,構(gòu)建任意復(fù)雜數(shù)據(jù)結(jié)構(gòu)

熟練掌握字典,是后續(xù)學(xué)習(xí) JSON 處理、配置管理、Web 開發(fā)、數(shù)據(jù)分析 的關(guān)鍵基礎(chǔ)。

(四)集合(set):去重與集合運(yùn)算

集合(set)是 Python 中用于存儲(chǔ)唯一元素并支持數(shù)學(xué)集合運(yùn)算的一種內(nèi)置數(shù)據(jù)結(jié)構(gòu)。其核心價(jià)值在于:

  • 天然去重

  • 高效的成員判斷(O(1) 平均時(shí)間復(fù)雜度)

  • 直觀表達(dá)集合關(guān)系(交集、并集、差集等)

在實(shí)際開發(fā)中,集合常用于數(shù)據(jù)清洗、權(quán)限控制、標(biāo)簽計(jì)算、關(guān)系判斷等場(chǎng)景。

1. 什么是集合(set)

集合的概念來(lái)源于數(shù)學(xué)中的集合:一組不重復(fù)的元素構(gòu)成的整體。

# 使用大括號(hào)創(chuàng)建集合
fruits = {"apple", "banana", "cherry"}
print(fruits)
# 輸出順序不固定,例如:{'banana', 'apple', 'cherry'}

# 使用 set() 構(gòu)造函數(shù)
nums = set([1, 2, 3, 2, 1])
print(nums)  # {1, 2, 3},自動(dòng)去重

核心特性

  • 無(wú)序(unordered)不支持索引和切片操作;元素順序不穩(wěn)定,每次打印結(jié)果可能不同

  • 元素唯一(unique)相同元素只會(huì)保留一份,適合用于去重、排重邏輯

  • 成員判斷高效x in set 的時(shí)間復(fù)雜度為 O(1),明顯快于列表的 O(n)

  • 僅支持可哈希(hashable)類型合法元素:int、float、str、tuple;非法元素:list、dict、set

s = {(1, 2), "abc", 10}   # 合法
# s = {[1, 2], 3}         # TypeError: unhashable type: 'list'

2. 集合的創(chuàng)建方式

# 空集合(注意不能用 {})
empty_set = set()

# 從列表 / 元組 / 字符串創(chuàng)建
set([1, 2, 2, 3])
set(("a", "b", "a"))
set("hello")   # {'h', 'e', 'l', 'o'}

?? {} 表示空字典,而不是空集合。

3. 集合的基本操作

添加元素
nums = {1, 2, 3}
nums.add(4)
print(nums)  # {1, 2, 3, 4}
  • add():一次只能添加一個(gè)元素

刪除元素
nums.remove(2)    # 元素不存在會(huì)拋 KeyError
nums.discard(5)   # 元素不存在不會(huì)報(bào)錯(cuò)
popped = nums.pop()  # 隨機(jī)刪除并返回一個(gè)元素
nums.clear()      # 清空集合

對(duì)比說(shuō)明

方法元素不存在時(shí)使用建議
remove拋異常確保元素一定存在
discard不報(bào)錯(cuò)更安全,推薦
pop隨機(jī)刪除不依賴具體元素
成員判斷
nums = {1, 2, 3}
print(2 in nums)       # True
print(5 not in nums)  # True

集合是做“是否存在”判斷的首選結(jié)構(gòu)。

4. 集合運(yùn)算(重點(diǎn))

集合支持與數(shù)學(xué)集合一致的運(yùn)算語(yǔ)義。

a = {1, 2, 3}
b = {3, 4, 5}
并集(Union)
print(a | b)
print(a.union(b))
# {1, 2, 3, 4, 5}
交集(Intersection)
print(a & b)
print(a.intersection(b))
# {3}
差集(Difference)
print(a - b)
print(a.difference(b))
# {1, 2}
對(duì)稱差集(Symmetric Difference)
print(a ^ b)
print(a.symmetric_difference(b))
# {1, 2, 4, 5}

5. 集合關(guān)系判斷

a = {1, 2}
b = {1, 2, 3}
print(a.issubset(b))      # True  子集
print(b.issuperset(a))   # True  超集
print(a.isdisjoint({4})) # True  是否無(wú)交集

常用于:權(quán)限校驗(yàn)、條件覆蓋判斷。

6. 可變集合與不可變集合

set(可變)
  • 支持 add / remove

  • 不能作為字典的 key

frozenset(不可變)
fs = frozenset([1, 2, 3])
  • 一旦創(chuàng)建不可修改

  • 可作為字典 key 或集合元素

  • 常用于配置、常量集合

7. 典型應(yīng)用場(chǎng)景

去重
nums = [1, 2, 2, 3, 4, 4]
unique_nums = list(set(nums))
權(quán)限 / 標(biāo)簽判斷
user_roles = {"admin", "editor"}
required_roles = {"editor", "viewer"}

if user_roles & required_roles:
    print("有權(quán)限")
查找共同元素
team_a = {"Alice", "Bob", "Charlie"}
team_b = {"Bob", "David"}

common = team_a & team_b
數(shù)據(jù)差異分析
old_users = {1, 2, 3}
new_users = {2, 3, 4}

lost = old_users - new_users   # 流失用戶
added = new_users - old_users  # 新增用戶

8. 與列表、字典的對(duì)比

結(jié)構(gòu)是否有序是否可重復(fù)核心用途
list順序數(shù)據(jù)
dict是(3.7+)key 不可重復(fù)映射關(guān)系
set去重 / 關(guān)系計(jì)算

小結(jié)一下吧

  • 集合是 無(wú)序、不重復(fù) 的數(shù)據(jù)結(jié)構(gòu)

  • 成員判斷和集合運(yùn)算效率極高

  • 核心能力:

    • 去重

    • 并 / 交 / 差 / 對(duì)稱差

    • 子集 / 超集判斷

  • 是處理“關(guān)系型數(shù)據(jù)”和“唯一性約束”的利器

掌握集合后,你可以用更簡(jiǎn)潔、更高效的方式解決大量實(shí)際問(wèn)題,為后續(xù)復(fù)雜數(shù)據(jù)結(jié)構(gòu)和算法學(xué)習(xí)打下堅(jiān)實(shí)基礎(chǔ)。

(五)元組(tuple):不可變序列

元組(tuple)是 Python 中的一種有序、不可變的序列類型。它在語(yǔ)法和使用方式上與列表(list)非常相似,但核心差異在于:一旦創(chuàng)建,元組的結(jié)構(gòu)不能被修改。

在實(shí)際開發(fā)中,元組常用于:

  • 表示固定含義的數(shù)據(jù)組合

  • 作為函數(shù)的多返回值

  • 作為字典的 key

  • 在某些場(chǎng)景下,替代列表以提升安全性和性能

1. 元組的基本概念

元組的核心特性

  • 有序(Ordered)元素按順序存儲(chǔ),可以通過(guò)索引訪問(wèn)

  • 不可變(Immutable)元組創(chuàng)建后,不能修改、添加、刪除元素

  • 可包含任意類型支持混合類型,支持嵌套結(jié)構(gòu)

point = (10, 20)
info = ("Alice", 18, True, ["Python", "Go"])

元素訪問(wèn)

print(point[0])   # 10
print(info[1])    # 18
print(info[-1])   # ['Python', 'Go']

元組 vs 列表(核心對(duì)比)

特性列表 list元組 tuple
是否可變可變不可變
是否有序
是否可作為 dict key
使用場(chǎng)景動(dòng)態(tài)數(shù)據(jù)固定數(shù)據(jù)
語(yǔ)法[ ]( )

2. 創(chuàng)建元組的多種方式

使用圓括號(hào)(最常見)
t = (1, 2, 3)
省略圓括號(hào)(語(yǔ)法層面支持)
t = 1, 2, 3

? 常用于函數(shù)返回多個(gè)值或簡(jiǎn)單賦值場(chǎng)景
? 不建議初學(xué)階段頻繁使用,容易降低可讀性

單元素元組(非常重要)
single = (5,)     # 正確
single2 = (5)     # 錯(cuò)誤,這是整數(shù)

?? 結(jié)論是否為元組,關(guān)鍵不在于括號(hào),而在于 逗號(hào)

使用tuple()構(gòu)造函數(shù)
nums = [1, 2, 3]
chars = "abc"

print(tuple(nums))   # (1, 2, 3)
print(tuple(chars))  # ('a', 'b', 'c')

3. 元組的索引、切片與遍歷

索引訪問(wèn)
t = (10, 20, 30, 40)

print(t[0])    # 10
print(t[-1])   # 40
切片操作
print(t[1:3])  # (20, 30)
print(t[:2])   # (10, 20)

注意

  • 切片返回的是 新元組

  • 原元組不會(huì)發(fā)生任何變化

遍歷元組
for item in t:
    print(item)

4. 元組的不可變性(核心理解)

不允許的操作
t = (1, 2, 3)

# t[0] = 10        # TypeError
# t.append(4)     # AttributeError
# del t[1]         # TypeError
元組中包含可變對(duì)象的情況(重點(diǎn))
t = (1, [2, 3])
t[1].append(4)

print(t)  # (1, [2, 3, 4])

如何理解?

  • 元組不可變:指的是
    ?? t[1] 這個(gè)“引用”不能被替換

  • 列表可變
    ?? 列表內(nèi)部的內(nèi)容仍然可以修改

?? 一句話總結(jié):

元組保證的是“結(jié)構(gòu)不變”,而不是“內(nèi)容絕對(duì)不變”

5. 元組解包(非常重要的能力)

基本解包
point = (10, 20)
x, y = point

print(x, y)  # 10 20
解包與函數(shù)返回值
def get_min_max(nums):
    return min(nums), max(nums)

min_val, max_val = get_min_max([3, 7, 1, 9])
print(min_val, max_val) # 1 9
使用*進(jìn)行擴(kuò)展解包
a, *b = (1, 2, 3, 4)
print(a)  # 1
print(b)  # [2, 3, 4]

6. 元組的常見應(yīng)用場(chǎng)景

作為字典的 key
location = {}
location[(10, 20)] = "Home"

print(location)

原因:

  • 字典 key 必須是 不可變類型

  • 列表不能作為 key,元組可以

函數(shù)返回多個(gè)值(Pythonic 寫法)
def user_info():
    return "Alice", 18, True

name, age, active = user_info()
表示“業(yè)務(wù)含義固定”的數(shù)據(jù)
HOST = "localhost"
PORT = 8080
CONFIG = (HOST, PORT)

?? 語(yǔ)義層面表達(dá):

“這組數(shù)據(jù)不應(yīng)該被修改”

7. 元組的常用方法與內(nèi)置函數(shù)

元組方法非常少,這是其設(shè)計(jì)的一部分:

t = (1, 2, 2, 3)

print(t.count(2))   # 2
print(t.index(3))   # 3

常配合使用的內(nèi)置函數(shù):

len(t)
max(t)
min(t)
sum(t)

8. 元組與列表的深入對(duì)比

維度列表元組
內(nèi)存占用較高較低
創(chuàng)建速度較慢較快
安全性易被修改更安全
可讀性偏數(shù)據(jù)容器偏結(jié)構(gòu)表達(dá)

小結(jié)一下吧

  • 元組是 不可變的有序序列

  • 與列表相似,但語(yǔ)義更偏向 “固定結(jié)構(gòu)”

  • 常見用途:

    • 函數(shù)多返回值

    • 字典 key

    • 不可修改的配置數(shù)據(jù)

  • 支持:

    • 索引、切片、遍歷

    • 解包(非常重要)

(六)總結(jié):如何選擇合適的數(shù)據(jù)結(jié)構(gòu)

? 至此,你已經(jīng)系統(tǒng)掌握 Python 的四大基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)::

  • 列表(list):有序、可變的序列

  • 字典(dict):鍵值映射

  • 集合(set):無(wú)序、不重復(fù)

  • 元組(tuple):不可變的序列

每種數(shù)據(jù)結(jié)構(gòu)都有自己的特點(diǎn)和適用場(chǎng)景,選擇合適的數(shù)據(jù)結(jié)構(gòu)能夠讓程序更高效、更易維護(hù)、更易理解

1. 數(shù)據(jù)結(jié)構(gòu)選擇對(duì)比表

數(shù)據(jù)結(jié)構(gòu)特性使用場(chǎng)景注意事項(xiàng)
列表 list有序,可變,可包含任意類型保存順序數(shù)據(jù),循環(huán)處理,多次增刪改遍歷修改時(shí)要小心;切片返回新列表
字典 dict鍵值映射,key 唯一,可變記錄型數(shù)據(jù)(用戶信息、配置、狀態(tài)映射),快速查找key 必須不可變;get 可提供默認(rèn)值
集合 set無(wú)序,不重復(fù),高效成員判斷去重、集合運(yùn)算、權(quán)限判斷、標(biāo)簽判斷無(wú)索引;遍歷順序不可控
元組 tuple有序,不可變,可包含任意類型固定數(shù)據(jù)、函數(shù)多值返回、字典 key內(nèi)部可變對(duì)象仍可修改;不可修改元素

2. 如何選擇數(shù)據(jù)結(jié)構(gòu)

選擇數(shù)據(jù)結(jié)構(gòu)可以按以下幾個(gè)維度:

1?? 是否需要順序
  • 是 → 列表或元組

  • 否 → 集合或字典

2?? 是否需要唯一性
  • 是 → 集合

  • 否 → 列表或元組

3?? 是否需要通過(guò)名字訪問(wèn)
  • 是 → 字典

  • 否 → 列表或集合

4?? 是否需要可變性
  • 可變 → 列表、字典、集合

  • 不可變 → 元組、不可變字典(擴(kuò)展應(yīng)用)

3. 常見組合場(chǎng)景

在實(shí)際開發(fā)中,這些數(shù)據(jù)結(jié)構(gòu)經(jīng)常組合使用:

場(chǎng)景數(shù)據(jù)結(jié)構(gòu)組合示例
多條記錄,每條記錄有多個(gè)字段列表 + 字典users = [{"name": "Alice", "age":18}, {"name": "Bob", "age":20}]
字典中某字段有多個(gè)值字典 + 列表grades = {"Alice":[90,95], "Bob":[80,82]}
去重的列表列表 + 集合unique_nums = list(set(nums))
函數(shù)返回多個(gè)值元組min_val, max_val = get_min_max([3,7,1,9])

4. 選用原則總結(jié)

  • 順序性優(yōu)先 → 列表/元組

  • 鍵值訪問(wèn)優(yōu)先 → 字典

  • 唯一性 / 集合運(yùn)算 → 集合

  • 數(shù)據(jù)固定不變 → 元組

  • 復(fù)雜嵌套 → 根據(jù)組合場(chǎng)景選擇最合適的容器

?? 核心思想:
數(shù)據(jù)結(jié)構(gòu)是工具,目的是高效組織和操作數(shù)據(jù)。
不要只記語(yǔ)法,要根據(jù)問(wèn)題特性選擇最合適的數(shù)據(jù)結(jié)構(gòu)。

七、結(jié)構(gòu)化數(shù)據(jù):Python 中的數(shù)據(jù)組織與處理

(一)為什么需要結(jié)構(gòu)化數(shù)據(jù)建模

在前面的章節(jié)中,我們已經(jīng)學(xué)習(xí)了 Python 提供的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu):列表(list)、字典(dict)、集合(set)和元組(tuple)
這些數(shù)據(jù)結(jié)構(gòu)在表達(dá)簡(jiǎn)單數(shù)據(jù)時(shí)非常高效,但當(dāng)我們開始處理真實(shí)世界中的業(yè)務(wù)數(shù)據(jù)時(shí),很快就會(huì)發(fā)現(xiàn):僅靠基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),往往難以支撐復(fù)雜數(shù)據(jù)的長(zhǎng)期演進(jìn)與工程化使用。

結(jié)構(gòu)化數(shù)據(jù)建模,正是為了解決這一問(wèn)題而出現(xiàn)的。

1. 現(xiàn)實(shí)世界數(shù)據(jù)的天然復(fù)雜性

現(xiàn)實(shí)中的數(shù)據(jù)幾乎從來(lái)不是“單值”的,而是具有以下典型特征:

  • 多字段(Multi-attribute)一個(gè)用戶不僅有名字,還包含年齡、郵箱、狀態(tài)、注冊(cè)時(shí)間等多個(gè)屬性;一個(gè)訂單不僅有金額,還包含商品列表、支付方式、物流信息等

  • 層級(jí)關(guān)系(Hierarchical)用戶包含地址信息;訂單包含多個(gè)商品;商品又包含規(guī)格、價(jià)格、庫(kù)存等子結(jié)構(gòu)

  • 實(shí)體之間存在關(guān)聯(lián)一對(duì)多:一個(gè)用戶對(duì)應(yīng)多個(gè)訂單;多對(duì)一:多個(gè)訂單屬于同一個(gè)商家;多對(duì)多:用戶與標(biāo)簽、商品與分類

  • 狀態(tài)與行為并存數(shù)據(jù)不僅是“靜態(tài)描述”,還會(huì)涉及狀態(tài)變化(如訂單狀態(tài)流轉(zhuǎn)),以及業(yè)務(wù)行為(如校驗(yàn)、計(jì)算、轉(zhuǎn)換)

這些特征決定了:現(xiàn)實(shí)世界的數(shù)據(jù),本質(zhì)上是結(jié)構(gòu)化、層級(jí)化、并且語(yǔ)義明確的。

2. 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)的能力邊界

Python 的 list 和 dict 是非常強(qiáng)大的工具,但它們的設(shè)計(jì)初衷是通用容器,而不是“領(lǐng)域模型”。

以字典為例:

  • 字典可以存任意鍵值對(duì)

  • 但它并不關(guān)心:

    • 這個(gè)字段是否必須存在

    • 這個(gè)字段應(yīng)該是什么類型

    • 不同字段之間是否存在約束關(guān)系

隨著業(yè)務(wù)復(fù)雜度的上升,單純使用 dict 會(huì)逐漸暴露出問(wèn)題:

  • 結(jié)構(gòu)不透明字段依賴“約定”而非“定義”,閱讀代碼時(shí)無(wú)法一眼看出數(shù)據(jù)結(jié)構(gòu)

  • 缺乏約束鍵名拼寫錯(cuò)誤只能在運(yùn)行時(shí)報(bào)錯(cuò),類型錯(cuò)誤難以及早發(fā)現(xiàn)

  • 可維護(hù)性下降字段增加或調(diào)整會(huì)波及大量代碼,缺乏統(tǒng)一的數(shù)據(jù)入口

  • 業(yè)務(wù)語(yǔ)義缺失data["status"] == 1 本身無(wú)法說(shuō)明業(yè)務(wù)含義,需要額外注釋或上下文才能理解

這意味著:基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)更適合“存數(shù)據(jù)”,但并不適合“表達(dá)數(shù)據(jù)含義”。

3. 從“數(shù)據(jù)容器”到“數(shù)據(jù)模型”的轉(zhuǎn)變

當(dāng)系統(tǒng)規(guī)模逐漸擴(kuò)大時(shí),我們需要的不再只是一個(gè)“能裝東西的容器”,而是一個(gè)明確表達(dá)業(yè)務(wù)含義的數(shù)據(jù)模型(Data Model)。

數(shù)據(jù)模型關(guān)注的不僅是“數(shù)據(jù)長(zhǎng)什么樣”,還包括:

  • 字段的業(yè)務(wù)語(yǔ)義

  • 字段之間的結(jié)構(gòu)關(guān)系

  • 數(shù)據(jù)的合法性規(guī)則

  • 數(shù)據(jù)可支持的操作與行為

這種轉(zhuǎn)變,本質(zhì)上是:從“如何存數(shù)據(jù)”,升級(jí)為“如何描述現(xiàn)實(shí)世界中的對(duì)象”。

4. Python 在結(jié)構(gòu)化數(shù)據(jù)建模上的天然優(yōu)勢(shì)

Python 之所以適合結(jié)構(gòu)化數(shù)據(jù)建模,主要得益于以下能力:

  • 靈活的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)(list / dict)

  • 完整的面向?qū)ο篌w系(Class)

  • 強(qiáng)大的類型注解支持

  • 內(nèi)建 JSON 處理能力

  • dataclass 等高級(jí)建模工具

這些能力,使得 Python 可以自然地完成從:原始數(shù)據(jù) → 半結(jié)構(gòu)化數(shù)據(jù) → 領(lǐng)域模型 → 工程化數(shù)據(jù)體系的逐層演進(jìn)。

小結(jié)一下吧

  • 現(xiàn)實(shí)世界的數(shù)據(jù)天然是結(jié)構(gòu)化的

  • 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)適合存儲(chǔ),但不適合長(zhǎng)期建模

  • 結(jié)構(gòu)化數(shù)據(jù)建模是代碼工程化的必經(jīng)之路

  • Python 提供了從簡(jiǎn)單到復(fù)雜的完整建模能力

在接下來(lái)的學(xué)習(xí)中,我們將從嵌套數(shù)據(jù)結(jié)構(gòu)開始,逐步引入 JSON 處理,最終過(guò)渡到 基于 Class 的結(jié)構(gòu)化數(shù)據(jù)建模,構(gòu)建可維護(hù)、可擴(kuò)展的 Python 數(shù)據(jù)體系。

(二)Python 中的嵌套結(jié)構(gòu)化數(shù)據(jù)

在明確了為什么需要結(jié)構(gòu)化數(shù)據(jù)建模之后,我們首先要面對(duì)的是:如何在 Python 中表達(dá)“多字段 + 多層級(jí)”的數(shù)據(jù)結(jié)構(gòu)。

在不引入面向?qū)ο笾?,Python 最直接、最常見的做法,就是使用嵌套的數(shù)據(jù)結(jié)構(gòu)——即在 list 或 dict 中再包含 list 或 dict。

嵌套結(jié)構(gòu),是 Python 邁向結(jié)構(gòu)化數(shù)據(jù)處理的第一步。

1. 嵌套結(jié)構(gòu)化數(shù)據(jù)的基本思想

所謂嵌套結(jié)構(gòu),本質(zhì)上是:用 dict 表達(dá)“對(duì)象”,用 list 表達(dá)“集合”,并通過(guò)層級(jí)組合還原現(xiàn)實(shí)關(guān)系。

這種思想非常直觀,也幾乎不需要額外語(yǔ)法成本,因此被廣泛用于:

  • 接口返回?cái)?shù)據(jù)

  • 配置文件

  • 臨時(shí)數(shù)據(jù)組織

  • JSON 原始載體

2. 字典嵌套字典:表達(dá)對(duì)象的層級(jí)屬性

適用場(chǎng)景:一個(gè)對(duì)象內(nèi)部存在子結(jié)構(gòu)

user = {
    "id": 1001,
    "name": "Alice",
    "profile": {
        "age": 28,
        "email": "alice@example.com",
        "address": {
            "city": "Beijing",
            "zipcode": "100000"
        }
    }
}

結(jié)構(gòu)理解

  • user:整體對(duì)象

  • profile:用戶的擴(kuò)展屬性

  • address:更細(xì)粒度的子結(jié)構(gòu)

這種結(jié)構(gòu)清晰地反映了現(xiàn)實(shí)語(yǔ)義:地址不屬于用戶本身,而屬于用戶的資料信息。

訪問(wèn)方式

city = user["profile"]["address"]["city"]

此時(shí)你已經(jīng)可以感受到第一個(gè)問(wèn)題:

  • 訪問(wèn)路徑依賴結(jié)構(gòu)穩(wěn)定

  • 任意一層缺失,都會(huì)導(dǎo)致運(yùn)行期錯(cuò)誤

3. 字典嵌套列表:表達(dá)一對(duì)多關(guān)系

適用場(chǎng)景:一個(gè)主體擁有多個(gè)子對(duì)象

order = {
    "order_id": "ORD-001",
    "user_id": 1001,
    "items": [
        {"sku": "SKU-1", "price": 100, "quantity": 2},
        {"sku": "SKU-2", "price": 50, "quantity": 1}
    ]
}

結(jié)構(gòu)理解

  • order 是訂單對(duì)象

  • items 是訂單下的商品集合

  • 每個(gè)商品仍然是一個(gè)“對(duì)象”

典型處理邏輯

total_amount = 0
for item in order["items"]:
    total_amount += item["price"] * item["quantity"]

此時(shí)一個(gè)非常關(guān)鍵的變化已經(jīng)出現(xiàn):業(yè)務(wù)計(jì)算邏輯,開始直接寫在“嵌套結(jié)構(gòu)遍歷”之中

這是后續(xù)引入 Class 建模的重要?jiǎng)訖C(jī)。

4. 列表嵌套字典:同構(gòu)對(duì)象的集合

適用場(chǎng)景:多個(gè)結(jié)構(gòu)相同的對(duì)象

users = [
    {"id": 1, "name": "Alice", "active": True},
    {"id": 2, "name": "Bob", "active": False},
    {"id": 3, "name": "Charlie", "active": True}
]

遍歷與篩選

active_users = []
for user in users:
    if user["active"]:
        active_users.append(user)

這種結(jié)構(gòu)在接口返回?cái)?shù)據(jù)中極為常見,但它也暴露了嵌套結(jié)構(gòu)的本質(zhì)問(wèn)題之一:

  • 字段完全依賴字符串約定

  • 沒(méi)有任何顯式結(jié)構(gòu)定義

  • 錯(cuò)誤只能在運(yùn)行期發(fā)現(xiàn)

5. 多層混合嵌套:真實(shí)系統(tǒng)中的常態(tài)

在真實(shí)系統(tǒng)中,嵌套結(jié)構(gòu)往往是多種形式的組合:

response = {
    "code": 0,
    "data": {
        "user": {
            "id": 1001,
            "orders": [
                {
                    "order_id": "ORD-001",
                    "items": [
                        {"sku": "SKU-1", "price": 100}
                    ]
                }
            ]
        }
    }
}

訪問(wèn)路徑示例

sku = response["data"]["user"]["orders"][0]["items"][0]["sku"]

此類代碼的特征非常明顯:

  • 訪問(wèn)鏈路極長(zhǎng)

  • 強(qiáng)依賴數(shù)據(jù)結(jié)構(gòu)細(xì)節(jié)

  • 可讀性和可維護(hù)性迅速下降

6. 防御式訪問(wèn):必要但有限的改進(jìn)

為了避免異常,開發(fā)中常使用防御式寫法:

user = response.get("data", {}).get("user", {})
orders = user.get("orders", [])

if orders:
    first_order = orders[0]

這種方式可以:

  • 降低運(yùn)行期錯(cuò)誤概率

  • 提高代碼健壯性

但需要清醒認(rèn)識(shí)到:防御式訪問(wèn)解決的是“不崩潰”,而不是“結(jié)構(gòu)合理”。

7. 嵌套結(jié)構(gòu)的工程性問(wèn)題總結(jié)

通過(guò)以上示例,可以清晰看到嵌套結(jié)構(gòu)在工程中的局限:

  • 結(jié)構(gòu)定義分散:數(shù)據(jù)結(jié)構(gòu)存在于代碼路徑中,而非集中定義

  • 業(yè)務(wù)語(yǔ)義缺失:字段只是字符串,無(wú)法承載規(guī)則和含義

  • 強(qiáng)耦合:結(jié)構(gòu)變更會(huì)影響大量訪問(wèn)代碼

  • 邏輯與數(shù)據(jù)混雜:業(yè)務(wù)計(jì)算被迫寫在遍歷和索引中

當(dāng)代碼中大量出現(xiàn)如下形式時(shí):

data["a"]["b"][0]["c"]["d"]

通常意味著:嵌套結(jié)構(gòu)已經(jīng)達(dá)到了可維護(hù)性的上限

8. 嵌套結(jié)構(gòu)在整體體系中的正確定位

嵌套 dict / list 并不是“錯(cuò)誤做法”,而是階段性工具

使用場(chǎng)景評(píng)價(jià)
原始 JSON 承載合適
臨時(shí)數(shù)據(jù)處理合適
腳本 / Demo合適
核心業(yè)務(wù)模型不合適
長(zhǎng)期維護(hù)系統(tǒng)不合適

它更適合作為:數(shù)據(jù)的“中間形態(tài)”,而非最終模型。

小結(jié)一下吧

  • 嵌套結(jié)構(gòu)是 Python 表達(dá)復(fù)雜數(shù)據(jù)的基礎(chǔ)方式

  • 它通過(guò) dict + list 組合還原現(xiàn)實(shí)關(guān)系

  • 隨著層級(jí)加深,維護(hù)成本迅速上升

  • 這正是引入 JSON 規(guī)范與 Class 建模的直接動(dòng)因

接著我們將進(jìn)入 半結(jié)構(gòu)化數(shù)據(jù):JSON 在 Python 中的處理,你會(huì)發(fā)現(xiàn):JSON 的便利性,并沒(méi)有從根本上解決嵌套結(jié)構(gòu)的問(wèn)題,而只是讓它“標(biāo)準(zhǔn)化”了。

(三)半結(jié)構(gòu)化數(shù)據(jù):JSON 在 Python 中的處理

在上一節(jié)中,我們已經(jīng)看到:通過(guò) list 與 dict 的嵌套,Python 可以完整表達(dá)復(fù)雜數(shù)據(jù)結(jié)構(gòu),但可維護(hù)性迅速下降。

在真實(shí)工程中,這類嵌套結(jié)構(gòu)往往并不是“手寫”的,而是來(lái)自:

  • HTTP 接口返回

  • 配置文件

  • 消息隊(duì)列

  • 日志或存儲(chǔ)系統(tǒng)

這些數(shù)據(jù)最常見的載體形式,就是 JSON(JavaScript Object Notation)。

1. 什么是半結(jié)構(gòu)化數(shù)據(jù)

從數(shù)據(jù)組織角度看,數(shù)據(jù)大致可以分為三類:

  • 非結(jié)構(gòu)化數(shù)據(jù):文本、圖片、音頻

  • 結(jié)構(gòu)化數(shù)據(jù):表結(jié)構(gòu)、強(qiáng)約束模型

  • 半結(jié)構(gòu)化數(shù)據(jù):結(jié)構(gòu)存在,但約束較弱

JSON 正是典型的半結(jié)構(gòu)化數(shù)據(jù)格式,其特點(diǎn)是:

  • 結(jié)構(gòu)清晰(層級(jí)、鍵值)

  • 可嵌套

  • 無(wú)強(qiáng)類型約束

  • 字段可選、可變

這使得 JSON 非常適合數(shù)據(jù)交換,但不適合直接作為業(yè)務(wù)模型。

2. JSON 的數(shù)據(jù)模型與 Python 的映射關(guān)系

JSON 本身支持的數(shù)據(jù)類型非常有限:

JSON 類型Python 對(duì)應(yīng)類型
objectdict
arraylist
stringstr
numberint / float
booleanbool
nullNone

也正因如此,JSON 在 Python 中的本質(zhì)就是:嵌套的 dict 與 list

換句話說(shuō):JSON 并沒(méi)有解決嵌套結(jié)構(gòu)的問(wèn)題,只是把它“標(biāo)準(zhǔn)化”了。

3. Python 中的 JSON 解析(反序列化)

Python 內(nèi)置 json 模塊,用于 JSON 與 Python 對(duì)象之間的轉(zhuǎn)換。

import json

json_str = '''
{
    "id": 1001,
    "name": "Alice",
    "active": true,
    "roles": ["admin", "editor"]
}
'''

data = json.loads(json_str)

解析后:

  • data 是一個(gè) dict

  • 所有字段完全不受約束

  • 訪問(wèn)方式與普通嵌套結(jié)構(gòu)一致

name = data["name"]
roles = data["roles"]

4. 從文件加載 JSON 數(shù)據(jù)

JSON 文件是配置與數(shù)據(jù)交換的常見形式(這里暫時(shí)先理解,后續(xù)這部分會(huì)在新博客單獨(dú)講解):

import json

with open("config.json", "r", encoding="utf-8") as f:
    config = json.load(f)

此時(shí)你獲得的是:

  • 一個(gè)完全動(dòng)態(tài)的嵌套結(jié)構(gòu)

  • 所有字段都只能“運(yùn)行期驗(yàn)證”

5. JSON 的典型嵌套結(jié)構(gòu)示例

考慮一個(gè)真實(shí)接口返回示例:

response = {
    "code": 0,
    "message": "success",
    "data": {
        "user": {
            "id": 1001,
            "name": "Alice",
            "orders": [
                {
                    "order_id": "ORD-001",
                    "items": [
                        {"sku": "SKU-1", "price": 100, "quantity": 2}
                    ]
                }
            ]
        }
    }
}

業(yè)務(wù)代碼往往會(huì)這樣寫:

orders = response["data"]["user"]["orders"]
first_item_price = orders[0]["items"][0]["price"]

到這里,你應(yīng)該已經(jīng)非常熟悉這種訪問(wèn)模式——它與嵌套結(jié)構(gòu)沒(méi)有任何本質(zhì)區(qū)別。

6. JSON 帶來(lái)的“結(jié)構(gòu)假象”

JSON 的一個(gè)常見誤區(qū)是:“有格式 ≠ 有模型”

雖然 JSON 看起來(lái)“結(jié)構(gòu)清晰”,但它存在以下天然問(wèn)題:

  • 字段完全不受約束缺字段不會(huì)報(bào)錯(cuò),多字段也不會(huì)報(bào)錯(cuò)

  • 類型不可靠price 可能是數(shù)字,也可能是字符串,錯(cuò)誤只能在運(yùn)行期暴露

  • 業(yè)務(wù)語(yǔ)義缺失status = 1 的含義無(wú)法自解釋,需要依賴外部文檔或注釋

  • 結(jié)構(gòu)變更極具破壞性任意字段調(diào)整都會(huì)影響訪問(wèn)鏈

JSON 解決的是“數(shù)據(jù)如何傳輸”,而不是“數(shù)據(jù)如何使用。

7. 防御式 JSON 解析的常見寫法

為了避免運(yùn)行期異常,代碼中常見如下寫法:

data = response.get("data", {})
user = data.get("user", {})
orders = user.get("orders", [])

if orders:
    order_id = orders[0].get("order_id")

這種寫法與上面講的嵌套方式依舊沒(méi)啥區(qū)別,更重要的是:仍然沒(méi)有一個(gè)“明確的數(shù)據(jù)模型”

8. JSON 在工程體系中的正確角色

在成熟系統(tǒng)中,JSON 的定位應(yīng)當(dāng)非常明確:

角色是否合適
網(wǎng)絡(luò)傳輸格式非常合適
配置文件合適
接口輸入 / 輸出合適
業(yè)務(wù)內(nèi)部模型不合適
核心領(lǐng)域?qū)ο?/span>不合適

JSON 更適合作為:系統(tǒng)邊界上的數(shù)據(jù)格式,而非系統(tǒng)內(nèi)部的結(jié)構(gòu)表達(dá)。

系統(tǒng)引入結(jié)構(gòu)化建模的階段,Python 給出的答案是:

  • Class

  • dataclass

  • 明確的數(shù)據(jù)模型定義

  • JSON ↔ Model 的轉(zhuǎn)換邊界

小結(jié)一下吧

  • JSON 是典型的半結(jié)構(gòu)化數(shù)據(jù)格式

  • 在 Python 中,JSON 本質(zhì)仍是嵌套 dict / list

  • JSON 適合傳輸,不適合直接承載業(yè)務(wù)模型

  • 防御式解析無(wú)法從根本上解決結(jié)構(gòu)問(wèn)題

  • 這直接引出了:為什么必須使用 Class 進(jìn)行結(jié)構(gòu)化建模

(四)面向?qū)ο蟮慕Y(jié)構(gòu)化建模:Class 的引入

在前面的講解中無(wú)論哪一步,數(shù)據(jù)始終以同一種形態(tài)存在:dict,只是內(nèi)容變“干凈”了而已。

接下來(lái)將通過(guò)一組連續(xù)示例說(shuō)明:為什么必須引入 Class,以及 Class 在工程中應(yīng)該如何使用。

1. 問(wèn)題起點(diǎn):業(yè)務(wù)邏輯正在“侵蝕”數(shù)據(jù)結(jié)構(gòu)

先看一個(gè)非常真實(shí)的場(chǎng)景,接口返回訂單數(shù)據(jù):

order_data = {
    "order_id": "ORD-001",
    "price": "100",
    "quantity": 2
}

業(yè)務(wù)中需要計(jì)算訂單金額,代碼往往這樣寫:

total_amount = int(order_data["price"]) * order_data["quantity"]

這段代碼沒(méi)有語(yǔ)法問(wèn)題,但存在嚴(yán)重的工程隱患

  • 類型轉(zhuǎn)換是“臨時(shí)的”

  • 規(guī)則是“隱含的”

  • 任意地方都可以重復(fù)這段邏輯

此時(shí)系統(tǒng)出現(xiàn)了第一個(gè)危險(xiǎn)信號(hào):業(yè)務(wù)規(guī)則開始散落在 dict 操作中。

2. 第一次建模:用 Class 固定結(jié)構(gòu)與類型

我們引入最基礎(chǔ)的 Class,僅做一件事:把“字段定義”和“類型規(guī)則”集中到一個(gè)地方

class Order:
    def __init__(self, order_id, price, quantity):
        self.order_id = order_id
        self.price = int(price)
        self.quantity = int(quantity)

此時(shí)發(fā)生了三件非常重要的變化:

  • 結(jié)構(gòu)集中Order 明確有哪些字段

  • 類型前置類型轉(zhuǎn)換只發(fā)生一次

  • 使用成本下降后續(xù)代碼不再關(guān)心字段細(xì)節(jié)

業(yè)務(wù)代碼變?yōu)椋?/p>

order = Order("ORD-001", "100", 2)

3. 第二次建模:讓業(yè)務(wù)行為回歸模型

現(xiàn)在再看金額計(jì)算邏輯。如果繼續(xù)寫在外部:

total = order.price * order.quantity

雖然比 dict 好,但語(yǔ)義仍然分散。正確的工程做法是:只要邏輯“屬于對(duì)象”,就應(yīng)進(jìn)入對(duì)象本身

class Order:
    def __init__(self, order_id, price, quantity):
        self.order_id = order_id
        self.price = int(price)
        self.quantity = int(quantity)

    def total_amount(self):
        return self.price * self.quantity

此時(shí):

  • 金額計(jì)算的業(yè)務(wù)含義被明確命名

  • 外部代碼無(wú)需關(guān)心實(shí)現(xiàn)細(xì)節(jié)

total = order.total_amount()

4. 工程規(guī)范一:Class 不是“數(shù)據(jù)殼”,而是“業(yè)務(wù)單元”

到這里,可以明確一個(gè)重要規(guī)范

一個(gè) Class 不應(yīng)該只是 dict 的替代品,而應(yīng)該是一個(gè)“可用對(duì)象”。

如果一個(gè) Class:

  • 只有屬性

  • 沒(méi)有任何方法

那它的價(jià)值是非常有限的。

5. 第三次建模:讓 Class 成為解析與清洗的邊界

回到真實(shí)輸入數(shù)據(jù)的問(wèn)題。接口返回的往往是 不可信 JSON

raw_data = {
    "order_id": "ORD-001",
    "price": None,
    "quantity": "2"
}

工程上正確的做法是:讓 Class 成為“不可信數(shù)據(jù) → 可信對(duì)象”的邊界

class Order:
    def __init__(self, data: dict):
        self.order_id = data.get("order_id")
        self.price = self._to_int(data.get("price"), default=0)
        self.quantity = self._to_int(data.get("quantity"), default=1)

    def _to_int(self, value, default=0):
        try:
            return int(value)
        except (TypeError, ValueError):
            return default

此時(shí):

  • 所有防御邏輯被“封裝”

  • 外部世界不再處理臟數(shù)據(jù)

  • 構(gòu)造完成的對(duì)象即“可用對(duì)象”

6. 工程規(guī)范二:業(yè)務(wù)代碼只接觸“可信對(duì)象”

正確的調(diào)用方式應(yīng)當(dāng)是:

order = Order(raw_data)
total = order.total_amount()

而不是:

# ? 不推薦
total = int(raw_data["price"]) * int(raw_data["quantity"])

規(guī)范總結(jié):

解析、清洗、校驗(yàn),必須發(fā)生在模型內(nèi)部
業(yè)務(wù)代碼不應(yīng)再做任何字段判斷

7. 第四次建模:用對(duì)象組合替代嵌套結(jié)構(gòu)

考慮一個(gè)更真實(shí)的訂單結(jié)構(gòu):

raw_order = {
    "order_id": "ORD-001",
    "items": [
        {"sku": "SKU-1", "price": "100"},
        {"sku": "SKU-2", "price": "50"}
    ]
}

如果繼續(xù)使用嵌套 dict:

total = 0
for item in raw_order["items"]:
    total += int(item["price"])

正確的建模方式是:用對(duì)象組合替代嵌套結(jié)構(gòu)

class OrderItem:
    def __init__(self, data):
        self.sku = data.get("sku")
        self.price = int(data.get("price", 0))

class Order:
    def __init__(self, data):
        self.order_id = data.get("order_id")
        self.items = [OrderItem(item) for item in data.get("items", [])]

    def total_amount(self):
        return sum(item.price for item in self.items)

此時(shí),結(jié)構(gòu)發(fā)生了質(zhì)變:

  • 嵌套 dict → 對(duì)象關(guān)系

  • 遍歷邏輯 → 模型內(nèi)部能力

8. 工程規(guī)范三:嵌套數(shù)據(jù) ≠ 嵌套 dict,而是“對(duì)象層級(jí)”

這是結(jié)構(gòu)化建模中非常重要的一條規(guī)范

嵌套關(guān)系應(yīng)通過(guò)“對(duì)象組合”表達(dá),而不是嵌套 dict 訪問(wèn)路徑。

一旦遵循這條規(guī)范:

  • 訪問(wèn)路徑顯著變短

  • 代碼可讀性成倍提升

  • 結(jié)構(gòu)演進(jìn)成本大幅下降

小結(jié)一下吧

通過(guò)示例可以總結(jié)出 Class 建模的核心工程規(guī)范:

  • Class 是模型,不是數(shù)據(jù)殼

  • 結(jié)構(gòu)、語(yǔ)義、行為必須統(tǒng)一

  • 解析與清洗是模型的職責(zé)

  • 業(yè)務(wù)代碼只操作可信對(duì)象

  • 嵌套關(guān)系用對(duì)象組合表達(dá)

到這里,你已經(jīng)完成了:

從“操作數(shù)據(jù)” → “使用模型” 的關(guān)鍵轉(zhuǎn)變

(五)復(fù)雜對(duì)象組合與領(lǐng)域建模

在真實(shí)系統(tǒng)中,所謂“復(fù)雜數(shù)據(jù)”,并不僅僅是 層級(jí)多,而是同時(shí)具備:

  • 多層嵌套結(jié)構(gòu)

  • 不同子結(jié)構(gòu)承擔(dān)不同職責(zé)

  • 局部規(guī)則 + 全局規(guī)則并存

  • 數(shù)據(jù)來(lái)自不可信邊界(接口 / MQ / DB)

這一節(jié),我們用一個(gè) 接近真實(shí)電商/交易系統(tǒng)的數(shù)據(jù)模型,完整展示 Python 中的復(fù)雜領(lǐng)域建模方式

1. 原始輸入:近真實(shí)系統(tǒng)級(jí) JSON 結(jié)構(gòu)

這是一個(gè) 近真實(shí)工程中常見復(fù)雜度 的訂單數(shù)據(jù)(已適度抽象):

raw_order = {
    "order_id": "ORD-9001",
    "user": {
        "id": "U-1001",
        "profile": {
            "name": "Alice",
            "level": "VIP"
        }
    },
    "items": [
        {
            "sku": "SKU-1",
            "pricing": {
                "unit_price": "100",
                "currency": "CNY"
            },
            "quantity": 2,
            "discounts": [
                {"type": "PROMOTION", "amount": "10"},
                {"type": "VIP", "amount": "5"}
            ]
        }
    ],
    "payment": {
        "method": "CREDIT_CARD",
        "transactions": [
            {"tx_id": "TX-1", "amount": "185"},
            {"tx_id": "TX-2", "amount": "10"}
        ]
    }
}

特點(diǎn):

  • 最深層級(jí):5 層

  • 同時(shí)包含:列表嵌套 + 對(duì)象嵌套

  • 金額、規(guī)則、行為全部混在 JSON 中

如果直接用 dict 操作,這類代碼幾乎不可維護(hù)。

2. 第一步:識(shí)別領(lǐng)域與聚合邊界(不是拆字段)

復(fù)雜建模的第一步不是寫類,而是劃分領(lǐng)域?qū)ο?/strong>。

從業(yè)務(wù)語(yǔ)義出發(fā):

JSON 片段領(lǐng)域?qū)ο?/th>
orderOrder(聚合根)
userUser
profileUserProfile
itemsOrderItem
pricingPricing
discountsDiscount
paymentPayment
transactionsPaymentTransaction

原則:

只要一個(gè)子結(jié)構(gòu)有“獨(dú)立業(yè)務(wù)含義”,就值得一個(gè) Class。

3. 底層值對(duì)象(Value Object)建模

Discount(最小業(yè)務(wù)單元)

class Discount:
    def __init__(self, data):
        self.type = data.get("type")
        self.amount = int(data.get("amount", 0))

Pricing(價(jià)格不是一個(gè)字段,而是一組規(guī)則)

class Pricing:
    def __init__(self, data):
        self.unit_price = int(data.get("unit_price", 0))
        self.currency = data.get("currency")

    def total(self, quantity):
        return self.unit_price * quantity

4. OrderItem:多層對(duì)象的“局部聚合”

class OrderItem:
    def __init__(self, data):
        self.sku = data.get("sku")
        self.quantity = int(data.get("quantity", 1))

        self.pricing = Pricing(data.get("pricing", {}))
        self.discounts = [
            Discount(d) for d in data.get("discounts", [])
        ]

    def discount_amount(self):
        return sum(d.amount for d in self.discounts)

    def subtotal(self):
        return self.pricing.total(self.quantity) - self.discount_amount()

注意這里已經(jīng)出現(xiàn)了領(lǐng)域行為協(xié)同

  • 折扣規(guī)則不在 Order

  • 價(jià)格規(guī)則不在 Order

  • OrderItem 自洽完成金額計(jì)算

5. 用戶領(lǐng)域:嵌套對(duì)象中的語(yǔ)義建模

class UserProfile:
    def __init__(self, data):
        self.name = data.get("name")
        self.level = data.get("level")

    def is_vip(self):
        return self.level == "VIP"


class User:
    def __init__(self, data):
        self.user_id = data.get("id")
        self.profile = UserProfile(data.get("profile", {}))

6. 支付領(lǐng)域:獨(dú)立聚合,不混入訂單邏輯

class PaymentTransaction:
    def __init__(self, data):
        self.tx_id = data.get("tx_id")
        self.amount = int(data.get("amount", 0))

class Payment:
    def __init__(self, data):
        self.method = data.get("method")
        self.transactions = [
            PaymentTransaction(tx)
            for tx in data.get("transactions", [])
        ]

    def paid_amount(self):
        return sum(tx.amount for tx in self.transactions)

7. Order:真正的“領(lǐng)域聚合根”

class Order:
    def __init__(self, data):
        self.order_id = data.get("order_id")

        self.user = User(data.get("user", {}))
        self.items = [OrderItem(i) for i in data.get("items", [])]
        self.payment = Payment(data.get("payment", {}))

    def order_amount(self):
        return sum(item.subtotal() for item in self.items)

    def is_fully_paid(self):
        return self.payment.paid_amount() >= self.order_amount()

注意:

  • Order 不參與任何底層計(jì)算

  • Order 只做“聚合協(xié)調(diào)”

  • 各領(lǐng)域職責(zé)清晰、不交叉

8. 工程級(jí)規(guī)范總結(jié)(復(fù)雜場(chǎng)景)

這一示例隱含了一套非常重要的工程規(guī)范

規(guī)范一:不要讓聚合根“變胖”
  • 金額計(jì)算下沉到 OrderItem

  • 折扣規(guī)則不寫在 Order

規(guī)范二:多層嵌套 ≠ 多層 dict
  • 每一層都是對(duì)象

  • 每一層都有行為

規(guī)范三:領(lǐng)域隔離
  • Payment 不知道 OrderItem 的存在

  • Order 不知道 Discount 的細(xì)節(jié)

規(guī)范四:結(jié)構(gòu)變化可控
  • JSON 結(jié)構(gòu)變化只影響局部 Class

這一節(jié)完成的不是“示例升級(jí)”,而是復(fù)雜度躍遷

  • 從 2 層嵌套 → 5 層嵌套

  • 從數(shù)據(jù)組合 → 領(lǐng)域協(xié)作

  • 從“能跑” → “可演進(jìn)、可維護(hù)”

你現(xiàn)在已經(jīng)具備:用 Python Class 構(gòu)建真實(shí)業(yè)務(wù)領(lǐng)域模型的能力

(六)JSON ↔ Class 的雙向轉(zhuǎn)換:邊界層與 DTO 設(shè)計(jì)

在 (五) 中,我們已經(jīng)構(gòu)建了一套復(fù)雜、內(nèi)聚、可演進(jìn)的領(lǐng)域模型。但此時(shí)如果直接將這些 Class 用在接口層或存儲(chǔ)層,會(huì)立即遇到新的問(wèn)題:

  • 接口層需要 JSON

  • MQ / RPC 需要可序列化結(jié)構(gòu)

  • 數(shù)據(jù)庫(kù)存儲(chǔ)結(jié)構(gòu)與領(lǐng)域模型不一致

  • 外部系統(tǒng)字段經(jīng)常變動(dòng)

這引出了一個(gè)非常重要的工程問(wèn)題領(lǐng)域模型不應(yīng)直接暴露在系統(tǒng)邊界。

1. 為什么不能讓領(lǐng)域模型“裸奔”到邊界

一個(gè)常見但危險(xiǎn)的做法是:

json.dumps(order.__dict__)

這種方式存在嚴(yán)重問(wèn)題:

  • 結(jié)構(gòu)不可控:私有字段、內(nèi)部狀態(tài)一并暴露

  • 語(yǔ)義污染:內(nèi)部對(duì)象結(jié)構(gòu)被外部依賴

  • 變更風(fēng)險(xiǎn)極高:內(nèi)部模型調(diào)整會(huì)破壞接口

  • 無(wú)法做版本治理:接口字段無(wú)法演進(jìn)

工程結(jié)論:領(lǐng)域模型 ≠ 接口數(shù)據(jù)模型

2. 邊界層的核心職責(zé)

在工程上,通常需要一個(gè)邊界層(Boundary Layer),它負(fù)責(zé):

  • JSON → DTO

  • DTO → Domain Model

  • Domain Model → DTO

  • DTO → JSON

其中,DTO(Data Transfer Object) 是核心中介。

3. DTO 的設(shè)計(jì)原則(非常重要)

DTO 與領(lǐng)域模型的關(guān)系,應(yīng)遵循以下原則:

  • 只包含數(shù)據(jù),不包含業(yè)務(wù)行為

  • 結(jié)構(gòu)扁平,面向接口需求

  • 允許字段冗余或命名不一致

  • 變化頻率遠(yuǎn)高于領(lǐng)域模型

  • 邊界轉(zhuǎn)換集中化

    一個(gè)成熟系統(tǒng)中,應(yīng)當(dāng)遵循:

    所有 JSON ↔ Domain 的轉(zhuǎn)換,都集中在邊界層完成

    而不是:Controller 中拼 dict; Service 中解析字段; Model 中關(guān)心接口格式

3.1 示例:為 Order 定義輸入 DTO

接口輸入 JSON:

{
  "order_id": "ORD-9001",
  "user_id": "U-1001",
  "items": [
    {
      "sku": "SKU-1",
      "unit_price": "100",
      "quantity": 2
    }
  ]
}

對(duì)應(yīng) DTO:

class OrderCreateDTO:
    def __init__(self, data):
        self.order_id = data.get("order_id")
        self.user_id = data.get("user_id")
        self.items = data.get("items", [])

DTO 的特點(diǎn):

  • 不做復(fù)雜解析

  • 不包含嵌套對(duì)象建模

  • 只服務(wù)接口需求

3.2 DTO → Domain Model(反序列化邊界)

將 DTO 轉(zhuǎn)換為領(lǐng)域模型,是邊界層的核心工作之一。

class OrderFactory:
    @staticmethod
    def from_create_dto(dto: OrderCreateDTO):
        raw = {
            "order_id": dto.order_id,
            "user": {"id": dto.user_id},
            "items": [
                {
                    "sku": item["sku"],
                    "pricing": {"unit_price": item["unit_price"]},
                    "quantity": item["quantity"],
                    "discounts": []
                }
                for item in dto.items
            ]
        }
        return Order(raw)

注意幾點(diǎn):

  • DTO 不知道領(lǐng)域模型

  • 領(lǐng)域模型不依賴 DTO

  • 轉(zhuǎn)換邏輯集中在 Factory / Assembler 中

3.3 Domain Model → DTO(序列化邊界)

對(duì)外輸出時(shí),同樣不能直接暴露領(lǐng)域模型。

class OrderResponseDTO:
    def __init__(self, order: Order):
        self.order_id = order.order_id
        self.total_amount = order.order_amount()
        self.paid = order.is_fully_paid()

再由 DTO 轉(zhuǎn)為 JSON:

response = json.dumps(order_response_dto.__dict__)

3.4. 復(fù)雜結(jié)構(gòu)下的 DTO 拆分策略

當(dāng)結(jié)構(gòu)進(jìn)一步復(fù)雜時(shí),應(yīng)避免:

class BigDTO:
    ...

而采用:

  • OrderDTO

  • ItemDTO

  • PaymentDTO

再由 Assembler 負(fù)責(zé)組合。

3.5 防腐層(Anti-Corruption Layer)視角

在對(duì)接外部系統(tǒng)時(shí),DTO 還承擔(dān)著一個(gè)更重要的角色:

防止外部模型“污染”內(nèi)部領(lǐng)域模型

字段改名、結(jié)構(gòu)變更、類型異常,都被限制在 DTO 層。

小結(jié)一下吧

通過(guò)本節(jié),你應(yīng)該建立起以下清晰認(rèn)知:

  • 領(lǐng)域模型只服務(wù)領(lǐng)域邏輯

  • DTO 是系統(tǒng)邊界的語(yǔ)言

  • JSON 永遠(yuǎn)不應(yīng)直接進(jìn)入領(lǐng)域模型

  • Factory / Assembler 是關(guān)鍵角色

  • 邊界清晰,系統(tǒng)才能長(zhǎng)期演進(jìn)

(七)使用 dataclass 與類型系統(tǒng)增強(qiáng)結(jié)構(gòu)化建模

在前面的分享中,我們已經(jīng)用“原生 Class”完成了復(fù)雜領(lǐng)域建模。但你可能已經(jīng)感受到幾個(gè)現(xiàn)實(shí)問(wèn)題:

  • __init__ 代碼大量重復(fù)

  • 字段類型只能靠約定

  • 對(duì)象結(jié)構(gòu)難以一眼看清

  • 重構(gòu)時(shí)缺乏工具輔助

這正是 dataclass 與類型系統(tǒng) 登場(chǎng)的時(shí)機(jī)。

1. 為什么在復(fù)雜建模階段引入 dataclass

dataclass 并不是“語(yǔ)法糖”,而是結(jié)構(gòu)化建模的工程工具。

它解決的核心問(wèn)題是:

問(wèn)題原生 Classdataclass
字段聲明分散在 __init__集中聲明
類型表達(dá)隱式顯式
可讀性中等
維護(hù)成本

工程結(jié)論:當(dāng)模型成為系統(tǒng)核心資產(chǎn)時(shí),必須使用 dataclass 或等價(jià)機(jī)制。

2. 從原生 Class 到 dataclass:逐步演進(jìn)

先看之前寫的的一個(gè)典型類:

class Discount:
    def __init__(self, data):
        self.type = data.get("type")
        self.amount = int(data.get("amount", 0))

使用 dataclass 重構(gòu)后:

from dataclasses import dataclass

@dataclass
class Discount:
    type: str
    amount: int

但這只是第一步,真實(shí)工程不會(huì)直接這樣寫。

3. dataclass 中的構(gòu)造邊界:__post_init__

在領(lǐng)域模型中:

  • 字段是“結(jié)構(gòu)”

  • 校驗(yàn)、轉(zhuǎn)換是“規(guī)則”

dataclass 提供 __post_init__ 來(lái)承載規(guī)則。

from dataclasses import dataclass

@dataclass
class Discount:
    type: str
    amount: int

    def __post_init__(self):
        self.amount = int(self.amount)

規(guī)范:類型轉(zhuǎn)換、校驗(yàn)邏輯應(yīng)放在 __post_init__,而不是外部代碼。

4. 復(fù)雜對(duì)象中的 dataclass 組合

重構(gòu) Pricing:

from dataclasses import dataclass

@dataclass
class Pricing:
    unit_price: int
    currency: str = "CNY"

    def total(self, quantity: int) -> int:
        return self.unit_price * quantity

OrderItem:

from dataclasses import dataclass, field
from typing import List

@dataclass
class OrderItem:
    sku: str
    pricing: Pricing
    quantity: int = 1
    discounts: List[Discount] = field(default_factory=list)

    def subtotal(self) -> int:
        discount = sum(d.amount for d in self.discounts)
        return self.pricing.total(self.quantity) - discount

此時(shí),模型結(jié)構(gòu)已經(jīng)一眼可讀。

5. 類型系統(tǒng)帶來(lái)的“隱性收益”

引入類型標(biāo)注后,產(chǎn)生的收益包括:

  • IDE 自動(dòng)補(bǔ)全

  • 靜態(tài)檢查(mypy / pyright)

  • 重構(gòu)安全性

  • 模型即文檔

例如:

def calculate_total(items: List[OrderItem]) -> int:
    ...

類型本身就表達(dá)了設(shè)計(jì)意圖。

6. dataclass 與不可變建模(高級(jí)用法)

在部分領(lǐng)域中(如支付、賬務(wù)),對(duì)象應(yīng)當(dāng)是不可變的。

@dataclass(frozen=True)
class PaymentTransaction:
    tx_id: str
    amount: int

不可變對(duì)象的工程意義:

  • 防止?fàn)顟B(tài)被隨意修改

  • 更容易推理

  • 更適合并發(fā)場(chǎng)景

7. dataclass ≠ DTO:職責(zé)仍然要分清

一個(gè)常見誤區(qū)是:“既然 dataclass 很方便,那 DTO 也用它吧?”

可以,但要遵守原則:

對(duì)象是否可用 dataclass是否包含行為
DTO可以不應(yīng)該
Domain Model強(qiáng)烈推薦必須

關(guān)鍵點(diǎn)不是工具,而是職責(zé)。

8. 工程規(guī)范:領(lǐng)域模型的現(xiàn)代 Python 寫法

綜合前面內(nèi)容,可以形成一套明確規(guī)范:

  • 領(lǐng)域模型使用 dataclass

  • 字段必須有類型

  • 規(guī)則寫在方法或 __post_init__

  • 嵌套關(guān)系通過(guò)類型表達(dá)

  • 不可變對(duì)象優(yōu)先用于關(guān)鍵領(lǐng)域

小結(jié)一下吧

通過(guò) dataclass 與類型系統(tǒng):

  • 模型從“能用”變?yōu)?ldquo;可靠”

  • 結(jié)構(gòu)從“隱式”變?yōu)?ldquo;顯式”

  • 重構(gòu)從“危險(xiǎn)”變?yōu)?ldquo;可控”

(八)領(lǐng)域模型與數(shù)據(jù)庫(kù)模型的邊界:ORM 與持久化設(shè)計(jì)

前面整體學(xué)習(xí)了解了:

  • 復(fù)雜領(lǐng)域建模

  • 明確的邊界與 DTO

  • dataclass + 類型系統(tǒng)增強(qiáng)

系統(tǒng)幾乎不可避免地會(huì)進(jìn)入一個(gè)危險(xiǎn)階段:為了“省事”,開始讓領(lǐng)域模型向數(shù)據(jù)庫(kù)結(jié)構(gòu)妥協(xié)。

這一節(jié)的目標(biāo),是明確劃清領(lǐng)域模型與持久化模型的邊界。

1. 一個(gè)常見但致命的誤區(qū)

很多系統(tǒng)會(huì)出現(xiàn)如下代碼風(fēng)格:

class Order(Base):
    __tablename__ = "orders"

    id = Column(String, primary_key=True)
    total_amount = Column(Integer)

看似優(yōu)雅,實(shí)際上隱藏著幾個(gè)問(wèn)題:

  • 領(lǐng)域模型被 ORM 污染

  • 數(shù)據(jù)庫(kù)結(jié)構(gòu)決定了領(lǐng)域結(jié)構(gòu)

  • 業(yè)務(wù)規(guī)則被擠出模型

工程結(jié)論:ORM Model ≠ Domain Model

2. 三種模型的職責(zé)劃分(必須牢記)

在成熟系統(tǒng)中,通常存在三類模型:

模型類型關(guān)注點(diǎn)變化頻率
DTO接口 / 邊界
Domain Model業(yè)務(wù)規(guī)則
Persistence Model(ORM)表結(jié)構(gòu)

它們解決的是完全不同的問(wèn)題。

3. 領(lǐng)域模型為什么不應(yīng)該“繼承 ORM”

原因并不抽象:

  • 數(shù)據(jù)庫(kù)字段不是業(yè)務(wù)語(yǔ)言

  • ORM 強(qiáng)制扁平化結(jié)構(gòu)

  • 懶加載/會(huì)話污染領(lǐng)域行為

  • 測(cè)試復(fù)雜度急劇上升

領(lǐng)域模型應(yīng)當(dāng):

  • 與數(shù)據(jù)庫(kù)無(wú)關(guān)

  • 可以脫離 ORM 獨(dú)立運(yùn)行與測(cè)試

4. 正確的工程結(jié)構(gòu)示意

一個(gè)合理的工程分層應(yīng)當(dāng)是:

領(lǐng)域模型永遠(yuǎn)不直接操作數(shù)據(jù)庫(kù)。

5. ORM Model:只做“表的映射”

以 SQLAlchemy 為例(僅作為概念說(shuō)明):

class OrderORM(Base):
    __tablename__ = "orders"

    order_id = Column(String, primary_key=True)
    total_amount = Column(Integer)

特點(diǎn):

  • 結(jié)構(gòu)與表一一對(duì)應(yīng)

  • 沒(méi)有業(yè)務(wù)行為

  • 允許妥協(xié)命名

6. Repository:連接領(lǐng)域與持久化的橋梁

Repository 是最關(guān)鍵、但最容易被忽略的一層

class OrderRepository:
    def save(self, order: Order):
        raise NotImplementedError

    def get(self, order_id: str) -> Order:
        raise NotImplementedError

領(lǐng)域?qū)又灰蕾?接口,而不是實(shí)現(xiàn)。

7. ORM → Domain 的裝配(反序列化)

class OrderRepositoryImpl(OrderRepository):
    def get(self, order_id: str) -> Order:
        orm = self.session.query(OrderORM).get(order_id)

        raw = {
            "order_id": orm.order_id,
            "items": self._load_items(orm),
            "payment": self._load_payment(orm)
        }

        return Order(raw)

注意:

  • ORM 結(jié)構(gòu)被“翻譯”

  • Domain Model 完全不知道 ORM 的存在

8. Domain → ORM 的持久化(序列化)

def save(self, order: Order):
    orm = OrderORM(
        order_id=order.order_id,
        total_amount=order.order_amount()
    )
    self.session.add(orm)

即使結(jié)構(gòu)重復(fù),也要接受。重復(fù)是隔離的代價(jià),也是穩(wěn)定性的來(lái)源。

9. 工程規(guī)范:持久化永遠(yuǎn)是“外部關(guān)心的事”

領(lǐng)域模型中 絕對(duì)不應(yīng)出現(xiàn)

  • session

  • commit

  • save()

  • ORM 注解

如果你在領(lǐng)域模型中看到這些,說(shuō)明:領(lǐng)域已經(jīng)被侵蝕。

小結(jié)一下吧

通過(guò)本節(jié),你應(yīng)當(dāng)形成以下堅(jiān)定認(rèn)知:

  • 領(lǐng)域模型不為數(shù)據(jù)庫(kù)服務(wù)

  • ORM 只是技術(shù)實(shí)現(xiàn)

  • Repository 隔離變化

  • 結(jié)構(gòu)重復(fù)是合理且必要的

  • 領(lǐng)域模型必須可以脫離數(shù)據(jù)庫(kù)獨(dú)立存在

(九)校驗(yàn)、異常與領(lǐng)域約束建模

現(xiàn)在我們已經(jīng)解決了:

  • 復(fù)雜結(jié)構(gòu)如何建模

  • 邊界如何隔離

  • 如何工程化增強(qiáng)模型

  • 如何與數(shù)據(jù)庫(kù)解耦

但到目前為止,仍有一個(gè)問(wèn)題被刻意回避了:如果數(shù)據(jù)是“非法的”,怎么辦?

現(xiàn)實(shí)系統(tǒng)中,非法數(shù)據(jù)是常態(tài),而不是例外

1. 一個(gè)常見但危險(xiǎn)的現(xiàn)狀

很多系統(tǒng)對(duì)“非法數(shù)據(jù)”的處理方式是:

if price <= 0:
    return None

或者:

try:
    ...
except Exception:
    pass

這些寫法的問(wèn)題不在于“能不能跑”,而在于:

  • 錯(cuò)誤被吞掉

  • 規(guī)則被隱式化

  • 系統(tǒng)進(jìn)入“不可預(yù)期狀態(tài)”

工程結(jié)論:校驗(yàn)不是工具層問(wèn)題,而是領(lǐng)域模型的職責(zé)

2. 什么是“領(lǐng)域約束”(Domain Constraint)

領(lǐng)域約束指的是:

  • 業(yè)務(wù)上不允許被破壞的規(guī)則

  • 與技術(shù)、存儲(chǔ)、接口無(wú)關(guān)

  • 一旦違反,系統(tǒng)就不應(yīng)繼續(xù)執(zhí)行

例如:

  • 訂單金額不能為負(fù)

  • 支付金額不能小于 0

  • 已完成訂單不能再次支付

這些規(guī)則 不屬于 Controller,也不屬于 Service,而是:領(lǐng)域模型自身的邊界。

3. 領(lǐng)域異常:用“異常”表達(dá)規(guī)則破壞

在領(lǐng)域建模中,異常不是“程序錯(cuò)誤”,而是:對(duì)業(yè)務(wù)規(guī)則被破壞的明確聲明

首先,定義領(lǐng)域異常基類:

class DomainError(Exception):
    pass

然后為關(guān)鍵規(guī)則定義具體異常:

class InvalidPriceError(DomainError):
    pass

class PaymentAmountError(DomainError):
    pass

class OrderStateError(DomainError):
    pass

規(guī)范:不要在領(lǐng)域中直接拋 ValueError、TypeError。

4. 在模型內(nèi)部執(zhí)行校驗(yàn)(而不是外部 if)

OrderItem 為例:

from dataclasses import dataclass

@dataclass
class OrderItem:
    sku: str
    quantity: int

    def __post_init__(self):
        if self.quantity <= 0:
            raise InvalidPriceError("quantity must be positive")

此時(shí):

  • 非法對(duì)象 根本無(wú)法被構(gòu)造

  • 錯(cuò)誤在最早階段暴露

5. 行為級(jí)校驗(yàn):規(guī)則與動(dòng)作綁定

不是所有校驗(yàn)都發(fā)生在構(gòu)造階段。

例如:支付行為。

class Order:
    ...

    def pay(self, amount: int):
        if amount <= 0:
            raise PaymentAmountError("payment must be positive")

        if self.is_fully_paid():
            raise OrderStateError("order already paid")

        self.payment.add_transaction(amount)

關(guān)鍵原則:規(guī)則應(yīng)當(dāng)與“動(dòng)作”綁定,而不是與“字段”綁定。

6. 領(lǐng)域狀態(tài)與約束的結(jié)合

復(fù)雜系統(tǒng)中,狀態(tài)本身就是約束來(lái)源。

class OrderStatus:
    CREATED = "CREATED"
    PAID = "PAID"
    CANCELED = "CANCELED"


class Order:
    ...

    def cancel(self):
        if self.status == OrderStatus.PAID:
            raise OrderStateError("paid order cannot be canceled")

        self.status = OrderStatus.CANCELED

此時(shí):

  • 狀態(tài)轉(zhuǎn)換路徑被嚴(yán)格限制

  • 非法流程無(wú)法發(fā)生

7. 校驗(yàn)邏輯的分層原則(非常重要)

一個(gè)成熟系統(tǒng)中,校驗(yàn)應(yīng)分為三層:

層級(jí)校驗(yàn)內(nèi)容示例
接口層格式、必填JSON 字段是否存在
邊界層基本合法性字符串能否轉(zhuǎn) int
領(lǐng)域?qū)?/td>業(yè)務(wù)規(guī)則金額、狀態(tài)、約束

絕對(duì)禁止:在 Controller 中寫業(yè)務(wù)規(guī)則判斷。

8. 異常如何“向外傳播”

領(lǐng)域異常的傳播路徑應(yīng)當(dāng)是:

Controller 的職責(zé)不是“判斷規(guī)則”,而是:

try:
    order.pay(amount)
except DomainError as e:
    return error_response(str(e))

9. 工程規(guī)范:失敗是系統(tǒng)能力的一部分

一個(gè)系統(tǒng)是否健壯,不取決于:能否處理正常數(shù)據(jù)

而取決于:能否正確拒絕不合法行為

領(lǐng)域異常的價(jià)值在于:

  • 規(guī)則顯式

  • 行為可追蹤

  • 錯(cuò)誤不可忽略

八、總結(jié)

至此,本篇內(nèi)容對(duì) Python 基礎(chǔ)知識(shí)進(jìn)行了一個(gè)相對(duì)系統(tǒng)的梳理與總結(jié)。

從運(yùn)行環(huán)境與工具選擇,到變量、控制流、函數(shù)、字符串處理,再到列表、字典、集合等核心數(shù)據(jù)結(jié)構(gòu),本博客力求用工程視角 + 可運(yùn)行示例的方式,期望在較短時(shí)間內(nèi)建立起對(duì) Python 編程的整體認(rèn)知和基本實(shí)戰(zhàn)能力。

需要說(shuō)明的是,這份內(nèi)容同樣也是我在學(xué)習(xí) Python 過(guò)程中的階段性整理與沉淀。難免存在理解不夠嚴(yán)謹(jǐn)或表述不夠完善之處,歡迎各位讀者在評(píng)論區(qū)留言指正、交流探討,這對(duì)我和后續(xù)讀者都會(huì)非常有價(jià)值。

如果你能通過(guò)本文:

  • 理解 Python 的核心語(yǔ)法思想

  • 看懂并獨(dú)立編寫基礎(chǔ)程序

  • 對(duì)后續(xù)深入學(xué)習(xí)(如數(shù)據(jù)處理、Web、自動(dòng)化或 AI 方向)不再畏懼

那么這篇總結(jié)就達(dá)到了它應(yīng)有的意義。

Python 是一門上手友好、上限極高的語(yǔ)言,但真正的成長(zhǎng)來(lái)自持續(xù)實(shí)踐,而不是一次性閱讀。希望你在未來(lái)的學(xué)習(xí)過(guò)程中,多動(dòng)手、多思考、多調(diào)試,把“會(huì)寫”逐步變成“寫得好、寫得穩(wěn)”。

以上就是入門初學(xué)者短期內(nèi)快速掌握Python的經(jīng)典全面教程(專家學(xué)習(xí)筆記)的詳細(xì)內(nèi)容,更多關(guān)于Python基礎(chǔ)學(xué)習(xí)總結(jié)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python filecmp.dircmp實(shí)現(xiàn)遞歸比對(duì)兩個(gè)目錄的方法

    python filecmp.dircmp實(shí)現(xiàn)遞歸比對(duì)兩個(gè)目錄的方法

    這篇文章主要介紹了python filecmp.dircmp實(shí)現(xiàn)遞歸比對(duì)兩個(gè)目錄的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 一篇文章帶你深入學(xué)習(xí)Python函數(shù)

    一篇文章帶你深入學(xué)習(xí)Python函數(shù)

    這篇文章主要帶大家深入學(xué)習(xí)Python函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Python中ArcPy柵格裁剪柵格(批量對(duì)齊柵格圖像范圍并統(tǒng)一行數(shù)與列數(shù))

    Python中ArcPy柵格裁剪柵格(批量對(duì)齊柵格圖像范圍并統(tǒng)一行數(shù)與列數(shù))

    本文介紹基于Python中ArcPy模塊,實(shí)現(xiàn)基于柵格圖像批量裁剪柵格圖像,同時(shí)對(duì)齊各個(gè)柵格圖像的空間范圍,統(tǒng)一其各自行數(shù)與列數(shù)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Python+OpenCV六種實(shí)時(shí)圖像處理詳細(xì)講解

    Python+OpenCV六種實(shí)時(shí)圖像處理詳細(xì)講解

    OpenCV常用的圖像處理為閾值二值化、邊緣檢測(cè)、輪廓檢測(cè)、高斯濾波、色彩轉(zhuǎn)換、調(diào)節(jié)對(duì)比度。本文主要介紹了利用Python和OpenCV對(duì)實(shí)時(shí)圖像進(jìn)行上述六種操作的詳細(xì)講解,感興趣的可以了解一下。
    2021-11-11
  • 詳解python中靜態(tài)方法staticmethod用法

    詳解python中靜態(tài)方法staticmethod用法

    本文主要介紹了python中靜態(tài)方法staticmethod用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • python Hypothesis生成和執(zhí)行大量的測(cè)試用例

    python Hypothesis生成和執(zhí)行大量的測(cè)試用例

    Hypothesis是一個(gè)基于屬性的測(cè)試(property-based testing)庫(kù),它能夠幫助我們生成和執(zhí)行大量的測(cè)試用例,與傳統(tǒng)的單元測(cè)試相比,屬性測(cè)試更加靈活和全面,能夠發(fā)現(xiàn)更多的邊界情況和潛在的錯(cuò)誤
    2024-01-01
  • python解析.pyd文件的詳細(xì)代碼

    python解析.pyd文件的詳細(xì)代碼

    這篇文章介紹了python解析.pyd文件的詳細(xì)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考
    2021-12-12
  • Python 生成短8位唯一id實(shí)戰(zhàn)教程

    Python 生成短8位唯一id實(shí)戰(zhàn)教程

    這篇文章主要介紹了Python 生成短8位唯一id實(shí)戰(zhàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • 使用Mixin設(shè)計(jì)模式進(jìn)行Python編程的方法講解

    使用Mixin設(shè)計(jì)模式進(jìn)行Python編程的方法講解

    Mixin模式也可以看作是一種組合模式,綜合多個(gè)類的功能來(lái)產(chǎn)生一個(gè)類而不通過(guò)繼承來(lái)實(shí)現(xiàn),下面就來(lái)整理一下使用Mixin設(shè)計(jì)模式進(jìn)行Python編程的方法講解:
    2016-06-06
  • python計(jì)算方程式根的方法

    python計(jì)算方程式根的方法

    這篇文章主要介紹了python計(jì)算方程式根的方法,涉及Python數(shù)學(xué)運(yùn)算的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05

最新評(píng)論

双牌县| 吉林省| 沐川县| 深州市| 岗巴县| 铁岭市| 万山特区| 仁怀市| 扎鲁特旗| 定兴县| 金门县| 瑞昌市| 类乌齐县| 汉源县| 肥东县| 琼中| 龙南县| 沁水县| 海林市| 水城县| 宜兰市| 遂昌县| 高密市| 万源市| 察隅县| 清水县| 健康| 武安市| 林西县| 桦南县| 靖宇县| 古田县| 望城县| 郸城县| 河池市| 开阳县| 鹤峰县| 松溪县| 苏尼特左旗| 青阳县| 海阳市|