2026年Python入门路线图:从零到实战的30天逐日详解(二)

📅 2026/7/24 16:03:25
2026年Python入门路线图:从零到实战的30天逐日详解(二)
欢迎来到Python 30天学习计划从第16天开始我们将进入数据分析和Web开发的实战阶段。接下来的每一天你都会学到一项实用的Python技能——从Pandas处理表格数据到Matplotlib绘制图表再到爬虫、Flask建站、SQLite数据库最后用Git管理代码版本。每节课都配有可直接运行的代码示例和练习任务跟着敲一遍你的Python水平就能稳步提升。准备好了吗让我们从第16天的Pandas开始吧第16天Pandas——表格处理神器今天要做什么学会用Pandas读取和处理表格数据体验一下几行代码搞定Excel半天活的快感。安装终端输入pip install pandas回车。敲这些代码试试import pandas as pd 创建DataFrame数据表 data { 姓名: [张三, 李四, 王五, 赵六, 钱七], 年龄: [25, 30, 22, 28, 35], 城市: [北京, 上海, 广州, 深圳, 杭州], 工资: [8000, 12000, 7000, 15000, 10000] } df pd.DataFrame(data) print(df) 输出 姓名 年龄 城市 工资 0 张三 25 北京 8000 1 李四 30 上海 12000 2 王五 22 广州 7000 3 赵六 28 深圳 15000 4 钱七 35 杭州 10000 基本操作 print(\n前3行) print(df.head(3)) print(\n基本信息) print(df.info()) print(\n统计摘要) print(df.describe()) 筛选数据 print(\n年龄大于25岁的) print(df[df[年龄] 25]) print(\n工资大于10000的) print(df[df[工资] 10000]) 多个条件用 与、|或每个条件要加括号 print(\n年龄大于25且工资大于10000的) print(df[(df[年龄] 25) (df[工资] 10000)]) 排序 print(\n按工资降序排列) print(df.sort_values(工资, ascendingFalse)) 分组统计 print(\n按城市分组统计平均工资) print(df.groupby(城市)[工资].mean()) 添加新列 df[税后工资] df[工资] * 0.8 df[年龄分组] df[年龄].apply(lambda x: 青年 if x 30 else 中年) print(\n添加新列后) print(df) 读取和保存 保存为CSV df.to_csv(员工数据.csv, indexFalse, encodingutf-8-sig) print(\n已保存为 员工数据.csv) 读取CSV df2 pd.read_csv(员工数据.csv) print(\n重新读取的CSV文件) print(df2)重点理解DataFrame是Pandas最核心的数据结构你可以把它想象成一个超级加强版的Excel表格。df[条件] 是最常用的筛选方式多个条件用 且和 |或连接每个条件必须用括号包起来。groupby 分组统计是数据分析的利器分组后可以调用 mean()、sum()、count() 等聚合函数。apply 方法可以对某一列的每个值应用一个函数非常灵活。今天的练习从网上找一份公开的CSV数据或者自己造一份用Pandas读取并查看前10行。按某一列进行分组统计每组的数量、平均值等。筛选出满足特定条件的数据导出为新的CSV文件。第17天Matplotlib和Seaborn——数据可视化今天要做什么学会把数据画成好看的图表以后做汇报再也不用愁图怎么画了。安装终端输入pip install matplotlib seaborn回车。敲这些代码试试import matplotlib.pyplot as plt import seaborn as sns import numpy as np 设置中文字体 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False 1. 基础折线图 x [1, 2, 3, 4, 5] y [2, 4, 6, 8, 10] plt.figure(figsize(8, 5)) plt.plot(x, y, markero, linestyle--, colorb, labely2x) plt.title(基础折线图, fontsize16) plt.xlabel(X轴, fontsize12) plt.ylabel(Y轴, fontsize12) plt.legend() plt.grid(True, alpha0.3) plt.show() 2. 多线对比 x np.linspace(0, 10, 100) y1 np.sin(x) y2 np.cos(x) plt.figure(figsize(10, 5)) plt.plot(x, y1, labelsin(x), colorred, linewidth2) plt.plot(x, y2, labelcos(x), colorblue, linewidth2, linestyle--) plt.title(正弦和余弦曲线, fontsize16) plt.xlabel(x, fontsize12) plt.ylabel(y, fontsize12) plt.legend() plt.grid(True, alpha0.3) plt.show() 3. 柱状图 categories [苹果, 香蕉, 橘子, 葡萄, 西瓜] values [30, 45, 25, 50, 35] plt.figure(figsize(8, 5)) bars plt.bar(categories, values, color[#FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7]) plt.title(水果销量统计, fontsize16) plt.xlabel(水果种类, fontsize12) plt.ylabel(销量吨, fontsize12) for bar, value in zip(bars, values): plt.text(bar.get_x() bar.get_width()/2, bar.get_height() 0.5, str(value), hacenter, fontsize10) plt.show() 4. 饼图 labels [Python, JavaScript, Java, C, 其他] sizes [35, 25, 20, 12, 8] colors [#FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7] explode (0.1, 0, 0, 0, 0) plt.figure(figsize(8, 8)) plt.pie(sizes, explodeexplode, labelslabels, colorscolors, autopct%1.1f%%, shadowTrue, startangle90) plt.title(编程语言受欢迎程度, fontsize16) plt.axis(equal) plt.show() 5. 散点图 np.random.seed(42) x np.random.randn(100) y 2 * x np.random.randn(100) * 0.5 plt.figure(figsize(8, 5)) plt.scatter(x, y, alpha0.6, cx, cmapviridis, s50) plt.colorbar(label颜色映射) plt.title(散点图示例, fontsize16) plt.xlabel(X, fontsize12) plt.ylabel(Y, fontsize12) plt.grid(True, alpha0.3) plt.show() 6. 子图布局 fig, axes plt.subplots(2, 2, figsize(12, 10)) x np.linspace(0, 10, 100) axes[0, 0].plot(x, np.sin(x), colorred) axes[0, 0].set_title(sin(x)) axes[0, 1].plot(x, np.cos(x), colorblue) axes[0, 1].set_title(cos(x)) axes[1, 0].plot(x, np.exp(-x/2) * np.sin(x), colorgreen) axes[1, 0].set_title(衰减振荡) axes[1, 1].plot(x, x**2, colorpurple) axes[1, 1].set_title(抛物线) plt.tight_layout() plt.show() 7. Seaborn风格美化 sns.set_theme(stylewhitegrid) tips sns.load_dataset(tips) plt.figure(figsize(10, 6)) sns.boxplot(datatips, xday, ytotal_bill, paletteSet2) plt.title(各天消费金额分布, fontsize16) plt.xlabel(星期, fontsize12) plt.ylabel(消费金额美元, fontsize12) plt.savefig(箱线图.png, dpi150, bbox_inchestight) plt.show()重点理解Matplotlib是Python最基础的绘图库功能强大但语法稍微繁琐。Seaborn在Matplotlib基础上做了封装统计图表更美观代码也更简洁。中文字体问题是个常见坑需要手动设置 plt.rcParams[font.sans-serif]如果你的电脑上没有SimHei换成你系统里有的中文字体名。plt.savefig() 可以把图保存为图片dpi 控制清晰度bbox_inchestight 可以去掉多余的白边。今天的练习用第16天创建的员工数据画一个柱状图展示每个人的工资。用Seaborn画一个箱线图按城市分组展示工资分布。把上面任意一张图保存为高清PNG插入到一个Word文档里看看效果。第18天爬虫入门——自动收集信息今天要做什么学会用requests获取网页内容用BeautifulSoup解析网页提取你想要的信息。安装终端输入pip install requests beautifulsoup4回车。敲这些代码试试import requests from bs4 import BeautifulSoup import time 1. 基础GET请求 url https://httpbin.org/get response requests.get(url) print(f状态码{response.status_code}) print(f响应内容{response.text[:200]}...) 2. 带参数的请求 params {name: 小明, age: 25} response requests.get(https://httpbin.org/get, paramsparams) data response.json() print(f请求参数{data[args]}) 3. POST请求 data {username: admin, password: 123456} response requests.post(https://httpbin.org/post, datadata) print(fPOST响应{response.json()[form]}) 4. 设置请求头 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept-Language: zh-CN,zh;q0.9, } response requests.get(https://httpbin.org/headers, headersheaders) print(f请求头{response.json()[headers]}) 5. 解析HTML html 我的第一个爬虫 第一段文字 第二段文字 点我访问 soup BeautifulSoup(html, html.parser) print(f标题{soup.h1.text}) print(f所有段落{[p.text for p in soup.find_all(p)]}) print(f链接{soup.a[href]}) 6. 爬取真实网页 url https://httpbin.org/html response requests.get(url, headersheaders, timeout10) soup BeautifulSoup(response.text, html.parser) print(f页面标题{soup.title.text if soup.title else 无标题}) 7. 带超时和异常处理 try: response requests.get(https://httpbin.org/delay/3, timeout5) print(请求成功) except requests.Timeout: print(请求超时) except requests.ConnectionError: print(网络连接失败) 8. 处理JSON API try: response requests.get(https://httpbin.org/json, headersheaders, timeout10) data response.json() print(f获取到的JSON数据{data}) except Exception as e: print(f爬取出错{e})重点理解requests.get() 是最常用的方法返回一个Response对象里面包含状态码、响应头、内容等。一定要设置User-Agent请求头不然很多网站会拒绝你的请求因为默认的User-Agent一看就是Python脚本。BeautifulSoup用来解析HTMLfind_all() 按标签名找select() 用CSS选择器找两种方式都很常用。爬虫一定要遵守网站的robots协议不要高频爬取不要爬隐私数据添加 time.sleep() 控制频率做一个有礼貌的爬虫。今天的练习用requests获取任意一个网页打印出状态码和响应头的Content-Type。用BeautifulSoup解析一个包含表格的HTML把表格数据提取出来存成列表。试着爬取一个你感兴趣的公开网页比如新闻列表提取出标题和链接保存到本地文件。第19天Flask——搭一个自己的网站今天要做什么用几行Python代码搭一个网站在浏览器里访问你自己的网页。安装终端输入pip install flask回车。敲这些代码试试# 新建一个文件叫 app.py把以下代码全部复制进去然后运行 from flask import Flask, render_template_string, request app Flask(name) 1. 最简单的路由 app.route(/) def home(): return h1欢迎来到我的第一个Flask应用/h1p这是首页/p 2. 带参数的路由 app.route(/user/name) def user(name): return fh1你好{name}/h1 3. 返回HTML模板 app.route(/hello) def hello(): html !DOCTYPE html html headtitleFlask示例/title/head body h1Hello, Flask!/h1 p这是用Flask渲染的HTML页面/p /body /html return html 4. 处理表单提交 app.route(/form, methods[GET, POST]) def form(): if request.method POST: name request.form.get(name, ) return fh1提交成功你好{name}/h1 html form methodPOST input typetext namename placeholder请输入你的名字 button typesubmit提交/button /form return html 5. 使用模板字符串 app.route(/blog/int:post_id) def blog_post(post_id): posts { 1: {title: 第一篇博客, content: 这是第一篇博客的内容}, 2: {title: 第二篇博客, content: 这是第二篇博客的内容}, } post posts.get(post_id) if not post: return h1404 - 文章不存在/h1, 404 html f h1{post[title]}/h1 p{post[content]}/p a href/返回首页/a return html 6. 静态文件路由 app.route(/about) def about(): return render_template_string( h1关于本站/h1 p这是一个用Flask搭建的简单网站/p p技术栈Python Flask/p ) 7. 综合示例简易博客 posts [] app.route(/blog) def blog_list(): html h1博客列表/h1ul for i, post in enumerate(posts, 1): html flia href/blog/{i}{post[title]}/a/li html /ula href/blog/new写新文章/a return html app.route(/blog/new, methods[GET, POST]) def blog_new(): if request.method POST: title request.form.get(title, ) content request.form.get(content, ) posts.append({title: title, content: content}) return h1发布成功/h1a href/blog返回博客列表/a form_html form methodPOST input typetext nametitle placeholder文章标题br textarea namecontent placeholder文章内容/textareabr button typesubmit发布/button /form return form_html if name main: print(博客已启动在浏览器打开 http://127.0.0.1:5000) app.run(debugTrue, port5000)重点理解app.route(/) 是装饰器告诉Flask当用户访问这个路径时执行下面的函数。int:post_id 是动态路由URL里的数字会被自动提取出来传给函数。request.method 判断是GET请求看页面还是POST请求提交表单。redirect(url_for(...)) 实现页面跳转。debugTrue 开启调试模式代码改了会自动重启方便开发。今天的练习把上面的代码跑起来在浏览器打开 http://127.0.0.1:5000浏览首页、点文章、写文章。给博客加一个关于我页面显示你的自我介绍。试着改一下CSS样式把博客改成你喜欢的颜色和布局。第20天SQLite数据库——让数据持久化今天要做什么学会用数据库存取数据告别文件读写的原始时代。不需要安装SQLite是Python自带的直接 import sqlite3 就能用。敲这些代码试试import sqlite3 连接数据库如果不存在会自动创建 conn sqlite3.connect(example.db) cursor conn.cursor() print(数据库连接成功) 1. 创建表 cursor.execute( CREATE TABLE IF NOT EXISTS students ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, score REAL, city TEXT ) ) print(表创建成功) 2. 插入单条数据 cursor.execute( INSERT INTO students (name, age, score, city) VALUES (?, ?, ?, ?), (小明, 20, 95.5, 北京) ) conn.commit() print(插入单条数据成功) 3. 批量插入数据 students_data [ (小红, 22, 88.0, 上海), (小刚, 21, 92.5, 广州), (小丽, 23, 78.5, 深圳), (小强, 20, 85.0, 杭州), (小美, 22, 96.0, 北京), ] cursor.executemany( INSERT INTO students (name, age, score, city) VALUES (?, ?, ?, ?), students_data ) conn.commit() print(f批量插入{len(students_data)}条数据成功) 4. 查询所有数据 cursor.execute(SELECT * FROM students) rows cursor.fetchall() print(\n 所有学生信息 ) for row in rows: print(fID: {row[0]}, 姓名: {row[1]}, 年龄: {row[2]}, 成绩: {row[3]}, 城市: {row[4]}) 5. 条件查询 cursor.execute(SELECT * FROM students WHERE score 90) high_scores cursor.fetchall() print(f\n成绩大于90分的学生{len(high_scores)}人) for row in high_scores: print(f{row[1]} - {row[3]}分) 6. 聚合查询 cursor.execute( SELECT city, COUNT(*) as 人数, AVG(score) as 平均分 FROM students GROUP BY city ) stats cursor.fetchall() print(\n 各城市统计 ) for row in stats: print(f{row[0]}: {row[1]}人, 平均分{row[2]:.1f}) 7. 更新数据 cursor.execute(UPDATE students SET score 100 WHERE name ?, (小明,)) conn.commit() print(\n小明成绩已更新为100分) 8. 删除数据 cursor.execute(DELETE FROM students WHERE score 80) conn.commit() print(已删除成绩低于80分的学生记录) 9. 验证最终数据 cursor.execute(SELECT * FROM students) print(\n 最终数据库内容 ) for row in cursor.fetchall(): print(row) 关闭连接 conn.close() print(\n数据库连接已关闭)重点理解SQLite是嵌入式数据库数据存成一个 .db 文件不需要安装数据库服务器非常适合小型项目。SQL语句是操作数据库的标准语言SELECT查、INSERT增、UPDATE改、DELETE删这四种操作叫CRUD。用 ? 做占位符可以防止SQL注入攻击绝对不要用字符串拼接来构造SQL语句。conn.commit() 很重要增删改操作之后必须提交否则数据不会保存。今天的练习创建一个图书管理数据库包含图书表书名、作者、价格、库存。插入5本书的数据然后查询价格大于30元的书。把第19天的博客程序改一下用SQLite替代内存列表存储文章数据。第21天数据分析实战——完整项目今天要做什么走一遍完整的数据分析流程获取数据→清洗→分析→可视化→写报告。安装如果前面都装了就不用再装检查一下pip install pandas matplotlib seaborn是否都已安装。敲这些代码试试import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns 设置中文字体 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False 1. 生成模拟数据实际项目中换成真实数据 np.random.seed(42) n 500 data { 年龄: np.random.randint(18, 65, n), 工资: np.random.randint(4000, 30000, n), 工作经验年: np.random.randint(0, 30, n), 学历: np.random.choice([高中, 本科, 硕士, 博士], n, p[0.2, 0.5, 0.2, 0.1]), 城市: np.random.choice([北京, 上海, 广州, 深圳, 杭州], n), 部门: np.random.choice([技术, 市场, 销售, 人事, 财务], n), } df pd.DataFrame(data) 让工资与工作经验和学历有一定相关性 df[工资] df[工资] df[工作经验年] * 300 df.loc[df[学历] 硕士, 工资] 3000 df.loc[df[学历] 博士, 工资] 6000 df.loc[df[学历] 高中, 工资] - 2000 故意加一些缺失值和异常值模拟真实数据 mask np.random.random(n) 0.05 df.loc[mask, 工资] np.nan # 5%的数据工资缺失 mask2 np.random.random(n) 0.02 df.loc[mask2, 工资] 999999 # 2%的异常值 print( * 50) print(数据分析实战员工工资分析) print( * 50) 2. 数据清洗 print(f\n原始数据量{len(df)}行) print(f缺失值情况\n{df.isnull().sum()}) 处理异常值工资不可能超过10万 df.loc[df[工资] 100000, 工资] np.nan 处理缺失值用中位数填充 median_salary df[工资].median() df[工资].fillna(median_salary, inplaceTrue) print(f\n清洗后数据量{len(df)}行) print(f缺失值情况\n{df.isnull().sum()}) 3. 描述性统计 print(\n 工资统计摘要 ) print(df[工资].describe()) 4. 分组分析 print(\n 各学历平均工资 ) edu_salary df.groupby(学历)[工资].agg([mean, median, count]) edu_salary.columns [平均工资, 中位数工资, 人数] edu_salary[平均工资] edu_salary[平均工资].round(0).astype(int) print(edu_salary) print(\n 各城市平均工资 ) city_salary df.groupby(城市)[工资].mean().sort_values(ascendingFalse).round(0).astype(int) print(city_salary) print(\n 各部门平均工资 ) dept_salary df.groupby(部门)[工资].mean().sort_values(ascendingFalse).round(0).astype(int) print(dept_salary) 5. 可视化 fig, axes plt.subplots(2, 2, figsize(14, 10)) 图1学历与工资的箱线图 sns.boxplot(datadf, x学历, y工资, paletteSet2, axaxes[0, 0]) axes[0, 0].set_title(不同学历的工资分布, fontsize14) axes[0, 0].set_xlabel(学历) axes[0, 0].set_ylabel(工资元) 图2工作经验与工资的散点图 sns.scatterplot(datadf, x工作经验年, y工资, hue学历, alpha0.6, axaxes[0, 1]) sns.regplot(datadf, x工作经验年, y工资, scatterFalse, colorgray, axaxes[0, 1]) axes[0, 1].set_title(工作经验与工资的关系, fontsize14) 图3各城市平均工资柱状图 city_salary.plot(kindbar, axaxes[1, 0], color[#FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7]) axes[1, 0].set_title(各城市平均工资, fontsize14) axes[1, 0].set_xlabel(城市) axes[1, 0].set_ylabel(平均工资元) axes[1, 0].tick_params(axisx, rotation0) 图4工资分布直方图 axes[1, 1].hist(df[工资], bins30, color#4ECDC4, edgecolorwhite, alpha0.8) axes[1, 1].axvline(df[工资].mean(), colorred, linestyle--, labelf平均值{df[工资].mean():.0f}) axes[1, 1].axvline(df[工资].median(), colororange, linestyle--, labelf中位数{df[工资].median():.0f}) axes[1, 1].set_title(工资分布直方图, fontsize14) axes[1, 1].set_xlabel(工资元) axes[1, 1].set_ylabel(人数) axes[1, 1].legend() plt.tight_layout() plt.savefig(工资分析报告.png, dpi150, bbox_inchestight) plt.show() 6. 输出分析结论 print(\n * 50) print(分析结论) print( * 50) print(f1. 样本共{len(df)}名员工平均工资{df[工资].mean():.0f}元中位数{df[工资].median():.0f}元) print(f2. 学历越高工资越高博士平均工资最高高中最低) print(f3. 工资最高城市{city_salary.index[0]}{city_salary.iloc[0]}元) print(f4. 工资最高部门{dept_salary.index[0]}{dept_salary.iloc[0]}元) print(f5. 工作经验每增加1年工资平均增长约300元) print(\n分析报告已保存为 工资分析报告.png)重点理解数据分析的标准流程获取数据→数据清洗→探索性分析→可视化→得出结论。数据清洗占了数据分析70%以上的时间缺失值、异常值、重复值都要处理。groupby 聚合函数是最常用的分析手段能快速看出不同分组的差异。可视化不是画完就完了要能从中读出信息比如上面的箱线图能看出学历越高工资越高散点图能看出工作经验越长工资越高。今天的练习去Kaggle或天池找一份真实的公开数据集用Pandas读取并清洗。做至少三种分组分析比如按性别、按年龄段、按地区分别画图。写一个简短的文字分析报告总结你从数据中发现了什么。完成这个项目第三阶段通关你已经完整走了一遍数据分析流程这套技能放到简历上就是实打实的加分项。第四阶段学点程序员的规矩第2226天前面你写的代码可能比较野路子这个阶段咱们学一些正规军的操作让你的项目更规范、更靠谱。第22天Git和GitHub——代码版本管理今天要做什么学会用Git管理代码版本把代码传到GitHub上。安装Git去 git-scm.com 下载安装。装好之后在终端输入git --version验证。具体操作先配置你的身份第一次用Git必须做这一步git config --global user.name 你的名字 git config --global user.email 你的邮箱example.com # 查看配置是否生效 git config --list 1. 初始化仓库 # 进入你的项目文件夹 cd 你的项目文件夹路径 初始化Git仓库会在当前文件夹生成一个隐藏的 .git 文件夹 git init 查看仓库状态红色表示未跟踪的文件 git status 2. 添加文件到暂存区 # 添加单个文件 git add 文件名.py 添加所有文件用 . 表示当前目录下所有文件 git add . 添加指定类型的文件 git add *.py 再次查看状态文件变成绿色表示已暂存 git status 3. 提交到本地仓库 # 提交暂存区的文件-m 后面写本次提交的说明 git commit -m 第一次提交初始化项目 如果忘了写 -m会进入vim编辑器按 i 输入说明按 Esc 后输入 :wq 保存退出 查看提交历史 git log 简洁版提交历史一行一 4. 把代码推到GitHub上 # 1. 去 github.com 注册一个账号然后点右上角 号新建一个仓库 # 仓库名填 python-learning选 Public公开不要勾选 README然后点创建 2. 创建完后GitHub会给你一段推送命令类似下面这样 git remote add origin https://github.com/你的用户名/python-learning.git git branch -M main git push -u origin main 3. 在终端里依次执行这三行输入你的GitHub用户名和密码或Token 如果提示让你登录按照提示操作就行 4. 刷新GitHub页面看到你的代码已经传上去了恭喜你 5. 日常提交三步走 # 以后每次写完新代码就执行这三步 git add . git commit -m 写清楚你这次做了什么 git push origin main重点理解git remote add origin是把本地仓库和远程仓库连上线。git push是把本地提交推送到GitHub-u是第一次推送时用的以后直接git push就行。养成小步快跑的习惯每完成一个小功能就commit一次别攒到最后一次性提交。commit message要写清楚比如第8天完成Student类和继承练习别写什么update、fix bug这种没意义的。今天的练习把前面21天写的所有代码整理到一个文件夹里初始化Git提交至少5个commit每个commit写清楚说明。注册GitHub把代码推上去然后在浏览器里确认能看到你的文件。在本地新建一个分支git checkout -b test-branch改一行代码提交然后切换回main分支看看刚才的改动还在不在。总结与展望到这里你已经完成了Python 30天学习计划中从第16天到第22天的核心内容。从Pandas数据处理、Matplotlib可视化、爬虫入门、Flask建站、SQLite数据库到数据分析实战和Git版本管理你掌握了一套完整的Python实战技能栈。这些知识不仅能帮你独立完成数据分析项目、搭建小型Web应用还能用Git规范地管理代码版本为后续更深入的学习打下坚实基础。接下来的第23天到第26天你将继续学习单元测试、虚拟环境、AI辅助编程等进阶内容让你的Python开发流程更加专业和高效。坚持每天动手敲代码、完成练习30天后你一定会惊讶于自己的成长。加油你已经走在正确的路上了