據(jù)清洗 — 把臟數(shù)據(jù)捋干凈)
前言FDE系列內(nèi)容總綱【大綱】FDE 前沿部署工程師學(xué)習(xí)系列教程-CSDN博客前置課程列表見文檔結(jié)尾附錄。階段2·Day 34數(shù)據(jù)清洗 — 把臟數(shù)據(jù)捋干凈FDE 學(xué)習(xí)系列教程 · 第二階段 · 第 3 周 · Day 4預(yù)計(jì)時(shí)長(zhǎng)2.5 小時(shí) | 難度★★★☆☆ | 前置知識(shí)SQL 基礎(chǔ)、Python 文件讀寫、logging 日志一句話目標(biāo)識(shí)別四類常見臟數(shù)據(jù)用 Python SQL 完成去重、缺失值處理、格式對(duì)齊、類型轉(zhuǎn)換和脫敏把一份臟 CSV 洗成標(biāo)準(zhǔn)結(jié)構(gòu)化數(shù)據(jù)入庫。?? 開場(chǎng)FDE 最真實(shí)的工作場(chǎng)景來了兄弟前三天學(xué)的查詢前提都是數(shù)據(jù)是干凈的。但現(xiàn)實(shí)會(huì)狠狠給你上一課??蛻舭l(fā)來一個(gè) Excel 導(dǎo)出的 CSV你滿懷期待地打開——設(shè)備名 溫度 負(fù)責(zé)人 手機(jī)號(hào) ← 問題 注塑機(jī)A1 65 李工 13812345678 注塑機(jī)A1 65 李工 13812345678 ← ① 跟上面完全重復(fù) 注塑機(jī)A2 八十二 王工 ← ② 溫度是中文手機(jī)號(hào)缺失 注塑機(jī)a3 91 趙工 138-1234-5678 ← ③ 設(shè)備名小寫、手機(jī)帶橫杠 注塑機(jī) A3 91 趙工 13812345678 ← ④ 名字多空格和上一行其實(shí)重復(fù) 沖壓機(jī)B1 75 李工 13812345678 沖壓機(jī)B1 75 李工 13812345678 ← ⑤ 又一條完全重復(fù) 注塑機(jī)A4 趙工 13811112222 ← ⑥ 溫度為空這就是江湖人稱的臟數(shù)據(jù)Dirty Data。這種東西直接進(jìn)數(shù)據(jù)庫統(tǒng)計(jì)結(jié)果全錯(cuò)、JOIN 關(guān)聯(lián)不上、報(bào)表數(shù)字打架??蛻暨€會(huì)一臉無辜地問你我們的數(shù)據(jù)……挺整齊的呀今天你就學(xué)會(huì)怎么把它洗干凈。這活兒不炫技但數(shù)據(jù)清洗往往占數(shù)據(jù)分析 60% 以上的時(shí)間是 FDE 的硬功夫。 一、先認(rèn)清四類臟數(shù)據(jù)別上來就寫代碼先建立臟數(shù)據(jù)分類學(xué)。對(duì)癥下藥才不亂┌──────────────────────────────────────────────────────────────┐ │ 臟數(shù)據(jù)的四大門派 │ ├──────────────┬───────────────────────────────────────────────┤ │ ① 重復(fù)數(shù)據(jù) │ 同一條記錄出現(xiàn)多次 │ │ (Duplicate) │ 完全重復(fù) / 實(shí)質(zhì)重復(fù)大小寫空格差異 │ │ │ 危害統(tǒng)計(jì)數(shù)量翻倍、SUM 偏大 │ ├──────────────┼───────────────────────────────────────────────┤ │ ② 缺失值 │ 該有的數(shù)據(jù)是空的 │ │ (Missing) │ 溫度沒填、手機(jī)號(hào)空、NULL │ │ │ 危害AVG 算錯(cuò)、JOIN 丟數(shù)據(jù)、程序報(bào)錯(cuò) │ ├──────────────┼───────────────────────────────────────────────┤ │ ③ 格式不一致 │ 同一個(gè)意思寫法五花八門 │ │ (Inconsistent)│ 82 / 八十二 / 約82度 │ │ │ 138-1234-5678 / 13812345678 │ │ │ 注塑機(jī)a3 / 注塑機(jī) A3 / 注塑機(jī)A3 │ │ │ 危害去重失效、關(guān)聯(lián)不上、無法計(jì)算 │ ├──────────────┼───────────────────────────────────────────────┤ │ ④ 類型/異常值│ 數(shù)字列混進(jìn)文字、溫度寫成 9999傳感器故障 │ │ (Wrong Type)│ 危害轉(zhuǎn) float 崩潰、統(tǒng)計(jì)被極端值帶偏 │ └──────────────┴──────────────────────────────────────────────┘清洗總原則先標(biāo)準(zhǔn)化去空格、統(tǒng)一大小寫再去重最后處理缺失和類型。順序很重要——如果不先把注塑機(jī)a3和注塑機(jī) A3標(biāo)準(zhǔn)化成同一個(gè)樣子去重時(shí)根本認(rèn)不出它倆是重復(fù)的。清洗流水線全景圖臟 CSV ① 標(biāo)準(zhǔn)化 ② 去重 ③ 補(bǔ)缺/轉(zhuǎn)類型 干凈數(shù)據(jù)庫 ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 重復(fù)行 │ │ 去空格 │ │ 完全重復(fù) │ │ 溫度→數(shù)字 │ │ │ │ 中文數(shù)字 │ ───? │ 統(tǒng)一大小寫│ ───? │ 去掉 │ ─? │ 缺失→NULL │ ──? │ MySQL │ │ 空手機(jī)號(hào) │ │ 去橫杠 │ │ 實(shí)質(zhì)重復(fù) │ │ 手機(jī)號(hào)兜底 │ │ 干凈表 │ │ 大小寫亂 │ │ 去多余字符│ │ 去掉 │ │ 記錄日志 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ 每一步都打日志改了什么可追溯? 二、準(zhǔn)備臟數(shù)據(jù)在sql_practice文件夾新建dirty_data.csv逐字粘進(jìn)去故意做臟device_name,temperature,owner_name,phone,type 注塑機(jī)A1,65,李工,13812345678,注塑 注塑機(jī)A1,65,李工,13812345678,注塑 注塑機(jī)A2,八十二,王工,,注塑 注塑機(jī)a3,91,趙工,138-1234-5678,注塑 注塑機(jī) A3,91,趙工,13812345678,注塑 沖壓機(jī)B1,75,李工,13812345678,沖壓 沖壓機(jī)B1,75,李工,13812345678,沖壓 沖壓機(jī)B2,88,陳工,13987654321,沖壓 注塑機(jī)A4,,趙工,13811112222,注塑對(duì)照清單確認(rèn)你能指出每行的毛病行毛病門派1-2完全重復(fù)① 重復(fù)3溫度八十二、手機(jī)空③格式 ②缺失4設(shè)備名小寫a3、手機(jī)帶橫杠③格式5設(shè)備名帶空格和空格與第4行實(shí)質(zhì)重復(fù)③格式 ①重復(fù)6-7完全重復(fù)① 重復(fù)9溫度為空②缺失? 三、寫清洗腳本Python 標(biāo)準(zhǔn)庫版這節(jié)也簡(jiǎn)單會(huì)的同學(xué)可以重點(diǎn)看清洗順序和日志記錄兩個(gè)思路。新建06_clean.py 數(shù)據(jù)清洗實(shí)戰(zhàn)從臟 CSV 到干凈數(shù)據(jù)庫 文件06_clean.py import sqlite3 import csv import logging # 配置日志時(shí)間 [級(jí)別] 信息 —— 清洗過程全程留痕 logging.basicConfig( levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s ) log logging.getLogger(__name__) # ① 讀入臟 CSV def load_dirty_csv(path): with open(path, encodingutf-8) as f: return list(csv.DictReader(f)) # ② 逐行清洗先標(biāo)準(zhǔn)化再轉(zhuǎn)類型 def clean_records(records): # 中文數(shù)字 → 阿拉伯?dāng)?shù)字 的映射表 cn_map {八十二: 82, 九十: 90, 九十一: 91} cleaned [] for i, r in enumerate(records): # —— 標(biāo)準(zhǔn)化去空格 —— r[device_name] r[device_name].strip() r[owner_name] r[owner_name].strip() # —— 標(biāo)準(zhǔn)化設(shè)備名英文統(tǒng)一大寫 去掉內(nèi)部空格 —— # 注塑機(jī)a3 → 注塑機(jī)A3注塑機(jī) A3 → 注塑機(jī)A3 r[device_name] r[device_name].upper().replace( , ) # —— 溫度中文數(shù)字轉(zhuǎn)阿拉伯再轉(zhuǎn) float —— temp_str r[temperature].strip() if temp_str in cn_map: temp_str cn_map[temp_str] try: r[temperature] float(temp_str) except (ValueError, TypeError): # 轉(zhuǎn)不了空字符串、奇怪文字就設(shè)為 None進(jìn)庫存 NULL r[temperature] None log.warning(f第 {i2} 行溫度無法轉(zhuǎn)換{temp_str}已設(shè)為 NULL) # —— 手機(jī)號(hào)去掉橫杠和空格空的設(shè) None —— phone r[phone].strip().replace(-, ).replace( , ) r[phone] phone if phone else None if not phone: log.warning(f第 {i2} 行手機(jī)號(hào)缺失已設(shè)為 NULL) r[type] r[type].strip() cleaned.append(r) return cleaned # ③ 去重標(biāo)準(zhǔn)化之后按 (設(shè)備名, 負(fù)責(zé)人) 判重 def deduplicate(records): seen set() unique [] for r in records: key (r[device_name], r[owner_name]) if key in seen: log.info(f去除重復(fù)行{r[device_name]} / {r[owner_name]}) continue seen.add(key) unique.append(r) return unique # ④ 存入干凈的 SQLite 表 def save_to_db(records, db_pathfde_clean.db): conn sqlite3.connect(db_path) cur conn.cursor() cur.execute( CREATE TABLE IF NOT EXISTS devices_clean ( id INTEGER PRIMARY KEY AUTOINCREMENT, device_name TEXT NOT NULL, temperature REAL, owner_name TEXT NOT NULL, phone TEXT, type TEXT, imported_at TEXT DEFAULT (datetime(now,localtime)) ) ) for r in records: cur.execute( INSERT INTO devices_clean (device_name,temperature,owner_name,phone,type) VALUES (?,?,?,?,?) , (r[device_name], r[temperature], r[owner_name], r[phone], r[type])) conn.commit() cur.execute(SELECT COUNT(*) FROM devices_clean) count cur.fetchone()[0] conn.close() return count # 主流程按順序串起來 raw load_dirty_csv(dirty_data.csv) log.info(f原始數(shù)據(jù){len(raw)} 行) cleaned clean_records(raw) log.info(f標(biāo)準(zhǔn)化 類型轉(zhuǎn)換完成{len(cleaned)} 行) unique deduplicate(cleaned) log.info(f去重后{len(unique)} 行刪掉 {len(cleaned)-len(unique)} 條重復(fù)) count save_to_db(unique) log.info(f? 寫入數(shù)據(jù)庫{count} 條干凈數(shù)據(jù))運(yùn)行并觀察python 06_clean.py預(yù)期日志注意每一步的行數(shù)變化[INFO] 原始數(shù)據(jù)9 行 [WARNING] 第 4 行溫度無法轉(zhuǎn)換八十二已設(shè)為 NULL ← 實(shí)際已被中文映射轉(zhuǎn)成82這行不會(huì)出現(xiàn) [WARNING] 第 4 行手機(jī)號(hào)缺失已設(shè)為 NULL [INFO] 去除重復(fù)行注塑機(jī)A1 / 李工 [INFO] 去除重復(fù)行注塑機(jī)A3 / 趙工 [INFO] 去除重復(fù)行沖壓機(jī)B1 / 李工 [INFO] 去重后6 行刪掉 3 條重復(fù) [WARNING] 第 10 行溫度無法轉(zhuǎn)換已設(shè)為 NULL [INFO] ? 寫入數(shù)據(jù)庫6 條干凈數(shù)據(jù)?? 小細(xì)節(jié)第 3 行溫度是八十二會(huì)被cn_map先轉(zhuǎn)成 82 再轉(zhuǎn) float所以不會(huì)報(bào)警告第 9 行溫度是空字符串映射表沒有float()報(bào)錯(cuò)才走 None 分支??梢栽谀_本里打斷點(diǎn)或加 print 驗(yàn)證這個(gè)分支邏輯。清洗后的干凈數(shù)據(jù)在 DBeaver 打開 fde_clean.db 查看device_name | temperature | owner_name | phone | type 注塑機(jī)A1 | 65.0 | 李工 | 13812345678 | 注塑 注塑機(jī)A2 | 82.0 | 王工 | NULL | 注塑 ← 八十二→82手機(jī)NULL 注塑機(jī)A3 | 91.0 | 趙工 | 13812345678 | 注塑 ← a3/A3 兩種寫法合并 沖壓機(jī)B1 | 75.0 | 李工 | 13812345678 | 沖壓 沖壓機(jī)B2 | 88.0 | 陳工 | 13987654321 | 沖壓 注塑機(jī)A4 | NULL | 趙工 | 13811112222 | 注塑 ← 空溫度存為 NULL9 行臟數(shù)據(jù) → 6 行干凈數(shù)據(jù)。世界清凈了。 四、SQL 清洗函數(shù)速查表清洗不一定要在 Python 里做很多標(biāo)準(zhǔn)化操作 SQL 也能直接干。這張表兩邊對(duì)照著用需求SQL 函數(shù)例子對(duì)應(yīng) Python去兩端空格TRIM(x)TRIM(device_name).strip()轉(zhuǎn)大寫UPPER(x)UPPER(name).upper()轉(zhuǎn)小寫LOWER(x)LOWER(name).lower()替換字符REPLACE(x,a,b)REPLACE(phone,-,).replace(-,)取子串SUBSTR(x,起,長(zhǎng))SUBSTR(phone,1,3)切片s[:3]拼接x || y138 || ****a b/ f-stringNULL 兜底COALESCE(x,默認(rèn))COALESCE(temp,0)x or 默認(rèn)類型轉(zhuǎn)換CAST(x AS 類型)CAST(82 AS REAL)float(x)去重DISTINCTSELECT DISTINCT name...set()/drop_duplicatesCOALESCE 是清洗界的暖男COALESCE(字段, 默認(rèn)值)意思是這個(gè)字段如果是 NULL就用默認(rèn)值頂上可以串多個(gè)COALESCE(phone, 未登記, 未知)——第一個(gè)非 NULL 的勝出。比 MySQL 專屬的IFNULL更通用SQLite/MySQL/PG 都支持。用 SQL 直接查干凈結(jié)果不落庫也能驗(yàn)證-- 同一份清洗邏輯用純 SQL 表達(dá)針對(duì)已入庫的原始表 SELECT DISTINCT UPPER(REPLACE(TRIM(device_name), , )) AS 標(biāo)準(zhǔn)設(shè)備名, CAST(REPLACE(temperature, 八十二, 82) AS REAL) AS 溫度, TRIM(owner_name) AS 負(fù)責(zé)人, REPLACE(REPLACE(TRIM(phone), -, ), , ) AS 手機(jī) FROM devices_raw;? 五、數(shù)據(jù)脫敏把敏感信息打碼清洗入庫后數(shù)據(jù)還常常要給別人看做報(bào)表、發(fā)給外部、截圖匯報(bào)。手機(jī)號(hào)、身份證號(hào)這類 PII個(gè)人身份信息必須脫敏——入庫存全量展示打碼。-- 手機(jī)號(hào)脫敏13812345678 → 138****5678 SELECT device_name AS 設(shè)備, owner_name AS 負(fù)責(zé)人, SUBSTR(phone, 1, 3) || **** || SUBSTR(phone, 8, 4) AS 脫敏手機(jī), COALESCE(CAST(temperature AS TEXT), 缺失) AS 溫度 FROM devices_clean ORDER BY device_name;結(jié)果設(shè)備 | 負(fù)責(zé)人 | 脫敏手機(jī) | 溫度 注塑機(jī)A1 | 李工 | 138****5678 | 65.0 注塑機(jī)A2 | 王工 | NULL | 缺失 注塑機(jī)A3 | 趙工 | 138****5678 | 91.0 沖壓機(jī)B1 | 李工 | 138****5678 | 75.0 沖壓機(jī)B2 | 陳工 | 139****4321 | 88.0 注塑機(jī)A4 | 趙工 | 138****2222 | 缺失拆解手機(jī)號(hào)脫敏公式13812345678 ├─┬─┤├────┤├─┬─┤ 前3位 打碼4位 后4位 SUBSTR(...,1,3) **** SUBSTR(...,8,4) 138 **** 5678脫敏 vs 加密 別混淆脫敏不可逆地隱藏一部分138****5678用于展示看個(gè)大概但無法還原加密可逆有密鑰能解開如 AES用于必須還原的存儲(chǔ)場(chǎng)景報(bào)表展示用脫敏就夠了別把完整手機(jī)號(hào)隨手貼到群里或截圖里。 六、? 常見翻車點(diǎn)翻車點(diǎn)后果正確姿勢(shì)先去重后標(biāo)準(zhǔn)化a3 和 A3 認(rèn)不出是同一條去重失效先 TRIM/UPPER 標(biāo)準(zhǔn)化再判重空字符串當(dāng)正常值float()直接崩或統(tǒng)計(jì)出零個(gè)字符的怪結(jié)果顯式判斷空統(tǒng)一轉(zhuǎn) None/NULL用 None判斷Python 里None要用is Noneif not phone:或x is None缺失值一律填 0溫度 0 是真實(shí)可能的值會(huì)污染平均值數(shù)值缺失填 NULLAVG 自動(dòng)忽略或業(yè)務(wù)默認(rèn)值別想當(dāng)然清洗不留日志出問題查不到改了啥、刪了幾條每步打日志原始多少、刪掉多少、轉(zhuǎn)換多少直接覆蓋原始數(shù)據(jù)清洗規(guī)則錯(cuò)了原始數(shù)據(jù)毀了找不回臟數(shù)據(jù)只讀結(jié)果寫新表/新文件??務(wù)必保留原始數(shù)據(jù)清洗永遠(yuǎn)在副本上做原始 CSV 和原始表絕不動(dòng)。萬一清洗邏輯有 bug你還能推倒重來。這是數(shù)據(jù)工作者的底線。 本課小結(jié)知識(shí)點(diǎn)一句話記住四類臟數(shù)據(jù)重復(fù)、缺失、格式不一致、類型/異常值清洗順序先標(biāo)準(zhǔn)化 → 再去重 → 后補(bǔ)缺/轉(zhuǎn)類型去空格Python.strip()/ SQLTRIM()統(tǒng)一大小寫.upper()/UPPER()去字符.replace(-,)/REPLACE()中文數(shù)字映射字典替換后再轉(zhuǎn) float類型轉(zhuǎn)換float()配 try/except失敗設(shè) None去重Python 用set存 keySQL 用DISTINCTNULL 兜底COALESCE(列, 默認(rèn)值)脫敏SUBSTR取頭尾 拼接打碼展示用日志留痕每步記錄行數(shù)變化和異??勺匪荼Wo(hù)原始在副本上清洗原始數(shù)據(jù)只讀不覆蓋 核心認(rèn)知數(shù)據(jù)清洗不是碰運(yùn)氣修修補(bǔ)補(bǔ)而是一條固定流水線——識(shí)別臟的類型、按正確順序處理、每一步留日志、原始數(shù)據(jù)不動(dòng)。把這套流程腳本化以后客戶再來 100 份臟 CSV你改改配置就能批量洗。 課后練習(xí)練習(xí) 1給臟數(shù)據(jù)加兩種新臟升級(jí)清洗腳本約 40 分鐘在dirty_data.csv里追加兩行注塑機(jī)A5,約82度,孫工,138 0000 5555, 注塑機(jī)a5,82,孫工,13800005555,新問題溫度寫成約82度需要從文字里提取數(shù)字提示用正則re.search(r\d, s)type列有空值提示空的填未知這兩行清洗后應(yīng)識(shí)別為同一臺(tái)設(shè)備而只保留一條修改06_clean.py處理它們跑通后確認(rèn)最終是 7 條干凈數(shù)據(jù)。練習(xí) 2用 SQL DISTINCT 驗(yàn)證去重約 15 分鐘把臟數(shù)據(jù)先導(dǎo)進(jìn)一張devices_raw表用SELECT DISTINCT 標(biāo)準(zhǔn)化列...去重和 Python 腳本的結(jié)果對(duì)比確認(rèn)條數(shù)和內(nèi)容一致。練習(xí) 3身份證脫敏約 15 分鐘寫一條 SQL把身份證號(hào)110101199001011234脫敏成110101********1234保留前 6 位和后 4 位中間 8 位打星。提示SUBSTR(x,1,6)********SUBSTR(x,15,4)。 下節(jié)預(yù)告今天我們?cè)谳p量的 SQLite 里完成了清洗。但客戶現(xiàn)場(chǎng)跑的是真正的MySQL。明天是本周收官干三件大事安裝配置 MySQL把練習(xí)環(huán)境升級(jí)成企業(yè)級(jí)數(shù)據(jù)庫用SQLAlchemy pandas在 Python 里優(yōu)雅地讀寫數(shù)據(jù)庫告別手寫一堆 cursor把第 2 周的工單 API 從內(nèi)存列表升級(jí)為 MySQL 持久化——服務(wù)重啟數(shù)據(jù)再也不丟親手體會(huì)分層架構(gòu)帶來的好處明天過后你就擁有一條完整的數(shù)據(jù)管道臟 CSV → pandas 清洗 → MySQL → FastAPI 查詢。本周的壓軸大戲明天見附錄前置課程列表階段一【FDE系列】階段1Day 1AI 層級(jí)關(guān)系 — 四個(gè)嵌套的圈-CSDN博客【FDE系列】階段1Day 2AI 三階段發(fā)展史 — 會(huì)認(rèn) → 會(huì)判斷 → 會(huì)創(chuàng)造-CSDN博客【FDE系列】階段1Day 3符號(hào) AI vs 機(jī)器學(xué)習(xí) — 兩條路線的本質(zhì)區(qū)別-CSDN博客【FDE系列】階段1Day 4Transformer 的歷史意義 — 2017 年的分水嶺-CSDN博客【FDE系列】階段1Day 5本周復(fù)習(xí)與自測(cè) — 檢驗(yàn)?zāi)愕?AI 認(rèn)知地基-CSDN博客【FDE系列】階段1Day 6Transformer 架構(gòu) — 一張圖紙蓋出千千萬萬棟樓-CSDN博客【FDE系列】階段1Day 7LLM 本質(zhì) — 文字接龍機(jī)器-CSDN博客【FDE系列】階段1Day 8Token — 模型眼中的最小單位-CSDN博客【FDE系列】階段1Day 9AI 幻覺 — 為什么會(huì)一本正經(jīng)地胡說八道-CSDN博客【FDE系列】階段1Day 10上下文窗口 — 模型的記憶力上限 本周復(fù)習(xí)-CSDN博客【FDE系列】階段1Day 11Prompt — 給模型立規(guī)矩-CSDN博客【FDE系列】階段1Day 12Memory — 讓模型記住上下文【FDE系列】階段1Day 13RAG — 給模型配圖書管理員-CSDN博客【FDE系列】階段1Day 14Tool Use — 讓模型動(dòng)手操作-CSDN博客【FDE系列】階段1Day 15MCP — 統(tǒng)一的工具接口標(biāo)準(zhǔn) 第三周復(fù)習(xí)-CSDN博客【FDE系列】階段1Day 16什么是 FDE — 把 AI 變成客戶結(jié)果的人-CSDN博客【FDE系列】階段1Day 17FDE vs 傳統(tǒng)實(shí)施 — 三大本質(zhì)區(qū)別-CSDN博客【FDE系列】階段1Day 18FDE 三重身份 C6 勝任力模型-CSDN博客【FDE系列】階段1Day 19七階段行動(dòng)路徑 行業(yè)經(jīng)驗(yàn)的價(jià)值-CSDN博客【FDE系列】階段1Day 20階段總結(jié)與產(chǎn)出物 — 第一階段收官-CSDN博客階段二【FDE系列】階段2Day 21Python 環(huán)境搭建 — 寫出你的第一行代碼-CSDN博客【FDE系列】階段2Day 22變量、數(shù)據(jù)類型、條件判斷 — Python 的“記憶“和“判斷“-CSDN博客【FDE系列】階段2Day 23循環(huán)與函數(shù) — 讓代碼跑 100 遍、把邏輯打包復(fù)用-CSDN博客【FDE系列】階段2Day 24數(shù)據(jù)結(jié)構(gòu) — 列表、字典、集合、元組-CSDN博客【FDE系列】階段2Day 25文件讀寫與 JSON — 讓程序連通外部數(shù)據(jù)第一周收官-CSDN博客【FDE系列】階段2Day 26模塊化編程 — 把代碼拆成“抽屜柜“-CSDN博客【FDE系列】階段2Day 27異常處理與日志 — 讓程序“摔不爛、查得到“-CSDN博客【FDE系列】階段2Day 28FastAPI 入門 — 把你的函數(shù)變成 API 服務(wù)-CSDN博客【FDE系列】階段2Day 29FastAPI 進(jìn)階 — Pydantic 模型與完整 CRUD 實(shí)戰(zhàn)-CSDN博客【FDE系列】階段2Day 30生產(chǎn)代碼規(guī)范 — 測(cè)試、類型注解、配置管理第二周收官-CSDN博客【FDE系列】階段2Day 31SQL 基礎(chǔ) — 增刪改查一把梭-CSDN博客【FDE系列】階段2Day 32多表查詢 — JOIN 與聚合-CSDN博客【FDE系列】階段2Day 33進(jìn)階查詢 — 窗口函數(shù)與 CTE-CSDN博客