【限时特惠】小白玩转Python数据分析_哔哩哔哩_bilibili
PyCharm 安装完成与 Python 下载
Section titled “PyCharm 安装完成与 Python 下载”- PyCharm 软件较大,安装需等待一段时间,完成后点击完成关闭安装窗口。
- 接下来打开 PyCharm。
- 非 Windows 系统可跳过此视频。
- 从官方渠道下载 Python 解释器和 PyCharm:搜索 Python 官网,找到带官方标签的网页点进去。
下载并安装 Python 解释器
Section titled “下载并安装 Python 解释器”-
访问官网:在浏览器地址栏直接输入
www.python.org进入官网。 -
自动识别系统:官网会自动检测当前操作系统版本(如 Windows),确保下载的安装包与系统匹配。
-
开始下载:
- 在导航栏点击 Downloads。
- 页面会自动推荐适合当前系统的版本,点击页面上的大黄色按钮即可开始下载安装程序。
安装 Python 解释器的关键设置
Section titled “安装 Python 解释器的关键设置”- 版本兼容性:下载版本号不必完全一致,只要是 3 开头的版本即可正常使用。
- 添加环境变量(至关重要):
- 在安装界面务必勾选 Add Python to PATH。
- 作用:将 Python 路径添加到系统环境变量中,使操作系统能够识别并定位 Python 的安装位置。
- 完成安装:勾选后点击 Install Now 开始安装,等待进度条走完即可。
- 路径长度限制:安装完成后,若出现 Disable path length limit 的提示,建议点击该选项以解除 Windows 对路径长度的限制。
测试 Python 安装
Section titled “测试 Python 安装”-
点击 close 关闭安装窗口。
-
验证安装成功:
- 在菜单栏搜索 CNB 进入命令提示符。
- 输入 Python(全大写)并回车。
- 若显示 Python 后跟安装版本及一串杂乱文字,说明电脑已有 Python。
-
接下来安装 Python:搜索 Python 官网,确认网址
www.jetbrings.com-python,然后找 downloads。
PyCharm 安装与配置
Section titled “PyCharm 安装与配置”选择 PyCharm 版本
Section titled “选择 PyCharm 版本”- PyCharm 提供两个版本:
- Professional (专业版):收费,功能更全面。
- Community (社区版):免费,对于纯 Python 开发已完全足够。
下载与安装步骤
Section titled “下载与安装步骤”- 在官网下载页面向下滚动,找到 Community Edition 进行下载。
- 运行安装程序后,按照指引点击“下一步”选择安装路径。
- 安装选项设置(建议根据需求勾选):
- 桌面图标:方便快速启动。
- 关联文件:将所有 Python 文件(.py)默认设置为通过 PyCharm 打开。
PyCharm 初次启动与环境配置
Section titled “PyCharm 初次启动与环境配置”- 首次打开 PyCharm,弹出语言和地区选择窗口,默认匹配操作系统(如中文)。
- 非中文系统无妨,后续可设置成中文。
- 点击下一个,同意用户协议(Terms)继续。
PyCharm 首次启动
Section titled “PyCharm 首次启动”- 首次启动时询问是否导入配置,无需则直接跳过。
- Windows上PyCharm初始化完成,可创建项目并编写代码。
- 打开PyCharm,若先前设置了语言和地区,可能已为中文界面。
PyCharm 界面语言设置
Section titled “PyCharm 界面语言设置”-
若界面默认为英文,可通过设置将其更改为中文:
- 在欢迎页面点击左下角的设置图标(齿轮图标)。
- 选择 Preferences(Windows 系统下为 Settings)。
- 在左侧菜单中找到并点击 Plugins(插件)。
- 若未直接显示,可在左上角的搜索框中输入
plugins进行查找。 - 在插件页面的搜索框内输入
chinese,即可找到中文语言包并进行安装。
界面语言插件配置与激活
Section titled “界面语言插件配置与激活”-
若在 Marketplace 中无法搜索到中文语言包,说明插件可能已被默认安装。
-
检查已安装插件:
- 点击插件窗口顶部的 Installed 标签页。
- 若插件显示为灰色(禁用状态),勾选该插件。
- 点击右下角的 Apply 和 OK 按钮以激活设置。
-
语言切换生效:
- 激活后,重新进入设置菜单(Windows 为 Settings,macOS 为 Preferences)。
- 在搜索框中输入
language即可进行后续的语言环境管理。
PyCharm 界面变更为中文与新建项目
Section titled “PyCharm 界面变更为中文与新建项目”-
重启后,往上滑动找到 Language and Region 栏,选择 中文,点击 OK 并 Restart。
-
页面语言变为中文。
-
创建项目集中管理代码文件:
- 欢迎页面点击 新建项目。
- 第一行表示项目文件夹位置,可换成好找的路径。
项目文件夹管理规范
Section titled “项目文件夹管理规范”- 在创建项目时,必须先在目标位置(如桌面)手动创建一个空文件夹,再将其选为项目路径。
- 若直接选择桌面作为项目根目录,PyCharm 会将整个桌面视为项目文件夹,导致文件混乱。
- 项目文件夹应仅用于存放与该项目直接相关的代码文件、素材等,严禁混入个人无关文件(如身份证照片、论文等)。
解释器与虚拟环境配置
Section titled “解释器与虚拟环境配置”- 解释器类型:默认选择项目虚拟环境(venv)。
- PyCharm 会自动检测电脑上安装的 Python 版本。
- 若安装了多个版本,可通过下拉菜单手动选择所需的 Python 版本。
- 项目创建:配置完成后点击“创建”,PyCharm 会自动生成项目结构,包含
venv等系统文件夹,用于隔离项目依赖。
理解项目虚拟环境 (venv)
Section titled “理解项目虚拟环境 (venv)”- venv 的作用:
- PyCharm 自动创建的
venv文件夹代表该项目的独立 Python 虚拟环境。 - 核心目的是实现项目隔离,让不同项目可以使用不同的 Python 解释器版本及第三方库,互不干扰。
- PyCharm 自动创建的
- 管理规范:
- 该文件夹及其内部内容(如
bin,lib等)严禁手动移动、删除或修改。 - 不要向此文件夹内添加任何无关文件。
- 该文件夹及其内部内容(如
- 进阶意义:
- 能够配置并理解虚拟环境,意味着已掌握了开发环境设置这一高门槛步骤,领先了 99% 的初学者。
- 后续创建新项目时,只需重复相同的步骤即可。
在 PyCharm 中创建并编写 Python 文件
Section titled “在 PyCharm 中创建并编写 Python 文件”-
在项目文件夹中创建代码文件:
- 在左侧项目目录树中,右键点击项目文件夹。
- 选择 新建 (New) > Python 文件 (Python File)。
- 输入文件名(例如
hello),PyCharm 会自动添加.py后缀,回车确认即可进入编辑区域。
代码编写与错误提示
Section titled “代码编写与错误提示”- 实时检查机制:PyCharm 会在编写过程中自动进行语法检查。
- 若代码存在拼写错误或语法问题,PyCharm 会自动用红色波浪线标记该处,提供即时反馈,帮助开发者在运行前修正错误。
计算机指令的本质
Section titled “计算机指令的本质”- 编程的本质是给计算机下指令。
- 只要拥有权限且指令符合计算机的逻辑规则,计算机就会严格按照编写的逻辑执行任务。
打印输出指令 print
Section titled “打印输出指令 print”- 使用
print()函数可以在屏幕上显示指定的文本内容。- 语法示例:
print("Dad!!")
- 语法示例:
- 函数组成部分:
print:代表打印(输出)指令。():圆括号用于存放需要打印的具体内容。- 若内容置于括号外,程序将无法识别并可能报错。
"":引号用于包裹字符串,标识这是需要打印的文本。
- 注意事项:
- 必须使用英文半角括号和引号,使用中文全角符号会导致程序无法运行。
- 编程语言对字符敏感,大小写和符号格式需严格遵循规范。
编程中的标点符号规范
Section titled “编程中的标点符号规范”-
编程语言仅识别英文半角标点,使用中文全角符号会导致程序无法运行。
-
中英文标点在视觉上非常相似,需特别注意区分:
| 符号类型 | 中文全角 | 英文半角 |
| –––– | –––– | –––– |
| 括号 | () | () |
| 逗号 | , | , |
| 分号 | ; | ; |
| 方括号 | [] | [] |
-
编程时应及时切换输入法至英文模式。
字符串引号的使用
Section titled “字符串引号的使用”- 在
print()函数中,包裹文本内容的引号既可以使用单引号' ',也可以使用双引号" "。 - 引号的作用类似于书面写作中的引用功能,用于明确区分“需要打印的原始文本”与“程序指令”。
- 无论使用哪种引号,必须确保成对出现,且同样必须为英文半角符号。
字符串与引号规则
Section titled “字符串与引号规则”- 字符串定义:被引号包裹的内容(如
"Dad!!")被视为字符串,即一串文本。 - 引号的作用:
- 明确标识文本内容,防止计算机将其误认为是变量或指令。
- 即使引号内包含中文或标点符号,程序也能正常处理。
- 符号规范:
- 必须使用英文半角引号和括号。使用中文全角符号会导致程序无法识别。
- 即使字符串内包含中文,外层的引号与括号仍需保持英文格式。
- 数字作为字符串:
- 若数字被引号包裹(如
"666"),计算机会将其视为字符串(文本)而非数值,从而避免计算逻辑错误。
- 若数字被引号包裹(如
开始实践:打印字符串
Section titled “开始实践:打印字符串”- 现在实践打印字符串“666”(字符串,非数字)。
- 双击打开之前创建的项目。
- 在项目文件夹中编写
print("666")。
Python 文件创建最佳实践
Section titled “Python 文件创建最佳实践”- 文件存放位置:选择项目根目录创建Python文件,避免放入
venv文件夹,因为venv用于虚拟环境,与代码应分开。 - 命名规范:文件名避免空格,后缀必须为
.py,以便Python解释器识别。
文件命名规范与注意事项
Section titled “文件命名规范与注意事项”- 推荐命名:使用英文、数字和下划线(
_),这能避免因文件名包含特殊字符或 Emoji 而导致的路径识别问题。 - 避免使用:特殊符号(如 Emoji、中文字符、空格等),以确保系统在读取文件时不会出现无法定位的问题。
创建 Python 文件后的初始配置
Section titled “创建 Python 文件后的初始配置”- Git 初始化弹窗:
- 首次创建文件时,PyCharm 可能会弹出询问是否将文件添加到 Git 版本控制的窗口。
- 操作建议:在入门阶段,若弹出此窗口,可直接选择“不再询问”并点击“取消”,无需在当前阶段处理 Git 相关配置。
- 代码执行:在文件内输入代码后,点击回车即可确认创建。
- 代码实践:在编辑器中输入
print("666")以完成字符串打印练习。
PyCharm 自动补全与运行代码
Section titled “PyCharm 自动补全与运行代码”- 输入
print或pr等小写时,PyCharm 提供自动补全提示(显示包含 “pr” 的关键词,如print)。 - 完整语法:
print("内容")- 添加 `()` 和一对 `""`,内写要打印的内容。- 运行代码:
- 右键编辑区,选择运行。
- 下方运行窗口显示结果。
运行结果分析与调试
Section titled “运行结果分析与调试”- 程序执行反馈:
- 运行代码后,PyCharm 会在下方运行窗口展示输出结果。
- 第一行通常显示系统自动触发的运行指令(包含解释器路径)。
- 最后一行显示退出代码(如
Process finished with exit code 0)。
- 退出代码含义:
0:表示程序运行成功,没有出现错误。- 非零数字:表示程序运行过程中出现错误。
- 调试建议:
- 运行窗口中的系统指令和退出代码由 PyCharm 自动生成,日常编写代码时可忽略,重点关注第一行和最后一行之间的输出内容。
- 若代码报错,检查重点应放在
print()函数内部的字符串定义及其符号规范上。
中文括号错误示例
Section titled “中文括号错误示例”- 右键运行:选择代码右键运行,成功打印输出。
- 语法错误触发:使用中文括号(如
print("妈")),编辑器显示红色波浪线实时提醒。 - 运行反馈:窗口显示红色错误提示(如
SyntaxError),退出代码为非零数字。 - 排查方法:不确定问题时,检查编辑器红色高亮处修正。
字符串高级操作
Section titled “字符串高级操作”字符串拼接 (Concatenation)
Section titled “字符串拼接 (Concatenation)”- 字符串可以通过
+号连接,将多个字符串合并为一个更长的字符串。 - 拼接逻辑:
print("Hello" + " " + "world" + "!")- 拼接时,计算机严格按照顺序执行,不会自动添加空格。- 若要在拼接的词之间保留空格,必须在字符串内部显式包含空格(如 `" "`)。单双引号转义与跨行字符串
Section titled “单双引号转义与跨行字符串”- 字符串不仅可以拼接,还支持更复杂的处理方式,如单双引号的嵌套使用(转义)以及处理跨行文本。
- 灵活运用引号可以避免程序将字符串内容误识别为代码指令。
字符串内嵌引号的解析错误
Section titled “字符串内嵌引号的解析错误”- 字符串内容本身包含引号时,需注意内外引号类型匹配。
- 错误示例:
print("黑SAT"good")- Python 将第一个和第二个引号配对,认为**“黑SAT”**是完整字符串结束。
- 后续
good和剩余引号被视为无效代码,导致语法错误(SyntaxError)。
字符串引号嵌套与转义
Section titled “字符串引号嵌套与转义”- 引号嵌套规则:
- 若字符串内部需要包含引号,可通过外层使用不同类型的引号来避免冲突。
- 例如:
print('He said "good!"')使用外层单引号包裹,内部的双引号即被视为普通字符,不会导致语法错误。
- 反斜杠转义 (Escape Character):
- 当字符串内部必须使用与外层相同的引号时,可在该引号前添加反斜杠 ``。
- 作用:告诉计算机该引号仅为普通字符,而非字符串的结束标志。
- 示例:
print("He said \"Let's go!\"")- 在此例中,`\"` 明确表示双引号是文本内容的一部分,防止程序提前终止字符串解析。转义符打印效果与换行规则
Section titled “转义符打印效果与换行规则”- 打印效果:转义后的字符串原样输出,包括反斜杠后的引号。
- 示例输出:
He said let's go(斜杠后引号保持不变)。
- 示例输出:
- 换行规则:Python 逐行读取执行,一句代码不能随意换行。
- 错误原因:行末未闭合引号或括号,解释器误认为语句中断,导致语法错误。
- 示例:字符串中直接换行会报错。
使用 \n 实现字符串换行
Section titled “使用 \n 实现字符串换行”- 若需在字符串中强制换行,可在换行位置插入
\n。- 示例:
print("Hello!\nHi!")会在输出中将Hi!打印在第二行。
- 示例:
\n中的反斜杠是转义符的另一种用法,用于指示后续字符(n)代表换行指令而非普通字母。
三引号实现跨行字符串
Section titled “三引号实现跨行字符串”- 当需要打印多行文本(如诗歌)时,使用
\n或多个print语句会显得繁琐。 - 使用三引号(
'''或""")可以包裹跨行字符串,直接保留代码中的换行格式。- 示例:
print('''君不见,黄河之水天上来, 奔流到海不复回。''')- 三引号不仅支持跨行,也解决了内部引号嵌套的冲突问题,是处理长文本或复杂格式字符串的推荐方案。
字符串实践环节
Section titled “字符串实践环节”实践开始:字符串连接示例
Section titled “实践开始:字符串连接示例”- 进入实践:在之前项目中新建空白 Python 文件。
- 示例代码:使用
print(),括号内放置多个字符串,中间用+连接。 - 重点:字符串连接 通过加号实现多字符串合并。
字符串连接与代码格式化
Section titled “字符串连接与代码格式化”- 字符串连接的空格处理:
- 拼接字符串时,Python 不会自动添加空格。若需在连接处保留间距,需在字符串内部手动添加空格。
- 示例:
print("你好" + " " + "这是一句代码")。
- 代码中的空格规范:
- 操作符(如
+)两端的空格是可选的,但添加空格可以提高代码的可读性,使排版更美观。 - 警告:严禁在每行的开头随意添加空格。PyCharm 会通过红色波浪线提示此类缩进错误,因为 Python 对代码缩进有严格的语法要求。
- 操作符(如
- 字符串连接时,需手动添加空格以保留间距。例如:
print("你好" + " " + "这是一句代码") - 操作符(如
+)两端空格可选,但可提高可读性。 - 严禁行首添加空格,会导致缩进错误。
- 演示:
print('Let's go'),PyCharm 会提示错误,因为'被理解为字符串的结束,导致语法错误。
字符串中的特殊字符处理
Section titled “字符串中的特殊字符处理”- 反斜杠转义的应用:
- 当字符串内部需要包含与外层引号相同的引号时,使用反斜杠 `` 进行转义。
- 示例:
print('Let\'s go')。 - 视觉识别:在代码编辑器中,反斜杠和其后的引号通常会显示为相同的颜色,提示它们是一组转义序列。
- 反斜杠与正斜杠的区别:
- 必须使用反斜杠
\(位于键盘 Enter 键上方),使用正斜杠/将导致代码无法正常运行。
- 必须使用反斜杠
换行控制与代码格式
Section titled “换行控制与代码格式”- print 函数换行:
- 若需在输出中打印两行内容,可以使用两个独立的
print()语句。 - 示例:
- 若需在输出中打印两行内容,可以使用两个独立的
print('第一行') print('第二行')打印空行演示
Section titled “打印空行演示”print("\n")输出一个空行。
三引号跨行输入 (例子4)
Section titled “三引号跨行输入 (例子4)”- 使用三个单引号
'''或三个双引号"""实现跨行字符串输入。 - PyCharm 智能补全:打三个引号后自动匹配。
三引号粘贴多行文本实践
Section titled “三引号粘贴多行文本实践”- 输入三个引号(‘’’ 或 “”“),PyCharm 自动补全闭合引号。
- 复制粘贴诗歌等多行文本到三引号间。
- 运行后,输出完整保留代码中的原始换行格式,原封不动打印。
变量复制与备份
Section titled “变量复制与备份”变量间复制原理
Section titled “变量间复制原理”- 复制操作:等号左边视为变量名,右边先求值后赋值。
- 示例场景:
MyLove已存前任手机号,现用信任手机号覆盖但不想丢失旧值。
备份旧值方法
Section titled “备份旧值方法”- 用新变量(如
MyX)先复制旧值,再更新原变量。 - 示例:
MyX = MyLove # 先存前任手机号到 MyX MyLove = "信任的手机号" # 覆盖新值- 结果:
MyX保留137那个手机号。
变量的现实类比与用途
Section titled “变量的现实类比与用途”- 频繁使用长字符串(如对象的手机号)很麻烦,难以记忆。
- 现实类比:通讯录通过人名(标签)找到手机号。
- 程序变量:同样用于存储或指代值,先给变量取名字。
变量命名规则
Section titled “变量命名规则”- 中间不能有空格,也不能是数字。
变量命名与赋值规则
Section titled “变量命名与赋值规则”变量命名限制
Section titled “变量命名限制”- 不能以数字开头:变量名首字符必须是字母或下划线,否则会导致语法错误。
- 禁止引号包裹:定义变量名时千万不要用引号(单引号或双引号)包裹,否则 Python 会将其识别为字符串而非变量名。
赋值操作 (Assignment)
Section titled “赋值操作 (Assignment)”- 赋值语法:使用等号
=将右侧的值赋给左侧的变量名。- 示例:
my_love = "13766666666"
- 示例:
- 赋值本质:将特定的值存入变量中,后续可通过变量名直接获取该值,无需重复输入数据。
变量使用注意事项
Section titled “变量使用注意事项”- 执行顺序:Python 程序从上到下逐行执行。必须先对变量进行赋值,才能在后续代码中调用该变量。
- 若在赋值前使用变量,程序会报
NameError,如同未将号码存入通讯录却试图拨号一样。
- 若在赋值前使用变量,程序会报
- 变量复用:赋值后,变量名可被反复调用,极大简化了代码编写与维护工作。
变量值更新与动态性
Section titled “变量值更新与动态性”- 变量的本质:之所以称为“变量”,是因为其存储的值可以根据程序逻辑随时改变。
- 动态更新示例:
my_love = "13766666666" # 初始赋值 my_love = "15066666666" # 赋予新值,原值被覆盖- 逻辑应用:当对象更换手机号或更换对象时,只需对原变量名进行新的赋值操作,后续程序中调用该变量时,会自动获取更新后的值。
复杂逻辑打印技巧与问候实践
Section titled “复杂逻辑打印技巧与问候实践”print调试复杂逻辑
Section titled “print调试复杂逻辑”- 逻辑复杂时,用print打印当前变量值,了解运行情况。
问候字符串拼接实践
Section titled “问候字符串拼接实践”- 示例:打招呼语句**“您好吃了吗”** + 名字(如招三)。
- 拼接后打印:“招三,您好吃了吗”(女士类似)。
使用变量简化重复输出
Section titled “使用变量简化重复输出”- 当需要多次输出相同字符串(如“您好吃了吗”)时,直接硬编码会造成冗余且难以维护。
- 通过将重复字符串赋值给变量,可以大幅简化代码并提高灵活性。
greet = "您好吃了吗"print(greet + "张三")print(greet + "李四")- 这种方式下,若需要修改问候语,只需修改
greet变量的值,所有后续的print语句都会自动更新,避免了逐行修改的繁琐。
变量在字符串拼接中的动态更新
Section titled “变量在字符串拼接中的动态更新”- 批量修改的便捷性:通过将重复的问候语赋值给变量(如
greet),当需要修改问候语(例如从中文“您好吃了吗”改为英文“Yo what’s up”)时,只需在代码顶部修改一次变量值。 - 自动联动:程序运行时,所有引用该变量的
print语句会自动获取更新后的值,无需逐行手动修改。
greet = "Yo what's up"print(greet + "张三")print(greet + "李四")print(greet + "王五")- 变量的动态本质:变量之所以称为“变量”,是因为其存储的值可以根据程序逻辑随时改变,后续所有调用该变量的地方都会同步反映出最新的赋值结果。
变量旧值备份策略
Section titled “变量旧值备份策略”备份变量旧值避免丢失
Section titled “备份变量旧值避免丢失”- 问题:直接替换变量值会导致原值丢失,无法找回之前的值(如中文问候)。
- 解决:先定义
groupchinese = group,备份旧值;再定义groupenglish = "新的值",存入新值。
groupchinese = group # 备份之前的中文 groupgroupenglish = "新的值" # 英文新值- 后续可分别使用不同变量调用对应值。
grid变量的多语言切换实践
Section titled “grid变量的多语言切换实践”更新grid为英文问候并验证
Section titled “更新grid为英文问候并验证”- 将
grid更新为gridenglish,打印查看:现在所有的打招呼均为英文。
保留中文切换方式
Section titled “保留中文切换方式”- 同时保留
grid chinese,需切换回中文打招呼时,直接使用即可。
grid = gridenglishprint(grid) # 现在所有的打招呼应该还是英文的变量命名规范与最佳实践
Section titled “变量命名规范与最佳实践”变量命名的语法限制
Section titled “变量命名的语法限制”- 禁止数字开头:变量名首字符必须为字母或下划线,以数字开头会导致语法错误。
- Python 语法校验:若违反命名规则,Python 解释器会直接报错。
变量命名的工程建议
Section titled “变量命名的工程建议”- 可读性优先:变量名应具备语义,便于理解和记忆,避免使用
a、a1、abc等无意义命名。 - 避免拼音命名:不建议使用拼音作为变量名,因为拼音阅读速度慢且容易引起歧义。
- 命名原则:好的变量名应能直观反映其存储数据的含义,避免在未来维护代码时忘记变量用途。
变量命名避坑指南
Section titled “变量命名避坑指南”- 避免使用拼音命名:
- 拼音阅读速度慢,且容易引起歧义(如
pingyin、pinyin、pingying的混淆)。 - 拼音不带声调容易产生歧义(如
gaoji既可以是“高级”也可以是“搞基”),导致代码意图不明。
- 拼音阅读速度慢,且容易引起歧义(如
- 变量命名的语义化:
- 变量名应直观反映存储数据的含义,避免使用
a、a1、abc等无意义命名,防止维护时遗忘用途。
- 变量名应直观反映存储数据的含义,避免使用
Python 对中文变量的支持
Section titled “Python 对中文变量的支持”- 版本差异:
- Python 3.0 版本之后开始支持中文变量名。
- 尽管支持,但主流开发习惯仍倾向于使用英文单词作为变量名,以保持代码的通用性和可读性。
变量命名与编码兼容性问题
Section titled “变量命名与编码兼容性问题”- 编码兼容性风险:
- 若控制台或日志系统的编码格式不支持中文,使用中文命名变量会导致乱码。
- 即使语言本身支持中文变量名,也应考虑运行环境的兼容性。
编程语言习惯与开发效率
Section titled “编程语言习惯与开发效率”- 输入法切换成本:
- 由于代码关键字和符号均为英文,频繁在中文和英文输入法之间切换会降低编码效率。
- 翻译工具的普及:
- 使用翻译工具(如词典)将中文含义转为英文命名并不困难,因此保持英文命名的习惯在工程实践中更为普遍。
Python 变量命名规范:下划线命名法 (snake_case)
Section titled “Python 变量命名规范:下划线命名法 (snake_case)”-
约定俗成:Python 社区普遍采用下划线命名法来增加多单词变量的可读性。
-
核心规则:
- 字母全部小写。
- 不同单词之间使用下划线
_分隔。
-
示例:
user_age(用户年龄)user_gender(用户性别)
-
设计逻辑:下划线替代了空格,既满足了变量名不能包含空格的语法限制,又保持了语义的清晰度。
变量命名的大小写敏感性
Section titled “变量命名的大小写敏感性”- 大小写区分:Python 变量名是区分大小写的,
user_age和user_Age被视为两个完全不同的变量。
避免占用 Python 关键字
Section titled “避免占用 Python 关键字”- 关键字冲突:变量名不能使用 Python 的内置关键字(如
print)。 - 后果:如果将
print赋值为字符串,print函数原有的打印功能会被覆盖,导致后续无法再调用该函数进行输出。
print = "u123" # 错误做法:覆盖了内置函数print("Hello") # 报错:此时 print 已不再是函数Python 关键字记忆与识别
Section titled “Python 关键字记忆与识别”关键字数量与学习建议
Section titled “关键字数量与学习建议”- Python 有30几个关键字,这些后面都会成为很眼熟的词,不需要现在死记。
PyCharm 中的关键字提示
Section titled “PyCharm 中的关键字提示”- PyCharm 会对 Python 关键字 进行颜色高亮展示。
- 如果打印出来的变量名是彩色的,说明那是关键字,最好换成其他的。
使用 map 模块的 sqrt 函数
Section titled “使用 map 模块的 sqrt 函数”导入 map 模块
Section titled “导入 map 模块”- 在代码文件开头使用
import map引入模块,以调用其函数。
import map调用 map.sqrt() 函数
Section titled “调用 map.sqrt() 函数”- 格式:
map.sqrt(),置于最开头后跟点号调用平方根函数。
公式实现:括号除以 2a
Section titled “公式实现:括号除以 2a”- 将分数线以上内容全部括起来,除以
2 * a。
(map.sqrt(...)) / (2 * a)求解公式实践:第一个解与第二个解
Section titled “求解公式实践:第一个解与第二个解”第一个解与第二个解的快速修改
Section titled “第一个解与第二个解的快速修改”- 第二个解修改:只需将公式中的加法改为减法。
print 输出验证
Section titled “print 输出验证”- 无 print 无输出:仅运算不会显示结果,必须用
print()包裹整个运算。 - 运行步骤:包裹后点击运行,即可看到两个正确结果。
- 求其他方程时,无需更改公式。
import mapprint((-b + map.sqrt(b**2 - 4*a*c)) / (2*a)) # 第一个解print((-b - map.sqrt(b**2 - 4*a*c)) / (2*a)) # 第二个解使用代码进行数学计算的优势
Section titled “使用代码进行数学计算的优势”- 公式可视化与检查:将完整公式写入代码中,便于随时查看逻辑结构,避免手动计算时的拼写或录入错误。
- 变量动态更新:当需要计算不同方程时,只需修改变量
a,b,c的值,无需重写整个公式,极大提高了复用性。 - 高效调试:通过代码运行直接获取计算结果,减少了人工计算的繁琐步骤,且能快速验证不同参数下的解。
使用中间变量简化复杂公式
Section titled “使用中间变量简化复杂公式”中间变量简化公式实践
Section titled “中间变量简化公式实践”- 公式复杂时,可通过中间变量分步骤计算,提高代码清晰度。
- 示例:将二次方程判别式 b² - 4ac 提取为变量
delta。
import map
delta = b**2 - 4 * a * cprint((-b + map.sqrt(delta)) / (2 * a))print((-b - map.sqrt(delta)) / (2 * a))- 优势:过程更简洁清晰,便于阅读、维护与调试。
代码注释的注意事项
Section titled “代码注释的注意事项”注释特点与不当用法
Section titled “注释特点与不当用法”- 注释不影响程序执行,有些程序员放飞自我:求佛祖保佑无bug、血泪劝退其他程序员。
真实公关危机案例
Section titled “真实公关危机案例”- 17年加米音乐:程序员注释免费VIP用户为**“穷逼VIP”**,引发用户不满。
- 程序员道歉:今后会**“正正经经写注释”**。
- 不要在注释里过多**“放飞自我”**。
数据类型与字符串长度
Section titled “数据类型与字符串长度”主要数据类型
Section titled “主要数据类型”- 编程世界的数据种类称为数据类型。
- 包括:字符串、整数、浮点数、画类型、空置类型,以及后续的列表、词典等。
字符串类型特点
Section titled “字符串类型特点”- 一串字符,表示文本内容。
- 用双引号或单引号包裹。
字符串长度计算
Section titled “字符串长度计算”- 使用列函数获取字符串长度。
- 空格、数字、符号等各占一个长度。
- 转义符特殊:如反斜杠后跟N(换行),整个转义符占一个长度。
基本数据类型介绍
Section titled “基本数据类型介绍”- 字符串后加方括号
[],放入索引提取单个字符。 - 索引从0开始:第一个为0,排第四的用索引3,返回
'L'字符。
- 整数在Python叫 int。
- 辅典数在Python叫 flump。
- 操作已在之前数学运算覆盖,直观不赘述。
Ball类型
Section titled “Ball类型”- 只包含两种值:true(t大写)和 false(f大写)。
空值类型 (NoneType)
Section titled “空值类型 (NoneType)”- 专门用于表示“完全没有值”的特殊数据类型。
- 仅包含一个值:
None。 - 注意事项:
None不等于0,不等于空字符串"",也不等于False。 - 适用场景:当需要定义一个变量但暂时不知道其具体值时,可先将其赋值为
None。
类型检查函数 type()
Section titled “类型检查函数 type()”- 使用
type()函数可以查看任何对象的数据类型。 - 示例输出:
type("Hello") # <class 'str'> type(6) # <class 'int'> type(6.0) # <class 'float'> type(True) # <class 'bool'> type(None) # <class 'NoneType'>数据类型与函数的关系
Section titled “数据类型与函数的关系”- 数据类型决定了该对象可以调用哪些函数。
- 函数是执行特定功能的工具,必须传入正确类型的数据才能得到预期的输出(类比:巧克力机器只能处理可可粉,若输入石头则会报错)。
- 示例:
len()函数适用于字符串,若传入不匹配的类型则无法正常工作。
len() 函数类型限制与字符串演示
Section titled “len() 函数类型限制与字符串演示”len() 函数适用性
Section titled “len() 函数适用性”len()函数对整数和浮点数使用会报错。- 对字符串有效。
字符串长度实践
Section titled “字符串长度实践”- 定义变量:
hello = "Hello"。 - 使用
print(len(hello))输出结果:12。 - 原因:空格和符号各占一个长度。
字符串索引示例
Section titled “字符串索引示例”索引从0开始
Section titled “索引从0开始”- 获取第一个字符:
s[0]返回'H'。
最后一个字符索引
Section titled “最后一个字符索引”- 字符串长度为12,最后一个索引为11。
s[11]返回'!'(感叹号)。
动态索引计算
Section titled “动态索引计算”- 使用
len(s) - 1计算最后一个索引,结果相同。 - 示例代码:
s = "Hello world!" # 长度12print(s[0]) # 'H'print(s[11]) # '!'print(s[len(s)-1]) # '!'布尔与空值变量赋值实践
Section titled “布尔与空值变量赋值实践”布尔值赋值演示
Section titled “布尔值赋值演示”- 赋值
tree1 = True,tree2 = True:需首字母大写。 - 小写
true会报错,不被识别为布尔值。 - 加引号
true则成字符串。
空值赋值演示
Section titled “空值赋值演示”n = None:首字母大写。- 小写
none不被识别。
验证之前变量类型
Section titled “验证之前变量类型”- 通过赋值实践确认数据类型正确性。
type() 函数额外示例
Section titled “type() 函数额外示例”None 与浮点数类型确认
Section titled “None 与浮点数类型确认”type(None)输出<class 'NoneType'>。type(1.5)输出<class 'float'>,因小数点而非int。
类型不匹配错误
Section titled “类型不匹配错误”- 对布尔值使用
len()报TypeError。 - 示例:
print(len(True)) # TypeError- 强调了解对象类型避免错误。
命名行模式与交互模式
Section titled “命名行模式与交互模式”- 命名行模式:
- 保存并运行整个文件。
- Python 解释器逐行解析和执行文件。
- 交互模式:
- Python 逐行执行命令并展示结果。
- 无需创建新文件。
- 可通过 PyCharm 下方的 Python 控制台,或 Windows 的 CMD,Mac 的终端(输入
python3)进入。 - 出现
>>>提示符,表示等待指令。 - 输入 Python 命令后立即执行,并显示结果。
- 例如:
print("hi")会立即输出hi。
交互模式 (Interactive Mode)
Section titled “交互模式 (Interactive Mode)”交互模式的特点
Section titled “交互模式的特点”- 无需创建 Python 文件即可直接运行代码。
- 无需显式调用
print()函数即可查看结果,Python 会自动返回表达式的计算结果。 - 示例:
>>> a = "你好" + "!" >>> a '你好!' >>> 3 * 2 6退出交互模式
Section titled “退出交互模式”- 使用
quit()函数(需带括号)。 - 使用快捷键
Ctrl + D。
交互模式与命令行模式的区别
Section titled “交互模式与命令行模式的区别”- 交互模式:适合快速测试和验证代码,但输入的指令不会被保存。
- 命令行模式(脚本运行):适合编写正式程序,代码可保存并重复执行,是我们日常开发的主要方式。
交互模式的实际应用
Section titled “交互模式的实际应用”- 比喻游乐场:随意测试命令、查看输出结果。
- 适合一次性计算:输入算式得结果后直接退出。
- 优势:快速计算,显得行云流水。
BMI 计算器介绍
Section titled “BMI 计算器介绍”- 使用
input()实现简单身体质量指数计算器。 - 公式:$$BMI = \frac{weight}{height^2}$$
weight:千克 (kg)。height:米 (m)。
- 首先定义变量
use_weight。
BMI 计算输入与类型转换问题
Section titled “BMI 计算输入与类型转换问题”用户输入体重与身高
Section titled “用户输入体重与身高”userweight = input("请输入您的体重单位是千克")userheight = input("请输入您的身高单位是米")
BMI 计算公式
Section titled “BMI 计算公式”userbmi = userweight / userheight ** 2
类型错误提示
Section titled “类型错误提示”- PyCharm 提示问题:
userweight和userheight为字符串(str)。 - 字符串不支持除法(
/)和平方(**)运算。
- 先将两者转换为数字类型才能计算。
- 身高暂不使用
int()函数转换。
BMI 计算器:输入转换与计算
Section titled “BMI 计算器:输入转换与计算”输入字符串转浮点数
Section titled “输入字符串转浮点数”- 用
float()函数将字符串转换为浮点数。 - 示例:计算 BMI 前转换
height和weight输入。
BMI 计算与输出
Section titled “BMI 计算与输出”- 计算 BMI 值:
bmi = weight / (height ** 2)。 - 计算结果为数字,打印前需用
str()转字符串。 - 示例:
height_float = float(height_str)weight_float = float(weight_str)bmi = weight_float / (height_float ** 2)print('BMI: ' + str(bmi))- 输入任意身高、体重数字,运行成功。
- 实现任意输入的 BMI 计算器。
条件判断的逻辑基础
Section titled “条件判断的逻辑基础”- 条件语句的核心在于根据判断条件是否满足来决定执行的内容。
- 现实生活中的决策逻辑示例: - 情绪决定行为:根据女朋友心情判断是否能打游戏。 - 职场决策:根据老板脸色判断是否提加工资。
Python 条件语句 if 结构
Section titled “Python 条件语句 if 结构”- 基本语法结构:
if [条件]:执行 A 行动
Section titled “执行 A 行动”else:
执行 B 行动
Section titled “执行 B 行动”- 条件判断的本质是布尔值(True 或 False)的求值。- 只要表达式的结果为布尔值,即可直接作为判断条件。布尔变量作为条件
Section titled “布尔变量作为条件”- 可以直接将布尔变量放置在
if后面作为判断条件:
is_happy = True if is_happy:执行相关逻辑
Section titled “执行相关逻辑”- 使用比较运算符可以生成布尔值,常见的比较运算符包括等于号
==。 - 比较运算符用于判断两个对象的值是否相等:
3 == 3返回True"a" == "b"返回False
比较运算符与逻辑判断
Section titled “比较运算符与逻辑判断”比较运算符基础
Section titled “比较运算符基础”- 比较运算符用于判断两个对象的关系,返回布尔值(
True或False)。 - 等于判断使用双等号
==,避免与赋值运算符=混淆。 - 不等于判断使用
!=。 - 常用运算符包括:
- 大于
> - 大于等于
>= - 小于
< - 小于等于
<=
- 大于
if 条件语句结构
Section titled “if 条件语句结构”if语句用于根据条件执行代码块,语法结构如下:
if [条件]: [执行语句]- 语法注意事项:
- 条件后必须紧跟冒号
:,表示条件定义结束。 - 执行语句必须进行缩进(推荐使用 4 个空格),否则会报错。
- 若条件为真,则执行缩进内的所有代码块。
- 若条件为假,则跳过该代码块。
- 条件后必须紧跟冒号
- 示例:
if 5 >= 20:结果为False,因此内部代码不会被执行。
条件判断的潜在问题与数据类型转换
Section titled “条件判断的潜在问题与数据类型转换”- 在
if语句中使用input()获取的值进行判断时,必须注意input()返回的始终是字符串类型。 - 若要将输入的字符串(如
mood_index)与数字进行比较,必须先用int()或float()函数将其转换为数值类型,否则逻辑判断将无法正确执行。
if-else 条件分支结构
Section titled “if-else 条件分支结构”else语句是可选的,用于处理条件为False时的逻辑。- 语法要点:
else必须紧跟冒号:。- 内部执行语句必须保持缩进(即使 PyCharm 会自动缩进,编写时仍需注意)。
代码示例:心情指数判断
Section titled “代码示例:心情指数判断”mood_index = int(input("你今天的心情指数是多少?"))
if mood_index >= 60: print("恭喜,今晚可以打游戏,去吧皮卡丘!")else: print("心情不佳,建议休息。")if-else 条件分支结构的灵活性
Section titled “if-else 条件分支结构的灵活性”- 代码块可以包含多行语句,只要保持一致的缩进即可。
else语句是可选的,根据逻辑需求决定是否需要处理条件为False的情况。
条件语句中的缩进规则
Section titled “条件语句中的缩进规则”- 缩进是 Python 识别代码块归属的唯一方式,必须严格遵守。
- 每一行属于
if或else的代码都必须有缩进,否则程序无法正确识别逻辑层级。
复杂逻辑的交互式打印
Section titled “复杂逻辑的交互式打印”- 在
print语句中,可以通过拼接字符串和变量来输出更丰富的提示信息。 - 示例:在
print中加入表情符号或动态文本,增强程序运行时的反馈感。
示例:多行代码块与表情符号输出
Section titled “示例:多行代码块与表情符号输出”if mood_index >= 60:
print("恭喜,今晚可以打游戏!")
print("( ^\_^) / ")else:
print("为了自个小命,还是别打了。")if-else 缩进错误与修正实践
Section titled “if-else 缩进错误与修正实践”无缩进 print 无条件执行
Section titled “无缩进 print 无条件执行”- 条件语句后若无缩进,视为 if 块结束,该 print 语句总是执行。
- 示例:输入后第一句和第二句都会打印。
独立 else 语法错误
Section titled “独立 else 语法错误”else不能独立存在,必须依附于if。- 缺少对应 if 会导致Python 报错。
修正缩进后的运行效果
Section titled “修正缩进后的运行效果”- 正确缩进后,输入“佐识”可见第二句也被打印。
- 确认 if-else 逻辑正常工作。
if-else 执行规则
Section titled “if-else 执行规则”- 条件为真:执行 if 下语句,跳过 else。
- 条件为假:执行 else 下语句。
多条件判断引入
Section titled “多条件判断引入”- 单条件不足以决定行动。
- 示例:女友心情不好时,不敢屁股对着她打一晚上游戏,需结合其他条件。
嵌套条件语句 (Nested if-else)
Section titled “嵌套条件语句 (Nested if-else)”嵌套逻辑的实现
Section titled “嵌套逻辑的实现”- 当需要在满足第一层条件的前提下,进一步进行逻辑判断时,可以使用嵌套
if语句。 - 逻辑流程:
if [条件1]: if [条件2]: [语句A] else: [语句B]- 执行前提:只有当
条件1为真时,程序才会进入内部判断条件2;若条件1为假,则直接跳过整个嵌套代码块。
嵌套结构中的缩进规范
Section titled “嵌套结构中的缩进规范”- 嵌套在内部的
if或else语句必须在外部if的基础上再次缩进(通常再增加 4 个空格)。 - 缩进是 Python 识别代码层级的唯一依据,错误的缩进会导致逻辑判断范围错误或语法报错。
流程控制可视化
Section titled “流程控制可视化”[开始] | [条件1] --(为假)--> [跳过] | (为真) | [条件2] --(为真)--> [语句A] | (为假) | [语句B]多条件判断与 elif 关键字
Section titled “多条件判断与 elif 关键字”- 当嵌套
if-else结构过于复杂时,可以使用elif(else if) 关键字来实现多条件分支,使逻辑更加清晰直观。 elif允许在多个条件中进行选择,Python 会从上到下依次判断,一旦找到第一个为True的条件,即执行对应的语句块并跳过后续所有分支。
elif 语法结构
Section titled “elif 语法结构”if [条件1]: [语句A]elif [条件2]: [语句B]elif [条件3]: [语句C]else: [语句D]- 执行逻辑:
- 顺序执行:Python 按照代码编写顺序从上往下检查条件。
- 唯一性:一旦某个
if或elif条件满足,后续的elif和else将不再执行。 - 灵活性:
elif的数量没有限制,可以根据业务需求添加任意多个。
- 与嵌套结构的对比:
elif结构扁平化,避免了过深的缩进(即“嵌套地狱”),提高了代码的可读性和可维护性。
多条件 elif 在 BMI 计算器中的应用
Section titled “多条件 elif 在 BMI 计算器中的应用”elif 执行逻辑
Section titled “elif 执行逻辑”- Python 从上到下依次检查
if和elif条件。 - 一旦某个条件为
True,执行对应代码块,跳过后续所有elif和else。 - 示例:条件2和条件3同时满足,只执行条件2分支,后续判断停止。
BMI 计算器扩展
Section titled “BMI 计算器扩展”- 基于之前代码(输入体重/身高,转浮点数,计算 BMI = 体重 / 身高²)。
- 成人BMI标准:
if bmi <= 18.5: 偏瘦elif bmi > 18.5 and bmi <= 25: 正常elif bmi > 25 and bmi <= 30: 超重
- 使用
elif实现多级分类,提高逻辑清晰度。
使用 elif 实现 BMI 分类
Section titled “使用 elif 实现 BMI 分类”- 逻辑结构:通过
if和多个elif组合,可以清晰地对 BMI 数值进行分段判断。 - 示例代码:
if user_BMI <= 18.5: print("BMI值属于偏瘦范围") elif 18.5 < user_BMI <= 25: print("BMI值属于正常范围") elif 25 < user_BMI <= 30: print("BMI值属于超重范围") else: print("BMI值属于肥胖范围")数学表达式在 Python 中的简化
Section titled “数学表达式在 Python 中的简化”- Python 支持直接使用连等式表示范围,例如
18.5 < user_BMI <= 25,这与数学中的写法一致。 - 这种写法比使用
and连接两个比较表达式更加简洁直观,且在 Python 中完全合法。
BMI 计算器完整代码实现
Section titled “BMI 计算器完整代码实现”- 使用
if-elif-else结构对计算出的user_BMI进行多级分类判断。 - Python 支持数学连等式语法,使范围判断更简洁直观。
if user_BMI <= 18.5: print("此BMI值属于偏瘦范围")elif 18.5 < user_BMI <= 25: print("此BMI值属于正常范围")elif 25 < user_BMI <= 30: print("此BMI值属于超重范围")else: print("此BMI值属于肥胖范围")程序运行与扩展建议
Section titled “程序运行与扩展建议”- 运行程序后,输入体重(kg)和身高(m)即可获得对应的 BMI 分类。
- 进一步优化的思路:
- 使用嵌套逻辑根据用户性别输出个性化问候(如“先生您好”或“女士您好”)。
- 增加输入校验,确保输入的数值合理,避免负数或零导致计算错误。
嵌套条件语句的局限与逻辑运算引入
Section titled “嵌套条件语句的局限与逻辑运算引入”双条件嵌套示例:心情与在家判断
Section titled “双条件嵌套示例:心情与在家判断”- 对象心情指数 < 60 时,进一步判断是否在家:
- 在家(真):不能打游戏。
- 不在家(假):拥有自由。
if 心情指数 < 60: if 在家: print("不能打游戏") else: print("拥有自由")复杂多条件嵌套问题
Section titled “复杂多条件嵌套问题”- 示例:奖励 switch 新年礼物需满足 4 个条件:
- 家务次数 >10 次。
- 翻红包次数 >1 次。
- 陪逛街次数 >4 次。
- 一个月内没有惹生气。
- 用嵌套
if表达:缩进层级过多,代码不优雅,易迷失逻辑(嵌套地狱)。
逻辑运算引入
Section titled “逻辑运算引入”- 复杂多条件场景下,逻辑运算符 可简化嵌套结构,提高代码可读性。
Python 逻辑运算符
Section titled “Python 逻辑运算符”- Python 仅包含三个逻辑运算符:
and、or、not。 - 逻辑运算符功能:
and(与):连接两个或以上操作对象,仅当所有条件均为True时返回True;只要有一个为False,结果即为False。or(或):连接两个或以上操作对象,只要有一个条件为True,即返回True;仅当所有条件均为False时返回False。not(非):对单个操作对象取反,若原值为True则返回False,反之亦然。
逻辑运算示例
Section titled “逻辑运算示例”and示例:x > 5 and x < 10(表示 x 同时满足大于 5 且小于 10)。or示例:x > 5 or x < 10(表示 x 满足大于 5 或小于 10 其中之一)。not示例:not x > 5(表示 x 不大于 5)。
逻辑运算执行逻辑
Section titled “逻辑运算执行逻辑”- 逻辑运算支持链式连接多个判断条件,例如:
x > 5 and x < 10 and x * 2 == 12- Python 会依次计算每个表达式的布尔值,并根据逻辑运算符的规则得出最终结果。
not运算符优先级较高,通常用于对单个布尔结果进行翻转。
逻辑运算符的直观理解
Section titled “逻辑运算符的直观理解”- 为了简化复杂的嵌套判断,可以将逻辑运算符类比为人的情绪倾向:
and(与):悲观者。只要有一个条件为False(不开心),整个结果就为False。or(或):乐观者。只要有一个条件为True(开心),整个结果就为True。not(非):反转者。直接将布尔值True变为False,反之亦然。
逻辑运算符优先级与混合使用
Section titled “逻辑运算符优先级与混合使用”- 当多种逻辑运算符混合使用时,遵循特定的优先级,类似于数学中的运算顺序:
- 优先级顺序:
not>and>or
- 优先级顺序:
- 使用括号改变优先级:
- 与数学运算中的括号用法一致,可以使用
()强制改变运算顺序,确保逻辑按预期执行。 - 示例:
not (x > 5 and (x < 10 or x == 12))
- 与数学运算中的括号用法一致,可以使用
逻辑运算符在实际业务中的应用
Section titled “逻辑运算符在实际业务中的应用”- 将多个条件合并到一个
if语句中,可以显著提升代码的可读性和优雅度,避免“嵌套地狱”。 - 示例:奖励 Switch 礼物的复杂条件判断
if (house_work_count > 10 and red_envelope_count > 1 and shopping_count > 4 and not has_been_angry): print("摩拳擦掌等待Switch!") else: print("Switch随风散去...")- 注意:虽然逻辑运算通常比嵌套更优雅,但并非所有场景都适用,需根据具体业务逻辑选择最清晰的表达方式。
列表 (List) 数据结构
Section titled “列表 (List) 数据结构”列表引入与必要性
Section titled “列表引入与必要性”- 当需要处理大量关联数据时,使用多个独立变量(如
item1,item2…)会导致代码冗余且难以维护。 - 数据结构:列表(List)是一种将相关联数据整合在一起的容器,能优雅地解决变量过多的问题。
列表的定义与操作
Section titled “列表的定义与操作”- 创建列表:使用一对中括号
[]表示,空列表即[]。 - 添加元素:使用
append()方法向已定义的列表中追加新数据。
shopping_list = [“键盘”, “键帽”]
shopping_list.append(“显示器”)
方法与函数的类比
Section titled “方法与函数的类比”append()是一种“方法”,它与函数类似,专门负责执行某个特定的功能。在列表对象后通过点号.调用,体现了面向对象的调用习惯。
方法与函数的调用差异
Section titled “方法与函数的调用差异”- 方法 (Method):通常在对象后通过点号
.调用,例如shopping_list.append("显示器")。这种方式强调该功能是专门为特定对象类型(如列表)设计的。 - 函数 (Function):通过函数名直接调用,并将操作对象作为参数传入,例如
len(shopping_list)。
数据类型的可变性 (Mutability)
Section titled “数据类型的可变性 (Mutability)”- 可变类型 (Mutable):如列表
list。修改其内容时,直接在原对象上进行操作,不需要重新赋值。 - 不可变类型 (Immutable):如字符串
str、整数int、浮点数float、布尔值bool。对这些类型进行操作(如s.upper())时,原对象保持不变,必须将返回的新值重新赋值给变量才能保存修改。
字符串不可变性示例
Section titled “字符串不可变性示例”s = "Hello"s.upper() 返回 “HELLO”,但 s 本身仍为 “Hello”
Section titled “s.upper() 返回 “HELLO”,但 s 本身仍为 “Hello””print(s.upper())
print(s)
若要更新 s,需重新赋值
Section titled “若要更新 s,需重新赋值”s = s.upper()
列表可变性示例
Section titled “列表可变性示例”shopping_list = ["键盘"]append 直接修改原列表,不需要重新赋值
Section titled “append 直接修改原列表,不需要重新赋值”shopping_list.append(“显示器”)
print(shopping_list)
列表元素的删除 (remove)
Section titled “列表元素的删除 (remove)”- 使用
remove()方法可以删除列表中的指定元素。 - 调用方式:
list_name.remove(value)。 - 注意事项:
remove()直接作用于原列表,无需重新赋值。- 若尝试删除列表中不存在的元素,程序会报错。
列表的灵活性
Section titled “列表的灵活性”- Python 列表可以存储不同数据类型的元素(如字符串、浮点数、布尔值、None 等),这与其他语言有显著区别,使用起来非常灵活。
列表长度查询
Section titled “列表长度查询”- 使用
len()函数可以获取列表的长度(即元素个数),与获取字符串长度的方法一致。
列表索引与访问
Section titled “列表索引与访问”- 列表通过索引访问元素,索引从
0开始。 - 获取最后一个元素的索引公式为:
列表长度 - 1。 - 示例:
list[0]获取第一个元素。
- 可以通过索引直接对列表中的某个位置进行重新赋值以修改内容。
列表元素的修改与覆盖
Section titled “列表元素的修改与覆盖”- 列表是可变的,可以直接通过索引定位并重新赋值来修改特定位置的元素。
- 这种操作会直接覆盖该位置原本的元素,不需要重新创建列表。
shopping_list = ["键盘", "显示器", "硬盘"]shopping_list[1] = "音响" # 索引为1的元素被更改print(shopping_list)输出: [“键盘”, “音响”, “硬盘”]
Section titled “输出: [“键盘”, “音响”, “硬盘”]”Python 内置列表函数
Section titled “Python 内置列表函数”- Python 提供了许多针对列表的内置函数,用于快速处理数据:
max(list):返回列表中的最大值。min(list):返回列表中的最小值。sorted(list):返回一个排序后的新列表,且不会改变原列表的顺序。
num_list = [1, 13, -7, 2, 96]print(max(num_list)) # 96print(min(num_list)) # -7print(sorted(num_list)) # [-7, 1, 2, 13, 96]列表操作实践
Section titled “列表操作实践”- 创建空列表:使用
[]。 - 动态添加元素:使用
append()方法。
shopping_list = []shopping_list.append("键盘")shopping_list.append("键帽")print(shopping_list)列表删除添加与索引实践
Section titled “列表删除添加与索引实践”remove删除与验证
Section titled “remove删除与验证”- 从
shopping_list中删除 键帽:shopping_list.remove("键帽")。 - 删除后打印列表,确认键帽已不在其中。
继续添加元素
Section titled “继续添加元素”shopping_list.append("音响")shopping_list.append("电竞椅")长度查询与索引访问
Section titled “长度查询与索引访问”print(len(shopping_list))输出 3,确认元素个数。- 访问第一个元素:
print(shopping_list[0])输出 键盘。
print(len(shopping_list)) # 3print(shopping_list[0]) # 键盘列表索引更新与价格函数实践
Section titled “列表索引更新与价格函数实践”索引更新:音响 → 硬盘
Section titled “索引更新:音响 → 硬盘”- 将索引 1 的元素从 音响 更新为 硬盘。
- 打印验证:原 音响 被 硬盘 覆盖。
shopping_list[1] = "硬盘"print(shopping_list) # ["键盘", "硬盘", "..."]价格列表示例
Section titled “价格列表示例”- 定义价格列表:键盘=799、显示器=1024、硬盘=200、电机=800。
price_list = [799, 1024, 200, 800]max/min 函数应用
Section titled “max/min 函数应用”max(price_list)获取最大值:1024。min(price_list)获取最小值:200。
sorted() 升序排序
Section titled “sorted() 升序排序”sorted(price_list)返回从小到大排序的新列表,不修改原列表。
列表内置函数输出演示与通讯录变量实现
Section titled “列表内置函数输出演示与通讯录变量实现”内置函数打印结果
Section titled “内置函数打印结果”max()输出:最大价格。min()输出:最小价格。sorted()输出:排序后的新列表。- 特定打印:成功输出 Wabbs。
通讯录变量模拟
Section titled “通讯录变量模拟”- 通讯录需求:通过姓名查找手机号。
- 用变量实现:
小名电话 = '手机号值'小花电话 = '手机号值'
- 查找方式:直接用变量名访问对应电话。
通讯录实现方案的局限性
Section titled “通讯录实现方案的局限性”- 使用独立变量(如
小名电话、小花电话)存储通讯录虽然可行,但存在扩展性问题:- 随着联系人增加,变量命名和管理变得繁琐。
- 无法通过统一的逻辑(如循环)批量处理联系人信息。
- 无法将姓名与电话建立直观的映射关系。
字典 (Dictionary) 数据结构引入
Section titled “字典 (Dictionary) 数据结构引入”- 核心概念:字典是一种用于存储键值对 (Key-Value Pair) 的数据结构,专门用于解决“通过名称查找对应数据”的需求。
- 映射逻辑:
- 键 (Key):相当于索引或名称(如“小明”),用于唯一标识和查找。
- 值 (Value):相当于具体存储的数据(如“13700000000”)。
- 类比:类似于现实生活中的字典,通过“字”(键)快速查找到对应的“释义”(值)。
字典的基本语法
Section titled “字典的基本语法”- 定义空字典:使用花括号
{}表示。 - 存储结构:
{键: 值}。 - 查找机制:通过键直接访问对应的值,比遍历列表更高效且直观。
字典示例结构
Section titled “字典示例结构”contacts = {
"小明": "13700000000",
"小花": "13700000001"}
字典的键值对语法与访问
Section titled “字典的键值对语法与访问”- 定义字典:使用花括号
{}包含键值对,键与值之间用冒号:分隔,键值对之间用逗号,分隔。
contacts = {"小明": "13700000000", "小花": "13700000001"}- 查找值:通过在字典名后使用方括号
[]放入键来获取对应的值。
print(contacts["小明"]) # 输出: 13700000000字典键的不可变性限制
Section titled “字典键的不可变性限制”- 键的类型要求:字典的键必须是不可变 (Immutable) 类型。
- 可作为键的类型:字符串 (
str)、整数 (int)、浮点数 (float)、布尔值 (bool)、元组 (tuple)。 - 不可作为键的类型:列表 (
list) 等可变数据类型。
- 可作为键的类型:字符串 (
- 应用场景:当需要用多个维度(如姓名和年龄)唯一标识一个人时,若直接使用列表作为键会报错,此时可以使用元组作为键,因为元组是不可变的。
错误示例:列表不可作为键
Section titled “错误示例:列表不可作为键”contacts = {[“张伟”, 23]: “15000000000”} # 报错
Section titled “contacts = {[“张伟”, 23]: “15000000000”} # 报错”正确做法:使用元组
Section titled “正确做法:使用元组”contacts = {("张伟", 23): "15000000000"}元组 (Tuple) 数据结构
Section titled “元组 (Tuple) 数据结构”- 定义:元组是不可变的序列,使用圆括号
()定义。 - 与列表的区别:
- 语法:列表用
[],元组用()。 - 可变性:列表可修改(添加/删除/更新),元组不可修改。
- 方法支持:元组不支持
append()或remove()等修改操作,因此在需要保证数据结构固定不变时非常有用。
- 语法:列表用
字典的高级操作与管理
Section titled “字典的高级操作与管理”- 字典的动态修改:
- 字典与列表一样是可变的,支持添加新键值对和更新已有键的值。
- 添加/更新语法:
字典名[键] = 值。 - 若键已存在,该操作会覆盖原有值;若键不存在,则新增该键值对。
示例:添加或更新
Section titled “示例:添加或更新”contacts = {“小明”: “13700000000”, “小花”: “13700000001”}
contacts[“美女A”] = “18600000000” # 添加
contacts[“美女A”] = “18600000000” # 若已存在则覆盖
- **键的存在性检查**: - 使用 `in` 关键字检查某个键是否存在于字典中,返回布尔值。
```pythonif "小明" in contacts: print("存在")- 删除键值对:
- 使用
del关键字配合方括号索引删除指定键。
- 使用
del contacts["小明"]字典长度查询
Section titled “字典长度查询”len()函数适用于字典,返回键值对数量。
print(len(contacts)) # 输出键值对个数字典删除操作
Section titled “字典删除操作”del 删除键值对
Section titled “del 删除键值对”- 使用
del 字典名[键]删除指定键及其值。 - 注意:若键不存在,会报错。
电子词典实践
Section titled “电子词典实践”- 需求:查询网络流行语含义。
- 结合字典、
input()和if判断实现。 - 步骤:
- 创建空字典
{}或预置词条:{键: 值}。 - 网上搜索流行语词条,复制添加(如第一个词条,下一个“剑职队用豆豪”)。
- 创建空字典
电子词典:添加流行语词条
Section titled “电子词典:添加流行语词条”- 长词条换行建议:较长内容建议换行,每个词条间更清晰,仍用键:值格式。
- 创建初始字典,长度为2。
- 添加方法:
字典名[键] = 值,依次添加后续流行语(如流星域)及其含义。 - 添加后字典有3条内容。
- 通过剪辑扩展至10条内容。
- 准备开始查询功能。
电子词典:实现查询逻辑
Section titled “电子词典:实现查询逻辑”- 获取用户输入:
- 使用
input()函数获取用户想要查询的词条,并将其赋值给变量query。 - 注意:必须将输入结果存入变量,否则无法获取用户输入的值。
- 使用
- 查询逻辑实现:
- 使用
if语句结合in运算符判断查询的词条是否存在于字典中。 - 若存在,打印查询结果;若不存在,可根据需求后续扩展提示逻辑。
- 使用
- 代码实现示例:
query = input("请输入您想要查询的词条:") if query in slang_dict: print("您查询的" + query + "含义如下:") print(slang_dict[query])- 获取字典值:
- 通过
字典名[键]的方式访问并获取对应的值。
- 通过
电子词典:异常处理与功能扩展
Section titled “电子词典:异常处理与功能扩展”- 查询失败提示:
- 若用户查询的词条不在字典中,应使用
else语句给出明确反馈,避免程序无响应。 - 示例:
print("您查询的流行语暂未收录")。
- 若用户查询的词条不在字典中,应使用
字典长度查询与类型转换
Section titled “字典长度查询与类型转换”- 获取字典大小:
- 使用
len()函数获取字典中键值对的总数。
- 使用
- 类型转换注意事项:
len()返回的是整数(int),若要将其拼接在字符串中进行打印,必须先使用str()函数将其转换为字符串。- 拼接示例:
print("当前词典收录词条数为:" + str(len(slang_dict)))。
电子词典完整代码逻辑
Section titled “电子词典完整代码逻辑”query = input("请输入您想要查询的词条:")if query in slang_dict: print("您查询的" + query + "含义如下:") print(slang_dict[query])else: print("您查询的流行语暂未收录")
print("当前词典收录词条数为:" + str(len(slang_dict)))电子词典查询演示
Section titled “电子词典查询演示”- 成功查询:输入
webds,打印其含义(字典中存在)。 - 失败查询:输入不存在词条(如
源),打印“您查询的流行语暂未收录”。 - 结束输出:打印当前词典收录词条总数。
大数据场景:全公司上万人体温报备,逐条查找高于38度体温低效。
for循环引入
Section titled “for循环引入”- 用途:处理大量数据,实现迭代(逐个遍历)。
- 迭代对象:列表、字典、字符串。
for 循环的结构与执行逻辑
Section titled “for 循环的结构与执行逻辑”- 核心语法:
for 变量名 in 可迭代对象:对每个变量做一些事情
Section titled “对每个变量做一些事情”…
- **执行机制**: - `for` 关键字后跟自定义变量名,该变量在循环中依次被赋值为可迭代对象(如列表、字典、字符串)中的每一个元素。 - 循环体内的代码(必须缩进)会针对每一个元素执行一次。- **变量命名**: - 循环变量名可自定义,建议根据业务含义命名(如 `temperature`),以提高代码可读性。循环应用示例:体温检查
Section titled “循环应用示例:体温检查”- 场景:遍历包含全公司人员体温的列表,对每个体温数值进行检查。
- 代码实现:
temperature_list = [36.4, 36.6, 36.2, 37.0, 36.8] for temperature in temperature_list:在此编写检查逻辑,例如 if temperature > 38:
Section titled “在此编写检查逻辑,例如 if temperature > 38:”- **缩进规则**:所有在 `for` 下方缩进的代码均被视为循环体的一部分,对列表中的每个元素都会执行一遍。for 循环在体温检查中的应用
Section titled “for 循环在体温检查中的应用”- 代码实现示例:
temperature_list = [36.4, 36.6, 36.2, 37.0, 36.5, 38.3, 38.1]
for temperature in temperature_list: if temperature >= 38: print(temperature) print("完球了")- 逻辑分析:
- 该循环遍历列表中的每个体温数值,当数值大于或等于38时,触发打印逻辑。
- 这种方式能快速统计有多少人发烧,但无法直接关联到具体的工号。
字典与循环的结合:处理键值对
Section titled “字典与循环的结合:处理键值对”- 场景:当需要关联工号(键)与体温(值)时,单纯的列表循环不足以满足需求。
- 字典方法:
dict.keys():获取所有键。dict.values():获取所有值。dict.items():获取所有键值对(元组形式)。
- 结合 for 循环遍历字典:
temperature_dict = {"111": 36.4, "112": 36.6, "113": 38.3}
for staff_id, temperature in temperature_dict.items(): if temperature >= 38: print(staff_id)- 解包机制 (Unpacking):
for循环后跟两个变量时,Python 会自动将items()返回的元组中的第一个元素赋给staff_id,第二个元素赋给temperature。- 这等同于手动解包:
staff_id = temperature_tuple[0]和temperature = temperature_tuple[1]。
for 循环结合 range 的应用
Section titled “for 循环结合 range 的应用”- range 函数:用于生成一个整数序列,常与
for循环配合实现指定次数的重复操作。- 语法:
range(起始值, 结束值) - 注意:生成的序列包含起始值,但不包含结束值(左闭右开)。
- 示例:
range(5, 10)会生成 5, 6, 7, 8, 9。
- 语法:
range 函数的步长参数
Section titled “range 函数的步长参数”- 语法:
range(起始值, 结束值, 步长)- 步长:决定了每次迭代跨越的数值间隔。
- 默认值:若不指定步长,默认为 1。
- 示例:
range(1, 10, 2)会生成 1, 3, 5, 7, 9。
编程解决数学问题的优势
Section titled “编程解决数学问题的优势”- 高斯求和案例:计算 1 到 100 的和,利用公式
(首项 + 尾项) * 项数 / 2可快速得出 5050。 - 代码实现:相比手动累加,使用循环处理大规模数值计算更高效且不易出错,体现了编程在处理重复逻辑时的核心价值。
使用 for 循环实现高斯求和
Section titled “使用 for 循环实现高斯求和”- 代码实现逻辑:
- 初始化一个变量
total = 0用于累加。 - 使用
for i in range(1, 101)遍历 1 到 100 的整数。 - 在循环体中执行
total = total + i,将当前数值累加到total中。 - 循环结束后,
total即为 1 到 100 的求和结果(5050)。
- 初始化一个变量
total = 0for i in range(1, 101): total = total + iprint(total)- 编程解决数学问题的优势:
- 相比手动计算或公式推导,编程通过循环处理重复累加逻辑,能够快速、准确地解决大规模数值计算问题,体现了计算机处理重复性任务的高效性。
while 循环:处理未知次数的重复任务
Section titled “while 循环:处理未知次数的重复任务”- 局限性:
for循环通常用于已知次数或已知集合的遍历。当任务需要持续执行直到某个条件不再满足(例如等待日落),而无法预知确切次数时,for循环不再适用。 - while 循环的引入:在无法确定循环次数的情况下,
while循环能够持续运行,直到条件变为False。
while 循环的基本结构
Section titled “while 循环的基本结构”- 语法:
while 条件: 行动- 执行逻辑:
- 计算机首先判断
条件是否为真(True)。 - 若为真,执行缩进后的
行动代码块。 - 执行完毕后,再次回到
while处重新判断条件。 - 只要条件持续为
True,循环就会不断执行;一旦条件变为False,循环即刻停止。
- 计算机首先判断
- 条件类型:条件可以是任何返回布尔值(
True或False)的表达式,例如比较运算或函数调用返回的结果。
while 循环执行逻辑详解
Section titled “while 循环执行逻辑详解”- 执行流程:
- 判断
while后条件是否为True。 - 若为真,执行下方缩进部分的内容,然后再次判断条件。
- 若仍为真,继续执行行动,直至条件为
False,推出循环。
- 判断
- 首次条件为假:若
while后面的条件在第一次判断时就为False,则行动一次也不会被执行。
while 循环初步应用示例:拍日落程序
Section titled “while 循环初步应用示例:拍日落程序”- 场景:当前天空亮度大约或等于500时,持续拍照片,直至亮度小于500。
- 优势:此例说明在条件合适结束未知的情况下,while循环比for循环更适合使用。
for 和 while 遍历列表比较
Section titled “for 和 while 遍历列表比较”- 三种遍历列表方式:前两段用 for range(len(list1)),第三段用 while。
range(len(list1)) 的 for 循环机制
Section titled “range(len(list1)) 的 for 循环机制”- 结束值:
range的结束值为list1长度。 - i 值变化:i 依次赋值为 0, 1, 2, … 直到长度-1。
- 长度-1 为最后一个元素索引。
- 效果:打印列表所有元素。
等价 while 循环步进
Section titled “等价 while 循环步进”- 初始:
i = 0,0 < len(list1),进入循环打印第一个元素。 - 循环:
i += 1后为 1,再次判断 1 < len(list1),打印第二个元素。 - 结束:i 达到列表长度,
i < len(list1)为假,推出循环。
- for 优势:更简单直观,代码行数更少。
- while 风险:更危险(如易死循环)。
while 循环的风险:无限循环
Section titled “while 循环的风险:无限循环”- 死循环成因:如果在
while循环中忘记更新循环条件(例如忘记对计数变量i进行递增操作),条件将始终为True,导致程序进入无限循环。 - 示例对比:
for 循环:自动管理迭代次数
Section titled “for 循环:自动管理迭代次数”for i in range(...):
...while 循环:需手动管理计数器
Section titled “while 循环:需手动管理计数器”i = 0
while i < ...:
...
i = i + 1 # 若漏掉此行,i 永远为 0,导致死循环while 与 for 的适用场景总结
Section titled “while 与 for 的适用场景总结”- for 循环:适用于有明确的循环对象或已知循环次数的场景,代码更简洁、更安全。
- while 循环:适用于循环次数未知,需根据特定条件持续运行的场景(如等待用户输入特定字符)。
实践:用户输入平均值计算器
Section titled “实践:用户输入平均值计算器”-
功能需求:持续接收用户输入的数字并求平均值,直到用户输入 ‘q’ 结束输入。
-
实现逻辑:
- 使用
while循环持续获取输入。 - 判断输入是否为 ‘q’,若是则跳出循环。
- 若非 ‘q’,将输入值累加并统计个数。
- 循环结束后计算并输出平均值。
- 使用
用户输入平均值计算器的实现逻辑
Section titled “用户输入平均值计算器的实现逻辑”-
核心思路:利用
while循环处理未知次数的用户输入,直到接收到终止信号 ‘q’。 -
关键步骤:
-
初始化变量:需要一个变量存储累加和,一个变量计数输入次数。
-
循环获取输入:使用
input()函数持续获取用户输入。 -
条件判断:检查输入是否为 ‘q’。
- 若是,退出循环。
- 若否,将输入字符串转换为数字(如
float()),累加到总和并增加计数器。
-
计算输出:循环结束后,通过
总和 / 计数计算平均值并输出。
-
-
代码实现示例:
sum_val = 0count = 0user_input = input("请输入数字(输入q结束):")
while user_input != 'q': sum_val += float(user_input) count += 1 user_input = input("请输入下一个数字(输入q结束):")
if count > 0: print("平均值是:", sum_val / count)while 循环条件逻辑
Section titled “while 循环条件逻辑”- 循环终止条件:在处理用户输入以 ‘q’ 结束的逻辑中,
while循环的条件应设置为user_input != 'q'。- 逻辑分析:只要输入的内容不等于 ‘q’,程序就继续执行循环体内的累加和计数操作;一旦输入为 ‘q’,条件变为
False,循环立即停止。
- 逻辑分析:只要输入的内容不等于 ‘q’,程序就继续执行循环体内的累加和计数操作;一旦输入为 ‘q’,条件变为
用户输入平均值计算器实现
Section titled “用户输入平均值计算器实现”- 初始化状态:在进入
while循环前,必须定义sum_val = 0和count = 0,用于在循环过程中持续更新总和与输入次数。 - 循环内输入更新:
- 循环体内的最后一行代码必须是再次调用
input()函数,以获取用户的下一次输入。 - 原因:若不更新
user_input的值,循环将陷入死循环,因为条件user_input != 'q'永远为真。
- 循环体内的最后一行代码必须是再次调用
- 数据处理:
- 使用
float(user_input)将输入的字符串转换为浮点数,以便进行数学运算。 - 每次循环将转换后的数值累加到
sum_val,并将count加 1。
- 使用
循环后的逻辑处理
Section titled “循环后的逻辑处理”- 条件检查:在循环结束后,应使用
if count > 0:进行判断,防止在没有任何输入的情况下直接进行除法运算,避免程序因除以零(ZeroDivisionError)而崩溃。
累加操作位置与代码优化
Section titled “累加操作位置与代码优化”- 位置要求:累加操作必须放在
while循环内、input()之前。- 否则只执行一次,或首次输入未累加。
- 若放
input()后,用户输入’q’时会尝试float('q')导致程序崩溃。
- 代码简写:
total += num # 等价于 total = total + num count += 1 # 等价于 count = count + 1完善平均值计算器逻辑
Section titled “完善平均值计算器逻辑”- 计算与输出:
- 循环结束后,计算平均值:
result = total / count。 - 使用
print输出最终结果,并结合str()将浮点数转换为字符串进行拼接。
- 循环结束后,计算平均值:
潜在的除零隐患
Section titled “潜在的除零隐患”- 问题场景:若用户在第一次输入时直接输入 ‘q’,则
count保持为 0,直接执行total / count会引发ZeroDivisionError。 - 解决方案:在计算平均值前增加条件判断:
if count > 0: result = total / count print("输入的数字平均值为:" + str(result))逻辑漏洞分析
Section titled “逻辑漏洞分析”- 空输入风险:如果用户在第一次输入即选择终止(输入 ‘q’),程序必须能够优雅地退出,而不是尝试计算空集的平均值。
- 数学原则:在 Python 及数学逻辑中,0 除以 0 是不允许的,因此必须显式地进行
count > 0的检查以确保程序的健壮性。
平均值计算器运行测试
Section titled “平均值计算器运行测试”- 正常输入测试:输入多个数字后输入
q,正确输出平均值。 - 立即退出测试:首次输入
q,程序优雅处理,无错误输出平均值。
春节短信个性化实践
Section titled “春节短信个性化实践”- 问题:群发祝福短信易显复印,降低诚恳感。
- 解决方案:在内容插入收件人姓名,两处位置需动态替换。
- 实现思路:用 for 循环 遍历联系人列表,将姓名拼接到短信模板正确位置。
- 优势:代码自动化,编写长字符串不麻烦。
字符串格式化方法:format()
Section titled “字符串格式化方法:format()”- 痛点:使用字符串拼接(
+)处理多处变量插入时,代码会被频繁打断,导致可读性差且容易出错。 - 解决方案:使用
format()方法,通过占位符{}优雅地插入变量。
message_content = """律回春渐,新元肇启。新岁甫至,福气东来。金{0}贺岁,欢乐祥瑞。金{0}敲门,五福临门。给{1}及家人拜年啦!新春快乐,{0}年大吉!""".format(year, name)- 原理:
- 大括号
{}作为占位符,标记需要替换的位置。 - 大括号内的数字(如
{0},{1})对应format()函数括号内参数的索引位置。 0代表第一个参数year,1代表第二个参数name。
- 大括号
- 优势:保持了长字符串的完整结构,逻辑直观,避免了繁琐的引号和加号嵌套。
使用 format() 方法进行字符串格式化
Section titled “使用 format() 方法进行字符串格式化”- 解决痛点:使用
+进行字符串拼接时,长字符串会被频繁打断,导致代码结构支离破碎、可读性差。 - 核心原理:使用花括号
{}作为占位符,配合.format()方法将变量按索引顺序填充。
message_content = """律回春渐,新元肇启。新岁甫至,福气东来。金{0}贺岁,欢乐祥瑞。金{0}敲门,五福临门。给{1}及家人拜年啦!新春快乐,{0}年大吉!""".format(year, name)- 索引对应关系:
{0}:对应format()函数内的第一个参数(即year)。{1}:对应format()函数内的第二个参数(即name)。
- 优势:完整保留了长字符串的文本结构,逻辑直观,避免了繁琐的引号闭合和加号连接。
使用关键字参数进行 format 替换
Section titled “使用关键字参数进行 format 替换”- 灵活性提升:除了使用索引,还可以使用关键字参数,使代码更具可读性。
- 实现方式:在
format()中直接指定变量名,并在字符串中使用对应的名称作为占位符。
message_content = """金{current_year}贺岁,欢乐祥瑞。给{receiver_name}及家人拜年啦!""".format(receiver_name=name, current_year=year)- 优势:
- 即使
year和name在字符串中多次出现,也能通过关键字准确匹配。 - 字符串中占位符的顺序不再受限于
format()参数的顺序。
- 即使
f-字符串 (f-string) 的使用
Section titled “f-字符串 (f-string) 的使用”- 语法特点:在字符串引号前添加字母
f,即可直接在花括号内引用变量。 - 执行机制:花括号内的内容会被直接求值,并自动插入到字符串中。
message_content = f"""新春快乐,{year}年大吉!"""- 对比:相比
format()方法,f-字符串写法更加简洁,直接将变量名嵌入字符串中,是现代 Python 开发中推荐的格式化方式。
浮点数格式化输出
Section titled “浮点数格式化输出”- 需求:在打印浮点数时,经常需要限制小数点后的位数,避免输出过长的小数。
- 实现方式:在格式化占位符中添加
: .nf,其中n为保留的小数位数。.2f表示保留两位小数。
格式化语法对比
Section titled “格式化语法对比”- 使用&;
.format()&;方法:
在占位符中指定格式
Section titled “在占位符中指定格式”print(“{0} 的当前绩点为: {1:.2f}”.format(name, gpa))
- **使用 f-string**: ```python直接在变量后的花括号内添加格式说明
Section titled “直接在变量后的花括号内添加格式说明”print(f”{name} 的当前绩点为: {gpa:.2f}“)
扇形面积计算程序
Section titled “扇形面积计算程序”- 公式:$$Area = \frac{\theta}{360} \times \pi \times r^2$$
- 实现逻辑:
- 定义变量
theta(角度) 和r(半径)。 - 使用
math.pi获取圆周率。 - 计算并输出结果。
- 定义变量
import math
theta = 60r = 10area = (theta / 360) * math.pi * (r ** 2)print(f"扇形面积为: {area:.2f}")代码重复问题与 DRY 原则
Section titled “代码重复问题与 DRY 原则”- 重复场景:程序中多处需计算扇形面积,仅角度和半径不同,即产生一堆相似代码。
- 示例:原型角 160°、半径 30,π取近似 3.14。
DRY 原则 (Don’t Repeat Yourself)
Section titled “DRY 原则 (Don’t Repeat Yourself)”- 核心理念:不要重复自己,避免做代码复读机。
- 违反后果:重复代码增加维护难度,修改时易遗漏导致不一致。
- 解决方案:使用函数封装重复逻辑。
Python 内置函数调用
Section titled “Python 内置函数调用”- 示例:
print、sum等自带函数,各负责特定任务。 - 调用方式:
函数名(参数),如print('hello')。
函数定义语法与规则
Section titled “函数定义语法与规则”- 函数类比:制作负责特定任务的“机器”,定义一次,后续直接调用即可,无需重复编写代码。
- 定义语法:
def 函数名():函数体代码(使用缩进划分范围)
Section titled “函数体代码(使用缩进划分范围)”- `def`:定义函数的关键字,后跟函数名、括号和冒号。 - 缩进:划分函数体代码范围,与 if/for 类似。- **实践步骤**:将之前扇形面积计算代码整体移入函数定义中。- **执行规则**:定义时函数体内代码**不执行**,仅在调用时(函数名括号)才实际运行。函数的局限性与参数引入
Section titled “函数的局限性与参数引入”- 当前痛点:定义的
calculate_sector_1()函数只能计算固定数值(角度160,半径30)。若要计算其他扇形,需重复定义calculate_sector_2()等,这导致了新的代码重复。 - 解决方案:引入参数 (Parameters),使函数像“通用机器”一样,根据输入的不同原料(角度和半径)输出不同的结果。
参数化函数的类比与实现
Section titled “参数化函数的类比与实现”- 类比:将函数比作“包子机”。
- 原始函数:只能做猪肉白皮包子。
- 参数化函数:可以根据输入的肉馅和面粉颜色,自动生产对应口味和颜色的包子。
- 参数化逻辑:
- 在定义函数时,在括号内设置变量名作为占位符。
- 调用函数时,传入具体数值,函数内部逻辑会根据这些数值动态执行。
函数参数化的代码实践
Section titled “函数参数化的代码实践”- 动态化改造:
def calculate_sector(central_angle, radius):内部逻辑使用传入的参数进行计算
Section titled “内部逻辑使用传入的参数进行计算”sector\_area = (central\_angle / 360) \* 3.14 \* (radius \*\* 2)
print(f"扇形面积为: {sector\_area}")调用时传入具体数据
Section titled “调用时传入具体数据”calculate_sector(160, 30)
calculate_sector(60, 15)
- **优势**:极大地提高了代码的复用性,只需编写一次逻辑,即可处理无数种不同的输入情况。通用扇形函数优化实践
Section titled “通用扇形函数优化实践”- 移除编号:将函数名
calculate_sector_1中的 1 全部删除,使其通用化,不限于第一个扇形。 - 添加参数:在括号内放入
central_angle(圆心角角度)和radius(半径)。 - 删除冗余赋值:传入参数后,自动赋值给函数内变量,无需手动复值,可移除这两行代码。
- 成果:获得计算并打印任意圆心角和半径的扇形面积函数。
- 代码压缩:原本多行重复代码,封装函数后简化为几行调用。
- 预告:此函数还可以做得更好,具体内容下视频分解。
函数参数的局限与作用域
Section titled “函数参数的局限与作用域”- 当前代码结构:
def calculate_sector(central_angle, radius): sector_area = (central_angle / 360) * 3.14 * radius ** 2 print(f'扇形面积为: {sector_area}')- 作用域 (Scope) 概念:
- 局部变量:在函数内部定义的变量(如
sector_area)属于局部变量,其生命周期仅限于函数内部。 - 访问限制:函数外部无法直接访问函数内部的变量。即便函数执行后,外部也无法通过
sector_area获取计算结果,因为该变量在函数运行结束后即被销毁。
- 局部变量:在函数内部定义的变量(如
局部变量与外部访问问题
Section titled “局部变量与外部访问问题”- 直观类比:函数内部就像一个封闭的院子,内部定义的变量是院里的树,院外的人(外部程序)无法直接看到或获取这些树。
- 示例演示:
def func(): a = 3
func() print(a) # 报错:NameError,外部无法访问内部定义的 a- 结论:若需在函数外部使用计算结果,仅依靠
print打印是不够的,必须引入后续机制(如返回值)来传递数据。
局部变量的作用域限制
Section titled “局部变量的作用域限制”- 生命周期:函数内部定义的变量(局部变量)仅在函数执行期间存在,函数运行结束后即被销毁。
- 访问限制:函数外部无法直接引用函数内部的变量,尝试访问会导致
NameError。 - 示例:
def func(): a = 3
func() print(a) # 报错:NameError: name 'a' is not defined- 结论:若需在函数外部使用计算结果,仅依靠函数内的
print是不够的,必须引入return机制将数据从函数“内部”传递到“外部”。
return 语句的作用
Section titled “return 语句的作用”-
功能:将函数内部计算出的值返回给调用者,使得函数执行后的结果可以被外部变量接收或进一步处理。
-
语法:在函数最后一行使用
return关键字后跟要返回的内容。 -
执行机制:
- 函数逐行执行内部语句。
- 函数调用完成后,
return将指定的值“带回”到调用位置。 - 返回值可以赋值给变量、直接打印或用于其他逻辑。
-
代码示例:
def func(): a = 3 return a
return_value = func() # 将函数返回的 3 赋值给变量 print(return_value) # 输出: 3- 默认行为:若函数中未写
return语句,函数执行完毕后默认返回None。
Python 函数的默认返回值
Section titled “Python 函数的默认返回值”- 默认行为:如果函数体中没有显式编写
return语句,函数执行完毕后会自动返回None。 - 应用场景:像
print()或list.append()这类函数,其核心目的是执行某种操作(如打印到屏幕或修改列表),而非返回计算结果,因此它们在 Python 中本质上都是返回None的函数。 - 调用建议:对于返回
None的函数,通常直接调用即可,无需将其赋值给变量。
函数返回值与业务逻辑的结合
Section titled “函数返回值与业务逻辑的结合”- 计算与输出的分离:
- 仅使用
print的函数类似于“只做包子不给食客”的机器,外部无法获取包子(计算结果)。 - 引入
return语句后,函数可以将计算结果“带回”给调用方,从而允许后续逻辑(如变量赋值、进一步计算)使用该结果。
- 仅使用
- 示例对比:
- 无&;
return:调用函数仅触发内部打印,外部无法获取数据。 - 有&;
return:调用函数时,外部变量可以接收函数返回的值。
- 无&;
示例:通过 return 将结果传递给外部
Section titled “示例:通过 return 将结果传递给外部”def calculate_sector(central_angle, radius):
sector\_area = (central\_angle / 360) \* 3.14 \* radius \*\* 2
return sector\_area外部通过变量接收返回值
Section titled “外部通过变量接收返回值”sector_area_1 = calculate_sector(160, 30)
- **类比理解**:`return` 就像是函数执行后的“打包带走”功能,没有它,函数内部的计算成果在函数运行结束后即被销毁。BMI 计算器函数实践
Section titled “BMI 计算器函数实践”-
公式:BMI = 体重 / (身高²)
-
函数要求:
- 计算任意体重/身高的 BMI 值
- 执行过程中打印“您的 BMI 分类为 [类名]”(如偏瘦、正常、肥胖)
- 返回计算出的 BMI 值
-
开始定义:
def 函数名():
BMI 函数分类逻辑实现
Section titled “BMI 函数分类逻辑实现”- 条件分支:
- BMI > 18.5 后,判断 BMI < 30 → 偏胖
- BMI > 30 → 肥胖(用 else 概括)
- 打印输出:
print(f"您的bmi分类为{category}")- 返回结果:
return BMI- 测试:函数编写完成,可进行测试验证。
BMI 函数返回值外部捕获
Section titled “BMI 函数返回值外部捕获”- 演示步骤:函数调用后打印BMI分类(如1.870对应的分类)。
- 捕获返回值:创建变量复制函数的return值。
- 外部打印:打印变量查看BMI计算结果。
- 效果:分类打印后,计算结果也成功输出。
result = calculate_BMI(...) # 接收return值print(result) # 输出BMI数值Python 标准库与模块化编程
Section titled “Python 标准库与模块化编程”内置函数与模块的区别
Section titled “内置函数与模块的区别”- 内置函数:如
sum()、print()、len()等,无需额外导入即可直接使用,适用于高频通用任务。 - 标准库模块:当内置函数无法满足需求时(如计算中位数),可使用 Python 标准库中的模块。
- 模块定义:本质上是一个包含函数和变量的 Python 程序,通过导入即可复用其中的功能。
模块引入与使用
Section titled “模块引入与使用”- 示例:statistics 模块
statistics模块提供了统计相关函数,例如median()用于计算中位数。- 引入方式:
import statistics。 - 调用方式:
statistics.median(data_list)。
模块化编程的优势
Section titled “模块化编程的优势”- DRY 原则 (Don’t Repeat Yourself):通过调用现成模块或自定义函数,避免重复编写逻辑,提高开发效率。
- 代码简化:通过引入模块,复杂的逻辑(如手动排序及索引计算中位数)可以被压缩为极简的代码调用。
为什么有些函数不是内置的?
Section titled “为什么有些函数不是内置的?”- 内置函数:属于“高频家具”(如电视),随时可用。
- 模块函数:属于“低频工具”(如烧烤炉),存放在“仓库”(模块)中,需要时再取出使用,避免占用全局命名空间,保持语言简洁。
模块导入的三种方式
Section titled “模块导入的三种方式”import 模块名:使用模块名.函数名()调用。from 模块名 import 函数名:直接使用函数名()调用。from 模块名 import *:导入模块内所有内容(不推荐,易产生命名冲突)。
模块导入方式的调用细节与注意事项
Section titled “模块导入方式的调用细节与注意事项”- 第一种(import 模块名):
- 调用时必须使用模块名.函数名或模块名.变量名。
- 示例:
import statistics后用statistics.median()。
- 第二种(from 模块名 import 函数名):
- 多个函数/变量用逗号分隔。
- 好处:直接调用函数名(),无需模块名前缀。
- 第三种(from 模块名 import *):
- 导入模块所有内容,直接调用。
- 适合同一模块多个内容,但不推荐:易产生命名冲突。
模块导入的命名冲突风险
Section titled “模块导入的命名冲突风险”- 命名冲突场景:
- 若同时从模块 A 和模块 B 使用
from ... import *导入,且两者都包含同名函数(如abc()),则后导入的模块会覆盖前者的定义。 - 调用
abc()时,程序无法明确指向,导致逻辑混乱或调用错误。
- 若同时从模块 A 和模块 B 使用
- 最佳实践建议:
- 优先使用
import 模块名:通过模块名.函数名()明确调用来源,避免命名冲突。 - 若必须使用
from ... import ...,应明确指定所需的特定函数名,而非使用*导入所有内容。
- 优先使用
利用官方文档探索标准库
Section titled “利用官方文档探索标准库”- Python 官方文档 (docs.python.org):
- 提供了标准库中所有内置模块的完整索引。
- 模块涵盖了字符串处理、日期时间、文件操作、正则表达式、数学计算等多种功能。
- 点击模块名称即可查看其包含的所有函数、变量及其详细用法说明。
- 学习路径:
- 遇到编程需求时,先查询标准库文档,避免重复造轮子。
- 通过文档示例(如
decimal模块的精度处理)学习如何正确调用模块内的函数。
深入理解模块源码与调用机制
Section titled “深入理解模块源码与调用机制”- 查看模块源码:
- 在 PyCharm 中,可以通过快捷键直接跳转到函数定义,查看其内部实现逻辑。
- Windows系统:按住
Ctrl键并点击函数名。 - macOS系统:按住
Command键并点击函数名。
- 代码复用与效率:
- 引入第三方库(非 Python 官方提供)能极大扩展程序功能。
- 引入第三方库的语法与标准库一致,但前提是必须先通过包管理工具安装(类似从家具店将家具搬入自家仓库,再进行后续使用)。
第三方库的安装与使用
Section titled “第三方库的安装与使用”-
安装与引入的类比:
- 安装 (pip install):将家具从家具店搬入自家仓库(从互联网下载并配置到本地环境)。
- 引入 (import):将仓库里的家具拿出来使用(在代码中加载模块)。
-
第三方库的获取:
- 通过 PyPI.org 搜索并查看第三方库的介绍与用法。
-
安装命令:
- 在终端 (Terminal) 执行:
pip install 库名(例如pip install akshare)。
- 在终端 (Terminal) 执行:
-
使用流程:
- 安装:
pip install(只需执行一次)。 - 引入:
import(在代码中调用)。 - 调用:使用库中的函数或方法。
- 安装:
实践:使用第三方财经库
Section titled “实践:使用第三方财经库”- 查找与调用:
- 在 PyPI 搜索特定功能的库(如 AkShare 财经数据接口)。
- 安装后使用
import引入,即可调用库内封装好的复杂函数(如get_cffex_daily()获取期货数据)。
- 优势:极大扩展了 Python 的原生功能,通过复用他人构建的复杂逻辑,显著提高开发效率。
面向对象编程 (Object-Oriented Programming) 基础
Section titled “面向对象编程 (Object-Oriented Programming) 基础”面向过程与面向对象的思维差异
Section titled “面向过程与面向对象的思维差异”- 面向过程 (Procedure-Oriented):关注执行步骤,将程序视为一系列指令的集合,直接聚焦于按顺序执行动作。
- 面向对象 (Object-Oriented):关注对象 (Object) 本身,将任务分解到各个对象上,描述对象具备的属性(变量)和行为(函数),最后通过对象间的交互完成任务。
类与对象的概念
Section titled “类与对象的概念”- 类 (Class):对象的模板或蓝图,定义了该类对象共有的属性和方法。
- 对象 (Object):类的具体实例。例如,人、洗衣机都是对象。
- 属性 (Attribute):类中定义的变量,用于描述对象的状态。
- 方法 (Method):类中定义的函数,用于描述对象的行为。
面向对象编程的优势
Section titled “面向对象编程的优势”- 逻辑封装:将相关属性和方法绑定在一起,不仅结构更清晰,还能更优雅地处理复杂逻辑。
- 复用与扩展:通过定义类,可以轻松创建多个对象,并让它们执行各自的方法,避免了面向过程编程中重复编写步骤的繁琐。
编程思维转变示例:洗衣机
Section titled “编程思维转变示例:洗衣机”- 面向过程:
放(“衣服”, “洗衣机”)
开机(“洗衣机”)
清洗(“洗衣机”)
烘干(“洗衣机”)
- **面向对象**: ```python class 洗衣机: def 清洗(self, 需清洗物品): ... def 烘干(self, 需烘干物品): ...将逻辑封装在类中,通过对象调用
Section titled “将逻辑封装在类中,通过对象调用”我的洗衣机 = 洗衣机()
我的洗衣机.清洗(“衣服”)
我的洗衣机.烘干(“衣服”)
面向对象编程中的属性封装
Section titled “面向对象编程中的属性封装”- 属性作为状态存储:
- 在类中,
容量可以直接作为对象的属性(self.容量)进行设置。 - 优势:当对象被创建时即完成初始化,后续调用任何方法(如
清洗或烘干)时,无需再将容量作为参数反复传入,直接通过self即可获取。
- 在类中,
- 逻辑清晰度:
- 将数据(属性)与行为(方法)绑定在对象内部,使得逻辑更加聚焦,减少了函数参数传递的冗余。
面向对象的三大特性
Section titled “面向对象的三大特性”- 封装 (Encapsulation):
- 将内部实现细节隐藏,仅通过外部接口(方法)进行访问和操作。
- 外部使用者只需知道方法名及其功能,无需关心内部如何实现。
- 继承 (Inheritance):
- 允许子类继承父类的属性和方法,实现代码复用。
- 多态 (Polymorphism):
- 允许不同对象对同一消息做出不同的响应。
封装的实践意义
Section titled “封装的实践意义”- 接口与实现分离:
- 类就像一个黑盒,
__init__、清洗、烘干等函数是其对外提供的接口。 - 使用者通过调用这些接口来驱动对象,不需要了解内部具体的计算逻辑或实现细节。
- 类就像一个黑盒,
继承 (Inheritance) 的核心逻辑
Section titled “继承 (Inheritance) 的核心逻辑”- 定义:允许创建具有层级关系的类,子类可以继承父类的属性和方法。
- 现实类比:儿子继承父亲,父亲继承爷爷,体现了代码的从属与复用关系。
- 解决的问题:
- 当多个类(如“小学生”和“大学生”)拥有大量共同属性(学号、年级)和方法(去学校)时,直接编写会导致大量重复代码。
- 通过引入“学生”父类,将共有逻辑封装其中,子类直接继承,从而减少代码冗余。
多态 (Polymorphism) 的核心逻辑
Section titled “多态 (Polymorphism) 的核心逻辑”- 定义:同样的接口(方法名),针对不同的对象,表现出不同的具体行为。
- 示例:
- 小学生执行
写作业()可能是在做简单的算术题。 - 大学生执行
写作业()可能是在做复杂的积分运算。
- 小学生执行
- 核心价值:调用者无需关心对象具体的类类型,只需通过统一的接口调用,程序会自动根据对象类型执行对应的逻辑。
面向对象编程中的多态示例
Section titled “面向对象编程中的多态示例”- 多态表现:
- 接口(方法名)统一,但对象类型不同,行为逻辑也不同。
- 示例:
写作业()方法在“小学生”对象中调用表现为简单的加减法,在“大学生”对象中调用则表现为复杂的积分运算。
- 核心价值:
- 调用者无需关心对象具体的类类型,只需通过统一接口调用,程序会自动根据对象类型执行对应的逻辑。
类中属性的初始化与赋值
Section titled “类中属性的初始化与赋值”__init__&;方法:- 类中定义的特殊方法,用于在创建对象时自动执行初始化逻辑。
- 示例:
self.name = "Lambton"将name属性绑定到该对象实例上。
self&;的作用:self代表当前创建的对象实例。- 若赋值时不加
self.(如name = "Lambton"),Python 会将其视为普通的局部变量,而非对象的属性,导致该值无法在对象外部通过对象.属性名访问。
对象实例化与属性访问
Section titled “对象实例化与属性访问”- 创建对象:
- 语法:
变量名 = 类名()。 - 过程:调用类名时,会自动触发
__init__方法,并将该对象作为self传入。 - 注意:
self参数无需手动传入,Python 会自动处理。
- 语法:
- 获取属性:
- 使用点号操作符:
对象.属性名(例如print(cat1.name))。
- 使用点号操作符:
动态属性赋值与 init 参数化
Section titled “动态属性赋值与 init 参数化”- 问题:硬编码属性(如
self.name = "Lambton")导致所有实例属性相同,缺乏灵活性。 - 优化:在
__init__中添加参数,实现实例化时动态赋值。
class CuteCat: def __init__(self, cat_name, cat_age, cat_color): self.name = cat_name self.age = cat_age self.color = cat_color实例化时传入参数
Section titled “实例化时传入参数”cat1 = CuteCat(“Jojo”, 2, “橙色”)
- **原理**:创建对象时(`CuteCat("Jojo", ...)`),Python 自动将传入的参数传递给 `__init__` 方法,从而实现每个对象拥有独特的属性值。面向对象编程的里程碑
Section titled “面向对象编程的里程碑”- 掌握属性封装与对象实例化,标志着从简单的指令执行转向面向对象编程,能够构建更具扩展性和逻辑性的程序结构。
定义对象方法 (Methods)
Section titled “定义对象方法 (Methods)”- 方法定义:方法本质上是定义在类内部的函数,用于描述对象能执行的行为(如“思考”或“叫唤”)。
- 定义规则:
- 语法与普通函数定义类似,但在类内部定义。
- 必须包含
self参数,以便在方法内部访问该对象的属性。
- 调用逻辑:
- 通过
对象名.方法名()的方式调用。 - Python 会自动将调用该方法的对象实例作为
self传入,无需手动指定。
- 通过
方法与函数的类比
Section titled “方法与函数的类比”- 函数:独立执行逻辑的工具。
- 方法:封装在对象内部的逻辑,能够直接操作该对象的属性(如
self.name),实现数据与行为的绑定。 - 方法定义规则:
- 方法本质上是类内部定义的函数,用于描述对象行为。
- 必须包含
self参数,以便方法内部能够访问该对象的属性(如self.age)。 - 定义语法与普通函数类似,但必须缩进在
class内部。
方法的参数与调用机制
Section titled “方法的参数与调用机制”- self 的作用:
self代表对象自身,用于将方法与特定实例绑定,从而在方法内获取或修改该实例的属性。- 示例:在
speak(self)方法中,通过self.age获取该猫咪对象的年龄。
- 调用方式:
- 使用
对象名.方法名()调用。 - Python 会自动将调用该方法的对象实例作为
self传入,无需手动指定。
- 使用
方法调用逻辑实践
Section titled “方法调用逻辑实践”- 动态行为演示:
- 方法可以根据对象的属性值产生不同的输出,例如根据
self.age的大小决定“喵”的重复次数。 - 字符串乘法:
"喵" * self.age,表示将字符串重复age次。
- 方法可以根据对象的属性值产生不同的输出,例如根据
- 代码示例:
class CuteCat: def __init__(self, cat_name, cat_age, cat_color): self.name = cat_name self.age = cat_age self.color = cat_color
def speak(self): print("喵" * self.age)
cat1 = CuteCat("Jojo", 1, "橙色") cat1.speak()- 执行效果:
- 若
cat1.age为 1,输出喵。 - 若
cat1.age为 3,输出喵喵喵。
- 若
- 核心价值:方法实现了对象数据(属性)与行为(逻辑)的统一,使得程序能够根据不同对象的状态展现出差异化的行为。
方法的参数扩展与逻辑封装
Section titled “方法的参数扩展与逻辑封装”- 方法接收参数:
- 类的方法不仅可以使用
self访问属性,还可以像普通函数一样接收额外参数。 - 示例:定义
think(self, content)方法,将思考的内容作为参数传入,实现动态行为。
- 类的方法不仅可以使用
- 调用逻辑:
- 调用时,
self参数由 Python 自动处理,仅需在括号内填入自定义参数。 - 示例:
cat1.think("现在去沙发还是去抓猫抓板")。
- 调用时,
实践:学生类定义与属性设置
Section titled “实践:学生类定义与属性设置”-
目标:创建一个
Student类,包含姓名、学号及语文、数学、英语三科成绩。 -
实现步骤:
- 使用
class Student:定义类。 - 使用
def __init__(self, ...):初始化属性,将学生信息绑定到对象实例。 - 编写方法实现成绩设置与打印功能。
- 使用
类定义的关键语法
Section titled “类定义的关键语法”- 类名规范:使用
class关键字后跟大写开头的类名(如Student)。 - 构造方法:使用
__init__(注意双下划线)作为初始化方法,PyCharm 会自动补全self参数。 - 属性绑定:在
__init__中通过self.变量名 = 参数名将传入的参数存储为对象的属性,保证每个实例拥有独立的数据。
学生类属性初始化实践
Section titled “学生类属性初始化实践”- 属性绑定逻辑:
- 在
__init__方法中,使用self.name = name和self.student_id = student_id将传入的参数绑定到对象实例上。 - 这种方式确保每个学生对象拥有独立的姓名和学号数据。
- 在
成绩字典的初始化
Section titled “成绩字典的初始化”- 成绩存储设计:
- 使用字典存储三科成绩,键为科目名称(字符串),值为成绩(初始设为 0)。
- 字典定义:
self.grades = {'语文': 0, '数学': 0, '英语': 0}。
- 初始化策略:
- 若所有学生对象的初始成绩均相同,则无需通过参数传入,直接在
__init__中定义即可,简化了实例化时的参数传递。
- 若所有学生对象的初始成绩均相同,则无需通过参数传入,直接在
学生类对象实例化与属性访问
Section titled “学生类对象实例化与属性访问”- 对象实例化操作
- 通过
类名(参数)的方式创建实例,例如chen = Student("小陈", "108618")。 - 实例化时,
__init__方法被自动调用,传入的参数被赋值给对应的self属性。
- 通过
- 属性访问演示
- 使用点号操作符直接读取实例属性:
对象名.属性名。 - 示例:
print(chen.name)可获取该对象的姓名。
- 使用点号操作符直接读取实例属性:
- 对象方法调用
- 同样使用点号操作符调用类中定义的方法,例如
对象名.方法名()。 - 验证:通过
print(zang.grades)可以直接访问并打印该对象初始化后的成绩字典。
- 同样使用点号操作符调用类中定义的方法,例如
学生类方法定义与成绩修改逻辑
Section titled “学生类方法定义与成绩修改逻辑”- 定义&;
set_grade&;方法-
在
Student类中定义set_grade(self, course, grade)方法,用于更新特定科目的成绩。 -
方法内部逻辑:
- 检查
course(科目名称)是否存在于self.grades字典的键中。 - 若存在,则更新该科目的分数为传入的
grade值。 - 若不存在,则忽略该操作,避免非法科目名称导致的错误。
- 检查
-
def set_grade(self, course, grade): if course in self.grades: self.grades[course] = grade- 方法设计的关键点
- 逻辑封装:将成绩更新的查验逻辑封装在方法内部,调用者只需提供科目和分数,无需关心字典是否存在该键。
- 参数传递:
self自动处理,course和grade作为外部传入的参数,实现了对象行为的动态化。 - 防御性编程:通过
if course in self.grades判断,确保了程序的健壮性,防止无效数据污染成绩字典。
学生类方法实现与成绩更新逻辑
Section titled “学生类方法实现与成绩更新逻辑”- 方法定义 (
set_grade)- 在
Student类中定义方法以封装成绩更新逻辑,确保数据操作的规范性与安全性。 - 语法:
def set_grade(self, course, grade): - 逻辑:通过
if course in self.grades:检查科目是否存在,仅在键存在时更新分数值,有效防止非法科目导致的错误。
- 在
成绩更新实践与验证
Section titled “成绩更新实践与验证”- 调用示例
- 实例化对象后,通过
对象名.set_grade(科目, 分数)调用方法。 - 示例:
zang.set_grade("数学", 95)将小臧的数学成绩更新为 95。
- 实例化对象后,通过
- 运行结果
- 验证:通过
print(zang.grades)输出字典,确认数学成绩已从初始值 0 变为 95。
- 验证:通过
打印学生所有成绩的方法
Section titled “打印学生所有成绩的方法”- 方法设计 (
print_grades)- 定义
print_grades(self)方法以统一输出学生信息及成绩。 - 优势:无需额外参数,直接通过
self.grades访问实例内部字典,实现数据的即时读取。
- 定义
- 代码实现
def print_grades(self): print(self.name) print(self.grades)- 逻辑优化
- 在打印成绩前,可先打印
self.name以增强输出的可读性,明确当前显示的是哪位学生的成绩。
- 在打印成绩前,可先打印
遍历字典打印成绩
Section titled “遍历字典打印成绩”- 在
print_grades方法中,使用for循环遍历self.grades字典,可以更优雅地逐行展示科目与成绩。 - 循环结构示例:
def print_grades(self): print(f"学生{self.name} (学号: {self.student_id}) 的成绩为:") for course in self.grades: print(f"{course}: {self.grades[course]}分")- 逻辑说明:
for course in self.grades:直接遍历字典的键(科目名称)。self.grades[course]:通过键获取对应的值(分数)。- 这种方式比直接打印整个字典更具可读性,且符合面向对象中“对象展示自身状态”的封装原则。
修改并打印学生成绩演示
Section titled “修改并打印学生成绩演示”- 实践操作:
- 修改小陈的语文成绩和数学成绩(使用
set_grade方法)。 - 调用
print_grades方法(可能指PrintGrate,打印所有成绩)。
- 修改小陈的语文成绩和数学成绩(使用
- 运行结果:
- 显示更新后的新成绩,全部正确展示。
- 验证要点:
- 确认成绩修改生效,方法调用成功输出完整成绩列表。
人类与小猫的属性行为示例与继承引入
Section titled “人类与小猫的属性行为示例与继承引入”人类与小猫的属性与行为对比
Section titled “人类与小猫的属性与行为对比”- 人类属性:名字、性别、两只眼睛、没有尾巴。
- 人类行为:呼吸、阅读。
- 小猫属性:名字、性别、两只眼睛、有尾巴。
- 小猫行为:呼吸、阿屎、不能阅读、抓沙发。
发现代码重复时的 DRY 原则
Section titled “发现代码重复时的 DRY 原则”- 复读记代码:编写相似逻辑时(如人类和小猫的共同属性行为),发现大量重复。
- DRY 原则(Don’t Repeat Yourself):不要重复你自己,追求最小重复代码。
继承作为代码复用解决方案
Section titled “继承作为代码复用解决方案”- 继承特征:面向对象的重要机制,用于改写重复代码。
- 应用:通过继承提取共同属性和行为,避免为每个对象重复编写相似逻辑。
继承与代码复用实践
Section titled “继承与代码复用实践”- 继承的实现语法
- 在定义子类时,在类名后的括号中指定父类名称即可实现继承。
- 语法示例:
class Human(Mammal):表示Human类继承自Mammal类。
- 继承的执行逻辑
- 属性继承:子类自动获得父类的属性初始化逻辑。若子类没有自己的
__init__方法,实例化子类时会自动调用父类的构造函数,确保子类对象具备父类定义的属性。 - 方法继承:子类自动拥有父类定义的所有方法。调用子类对象的这些方法时,程序会直接执行父类中定义的逻辑。
- 属性继承:子类自动获得父类的属性初始化逻辑。若子类没有自己的
- 方法调用优先级
- 当子类和父类拥有同名方法时,程序会优先调用子类自身的方法。
- 只有当子类中不存在该方法时,程序才会向上查找并调用父类的方法。
- 继承的实际应用
- 将共有属性(如姓名、性别、眼睛数量)和共有行为(如呼吸、排泄)封装在父类(如
Mammal)中。 - 子类(如
Human或Cat)只需定义特有的属性或方法,从而大幅减少重复代码,遵循 DRY 原则。
- 将共有属性(如姓名、性别、眼睛数量)和共有行为(如呼吸、排泄)封装在父类(如
子类构造函数与 super() 调用
Section titled “子类构造函数与 super() 调用”子类独立 __init__ 的问题
Section titled “子类独立 __init__ 的问题”- 人类和小猫各自的 Hestel 属性值不同,不能只在父类中硬编码。
- 若子类单独定义
__init__,实例化时优先调用子类构造函数,导致实例仅获得 Hestel 属性,丢失父类的 name、sex 等属性。
手动复制属性的重复问题
Section titled “手动复制属性的重复问题”- 解决方案:在子类
__init__中全部重写 name、sex 等属性代码,但造成重复代码。
使用 super() 的优雅解决方案
Section titled “使用 super() 的优雅解决方案”- super():返回当前类的父类。
- 在子类
__init__中调用super().__init__(),自动执行父类构造函数。 - 结果:子类实例同时获得父类属性(性别、眼睛数量等)和自身特有属性(Hestel)。
继承的核心价值
Section titled “继承的核心价值”- 成功移除重复的属性和方法代码行。
- 实例化后,属性获取和方法调用与之前完全相同,无任何区别。
继承使用技巧
Section titled “继承使用技巧”- 判断标准:如果 A 和 B 可以说成 A 是 B 的一种,即可使用继承。
员工系统继承实践
Section titled “员工系统继承实践”- 员工分类:全职员工、兼职员工。
- 共同属性:姓名、功耗。
- 共同方法:打印信息(输出姓名和功耗)。
- 全职特有:月薪属性,按月发工资。
- 兼职特有:按天发工资,有日期、每月工作天数属性,计算月工资方法不同。
继承设计思路
Section titled “继承设计思路”- 父类:
Employee,封装姓名、功耗及打印信息方法。 - 子类:全职(
FullTimeEmployee)和兼职(PartTimeEmployee)继承Employee。 - 子类扩展:各自添加特有属性和月工资计算方法。
- 先定义
Employee父类。
员工系统父类 Employee 定义
Section titled “员工系统父类 Employee 定义”- 属性初始化:在
__init__中统一管理所有员工的共有属性name和id。 - 方法封装:定义
print_info方法,统一处理员工基本信息的打印逻辑,避免在子类中重复编写相同的输出代码。
class Employee: def __init__(self, name, id): self.name = name self.id = id
def print_info(self): print(f"员工名字: {self.name}, 工号: {self.id}")子类继承与扩展实现
Section titled “子类继承与扩展实现”- 全职员工类&;
FullTimeEmployee- 继承
Employee父类,通过super().__init__(name, id)复用父类构造函数。 - 扩展特有属性:
monthly_salary(月薪)。
- 继承
class FullTimeEmployee(Employee): def __init__(self, name, id, monthly_salary): super().__init__(name, id) self.monthly_salary = monthly_salary员工系统子类完整实现与测试
Section titled “员工系统子类完整实现与测试”兼职员工月工资计算
Section titled “兼职员工月工资计算”- 计算公式:日薪 × 每月工作天数,比全职员工更复杂。
对象实例化与测试
Section titled “对象实例化与测试”- 创建张三兼职员工:传入姓名、编号、日薪及月工作天数属性。
- 创建小米4兼职员工:传入姓名、编号、日薪及月工作天数属性。
- 验证:打印两个员工的信息,确认属性设置正确。
员工月工资计算方法与多态
Section titled “员工月工资计算方法与多态”子类工资计算方法
Section titled “子类工资计算方法”- 全职员工:直接返回 monthly_salary。
- 兼职员工:daily_salary × work_days。
- 不同子类拥有同名方法
calculate_monthly_pay(),但内部逻辑不同。 - 外部调用时自动执行对应类的计算逻辑,无需区分员工类型。
- 调用各自的工资计算方法,打印每月工资。
文件操作基础
Section titled “文件操作基础”文件与目录概念
Section titled “文件与目录概念”- 文件:文档、图片、音乐等统称。
- 目录:文件夹,文件归属其中。
文件操作类比
Section titled “文件操作类比”- 手动:进入目录,点开文本编辑。
- 代码:对文件进行读写操作。
目录结构与绝对路径
Section titled “目录结构与绝对路径”操作系统目录结构
Section titled “操作系统目录结构”- Linux/MacOS 等类 Unix 系统:
- 树状结构,根节点为根目录,用
/表示。 - 所有文件目录存放在根目录下。
- 树状结构,根节点为根目录,用
- Windows 系统:
- 每个磁盘分区有独立根目录,用分区名 + 反斜杠表示(如 C:\)。
- 从根目录出发的路径。
- 类 Unix 系统:以
/开头,各级目录用/分割,最后为目标文件或目录。 - Windows 系统:以分区名 + 反斜杠开头。
相对路径 (Relative Path)
Section titled “相对路径 (Relative Path)”- 定义:从一个参考位置(当前所在目录)出发的路径,而非从根目录出发。
- 核心用途:表示当前位置与其他文件或目录的相对关系。
- 关键符号:
.(点):表示当前目录。..(点点):表示上一级目录(父目录)。
- 路径构造:
- 使用
.或..作为起点。 - 目录间使用斜杠
/或反斜杠 `` 分隔(取决于操作系统)。 - 示例:
../tmp/images/profile/1.jpg表示从当前目录向上跳转一级,进入tmp目录下的images文件夹,再进入profile找到目标文件。
- 使用
相对路径的简化规则
Section titled “相对路径的简化规则”- 省略规则:在当前目录下引用同级文件时,开头的
./可以省略,直接使用文件名即可。 - 识别特征:相对路径总是以
.或..开头(除非省略了./),区别于绝对路径的根目录开头方式。
获取文件路径的技巧
Section titled “获取文件路径的技巧”- 复制路径引用:在 IDE(如 PyCharm)中,右键点击文件并选择“复制路径/引用”,可以直接获取该文件的绝对路径或相对于项目根目录的相对路径。
- 路径用途:获取文件位置后,即可在代码中进行后续的读写操作。
编程中的文件处理场景
Section titled “编程中的文件处理场景”- 数据处理自动化:
- 传统方式:手动复制数据到代码中,当数据文件(如不同日期的销售数据)变多时,需要反复修改代码,效率低下且容易出错。
- 自动化方式:通过程序读取外部文件,仅需修改文件名即可处理不同数据,极大提升了代码的可维护性与复用性。
使用 open() 函数打开文件
Section titled “使用 open() 函数打开文件”- 基本语法:
open(file_path, mode, encoding)file_path:文件的路径(支持相对路径或绝对路径)。mode:操作模式,默认为'r'(读取模式)。encoding:编码方式,通常设置为'utf-8'以避免乱码。
文件操作模式
Section titled “文件操作模式”'r':读取模式(Read),只读文件内容。'w':写入模式(Write),只写文件内容。- 默认行为:若未指定模式,
open()默认以'r'模式打开。
常见异常处理
Section titled “常见异常处理”- FileNotFoundError:当程序尝试以读取模式打开一个不存在的文件路径时,会触发此错误,提示文件未找到。
文件对象与后续操作
Section titled “文件对象与后续操作”- 执行结果:
open()函数若执行成功,会返回一个文件对象 (file object)。 - 后续流程:获取文件对象后,即可对其进行读取或写入操作,后续操作将基于此对象进行。
read() 方法读取文件内容
Section titled “read() 方法读取文件内容”- 调用
f.read()可以一次性读取文件中的所有内容,并以字符串形式返回。 - 编程习惯:偏好
.txt等纯文本格式,直接转换为字符串;避免 Word 等含字号、字体、颜色等复杂格式的文件,以防读取问题。
read() 方法的读取机制
Section titled “read() 方法的读取机制”- 程序记录文件读取位置(指针)。
- 首次
f.read()后,指针移至文件末尾。 - 再次调用
f.read()返回空字符串(无后续内容)。
大文件处理建议
Section titled “大文件处理建议”- 文件特别大时,避免
read(),因占用大量内存,甚至导致内存崩溃。 - 不想一次性读完,可给
read()传参分批读取。
f = open("./data.txt", "r", encoding="utf-8")print(f.read()) # 读取全部内容并打印print(f.read()) # 返回空字符串readline 方法
Section titled “readline 方法”- 功能:每次只读取文件的一行内容,包含末尾的换行符
\n。 - 读取机制:
- 每次调用
f.readline()读取当前行,并将读取位置(指针)移至下一行起始处。 - 遇到文件末尾时,返回空字符串
""。
- 每次调用
- 应用场景:适合处理超大文件,避免一次性读取导致内存溢出。
f = open("./data.txt", "r", encoding="utf-8")line = f.readline()while line != "": print(line) line = f.readline()readlines 方法
Section titled “readlines 方法”- 功能:一次性读取文件的所有内容,并将每一行作为一个元素存入一个列表中返回。
- 特点:
- 方便对文件内容进行按行遍历或索引访问。
- 同样会保留每行末尾的换行符
\n。
print(f.readlines())输出示例: [‘第一行内容\n’, ‘第二行内容\n’, ‘第三行内容’]
Section titled “输出示例: [‘第一行内容\n’, ‘第二行内容\n’, ‘第三行内容’]”文件关闭与自动管理
Section titled “文件关闭与自动管理”close() 方法
Section titled “close() 方法”- 文件读写完成后调用
f.close(),释放系统资源。 - 与
open()函数成反义词对。
with 语句自动关闭
Section titled “with 语句自动关闭”- 语法:
with open("./data.txt", "r", encoding="utf-8") as f:对文件对象 f 的操作
Section titled “对文件对象 f 的操作”- **优势**:缩进代码块执行完毕后,文件**自动关闭**,无需手动调用 `close()`,代码更简洁可靠。- 避免忘记关闭导致资源泄漏。实践:创建用于读取的文本文件
Section titled “实践:创建用于读取的文本文件”- 创建文件:在代码编辑器中右键新建文件(例如
data.txt),后缀.txt明确其为纯文本格式。 - 路径与位置:文件在项目文件夹中的位置决定了读取时所需的路径(相对路径)。
- 内容填充:在文件中输入内容(如诗歌),确保文件已保存。
Python 读文件操作实践
Section titled “Python 读文件操作实践”- 打开文件:使用
open()函数,传入文件路径、模式'r'及编码'utf-8'。 - 读取内容:
- 使用
f.read()一次性读取全部内容。 - 配合
with语句实现自动关闭文件,无需显式调用close()。
- 使用
实践代码示例
Section titled “实践代码示例”with open(“./data.txt”, “r”, encoding=“utf-8”) as f:
content = f.read()
print(content)open() 函数参数详解
Section titled “open() 函数参数详解”同文件夹相对路径
Section titled “同文件夹相对路径”- 代码文件与目标文件同文件夹:使用
.(当前目录)+ 分隔符 + 文件名。 - 类 Unix 系统(Linux/Mac):分隔符为
/,如./data.txt。 - Windows 系统:分隔符为
\,如.\data.txt。
模式与编码参数
Section titled “模式与编码参数”- mode=‘r’:读模式,可省略(open() 默认 ‘r’)。
- encoding=‘utf-8’:推荐显式指定,避免系统默认编码导致乱码。
- open() 成功执行返回文件对象,用于后续读写操作。
文件读取完整实践演示
Section titled “文件读取完整实践演示”运行结果验证
Section titled “运行结果验证”- 三行代码(
open/read/print/close)运行后,成功打印文件全部内容,与原文件完全一致。
with语句替换手动close
Section titled “with语句替换手动close”- 替换步骤:删除手动
f.close()行,使用with open("./data.txt", "r", encoding="utf-8") as f:。 - 缩进要求:所有读文件操作(如
content = f.read(); print(content))置于with代码块缩进下。 - 优势:自动关闭文件,避免忘记
close()。
readline() 方法详解
Section titled “readline() 方法详解”与 read() 的区别
Section titled “与 read() 的区别”readline()逐行读取,与read()(一次性读全部)结果相同但更适合大文件。
连续读取示例
Section titled “连续读取示例”print(f.readline())print(f.readline()) # 读取前两行内容with语句块内所有文件操作必须缩进。- 无缩进时文件已自动关闭,调用
f.readline()会报错。
额外空行原因
Section titled “额外空行原因”readline()读取行尾\n。print()默认后加换行。- 两者结合产生多一空行。
readlines() 方法详解
Section titled “readlines() 方法详解”- 功能:一次性读取文件所有内容,并将其作为字符串列表返回,列表中的每个元素对应文件的一行。
- 特点:
- 自动包含行尾的换行符
\n。 - 适合与
for循环结合使用,遍历处理每一行。
- 自动包含行尾的换行符
- 代码示例:
with open("data.txt", "r", encoding="utf-8") as f: lines = f.readlines() for line in lines: print(line)- 优势:相比
readline()需要手动循环,readlines()直接将文件内容转化为列表,代码结构更简洁,避免了手动维护循环计数器。
文件写入操作 (Write Mode)
Section titled “文件写入操作 (Write Mode)”写入模式 ‘w’ 的特性
Section titled “写入模式 ‘w’ 的特性”- 覆盖写入:使用
'w'模式打开文件时,若文件已存在,原有内容会被清空;若文件不存在,则会创建新文件。 - 与读模式的相似性:同样需要使用
with open(...) as f:结构,操作完成后自动关闭文件。
写入数据的方法
Section titled “写入数据的方法”- write() 方法:将字符串直接写入文件。
- 注意:
write()不会自动添加换行符,若需换行需手动拼接 `
- 注意:
`。
- 代码示例:
with open("./output.txt", "w", encoding="utf-8") as f: f.write("姓名:张伟\n") f.write("平均分:85")读写操作对比
Section titled “读写操作对比”| 模式 | 描述 | 存在时行为 | 不存在时行为 |
|---|---|---|---|
| ‘r’ | 只读 | 读取内容 | 报错 (FileNotFoundError) |
| ‘w’ | 只写 | 清空原内容 | 创建新文件 |
文件操作的优雅实践
Section titled “文件操作的优雅实践”- 将程序计算结果存入文件,避免重复运行程序计算,同时方便将结果分享给他人。
文件写入 write() 方法实践
Section titled “文件写入 write() 方法实践”write() 不自动换行
Section titled “write() 不自动换行”write()方法写入字符串,连续调用直接拼接,无自动换行。- 需手动添加
\n实现换行。
with open("./data.txt", "w", encoding="utf-8") as f: f.write("Hello!") f.write("Yoooo") # 结果: Hello!Yoooowith open("./data.txt", "w", encoding="utf-8") as f: f.write("Hello!\n") f.write("Yoooo") # 结果: Hello!\nYoooo (两行)追加模式 ‘a’ (Append Mode)
Section titled “追加模式 ‘a’ (Append Mode)”- 功能:在文件末尾添加内容,而不是像 ‘w’ 模式那样清空原有内容。
- 特性:
- 若文件不存在,同样会创建新文件。
- 适合在已有数据的基础上持续记录,如日志或追加记录。
- 代码示例:
with open("./data.txt", "a", encoding="utf-8") as f: f.write("Hello!\n") f.write("Yoooo")读写操作限制与 ‘r+’ 模式
Section titled “读写操作限制与 ‘r+’ 模式”- 读取限制:在 ‘w’ 或 ‘a’ 模式下,直接调用
read()会报错UnsupportedOperation,因为这些模式仅设计用于写入。 - 同时读写需求:若需在同一文件对象上同时进行读取和写入,应使用
'r+'模式。 - ‘r+’ 模式优势:
- 允许在打开文件后调用
read()读取内容。 - 允许调用
write()在文件末尾追加内容,而不会清空原有数据。 - 避免了多次
open()带来的繁琐操作。
- 允许在打开文件后调用
文件写入实践任务:写入 PoM表TX.txt
Section titled “文件写入实践任务:写入 PoM表TX.txt”- 创建新文件 PoM表TX.txt。
- 使用 ‘w’ 模式:文件不存在时自动创建。
- 写入三句词。
- 相对路径:同文件夹下用
"PoM表TX.txt"或"./PoM表TX.txt"(./可省略)。
with open("PoM表TX.txt", "w", encoding="utf-8") as f:f.write("第一句\\n")
f.write("第二句\\n")
f.write("第三句")- 路径:相对路径,代码文件同文件夹。- 编码:传入 `encoding="utf-8"` 确保兼容中文。写入多行文本的换行控制
Section titled “写入多行文本的换行控制”write()方法不会自动在写入的字符串后添加换行符。- 若要实现多行效果,必须在字符串末尾手动添加
\n。
with open("poem.txt", "w", encoding="utf-8") as f: f.write("第一句\n") f.write("第二句\n") f.write("第三句")灵活的写入策略
Section titled “灵活的写入策略”- 分次写入:通过多次调用
write()逐步写入,需注意手动添加换行符以保持格式正确。 - 一次性写入:可以将所有内容拼接成一个长字符串,通过一次
write()调用完成写入,代码更简洁。
一次性写入示例
Section titled “一次性写入示例”with open(“poem.txt”, “w”, encoding=“utf-8”) as f:
f.write("第一句\\n第二句\\n第三句")任务二:文件内容追加实践
Section titled “任务二:文件内容追加实践”- 场景需求:在已有的
poem.txt文件末尾添加两行新内容,而不清空原有数据。 - 模式选择:使用
'a'(Append) 模式,避免'w'模式导致的覆盖清空。
追加操作实现
Section titled “追加操作实现”with open("poem.txt", "a", encoding="utf-8") as f: f.write("起舞弄清影\n") f.write("何似在人间。\n")- 关键细节:
- 换行符管理:在追加内容时,必须在每行字符串末尾添加
\n。若不添加,新写入的内容会直接连接在原文件末尾的字符之后。 - 防止粘连:若原文件末尾本身没有换行符,追加内容时需在开头额外添加一个
\n,否则新内容会与原文件最后一行“粘”在一起。
- 换行符管理:在追加内容时,必须在每行字符串末尾添加
程序异常与错误处理
Section titled “程序异常与错误处理”程序崩溃的原因
Section titled “程序崩溃的原因”- 代码逻辑错误:即便代码本身语法正确,也可能因外部因素导致程序运行中断(崩溃)。
- 输入数据不合理:例如用户输入了程序无法处理的数据类型或格式,会导致程序在运行过程中产生报错。
- 资源访问失败:如尝试打开不存在的文件,程序会抛出异常并停止执行后续代码。
异常处理的重要性
Section titled “异常处理的重要性”- 程序中断机制:当程序在某一行产生报错时,后续所有代码将不会被执行。
- 预防性编程:学习在程序“炸掉”之前进行预判,捕获异常,并以预期的逻辑处理错误,从而避免程序完全停摆。
常见异常类型
Section titled “常见异常类型”- IndexError (索引错误):当尝试访问列表长度范围之外的索引时触发。
- ZeroDivisionError (除零错误):当尝试用数字除以 0 时触发。
- FileNotFoundError (找不到文件错误):当尝试打开一个不存在的文件时触发。
- TypeError (类型错误):当操作数类型不匹配时触发,例如尝试将两个字符串进行乘法运算。
try-except 异常捕获引入
Section titled “try-except 异常捕获引入”异常捕获必要性
Section titled “异常捕获必要性”- 程序某行抛异常时,后续代码停止执行。
- 通过预防性编程预判错误,优雅处理避免崩溃。
异常处理思路
Section titled “异常处理思路”- try-except 语句:
try:后缩进,放可能报错代码。except 错误名:后捕捉特定异常。
- 示例:
float()转换无法转为数字的字符串,报 ValueError。
无法避免的错误场景
Section titled “无法避免的错误场景”- 用户输入非数字(如诗句),
float()转换失败,程序直接崩溃。 - 无机会提示用户,需提前捕捉异常保持程序运行。
try-except 异常处理机制
Section titled “try-except 异常处理机制”- 核心逻辑:将可能引发错误的代码放入
try代码块中,并在except块中定义错误发生后的补救逻辑。 - 程序防崩溃:通过捕获异常,程序在遇到错误时不会直接停止执行,而是转而执行
except中的代码。 - 代码示例:
try: user_weight = float(input("请输入体重(kg): ")) user_height = float(input("请输入身高(m): ")) user_BMI = user_weight / user_height ** 2 except ValueError: print("输入不合规数字,请重新运行程序并输入正确数字。")多异常捕获与通用处理
Section titled “多异常捕获与通用处理”- 针对性捕获:可以为不同的异常类型编写多个
except块,分别处理不同错误(如ValueError和ZeroDivisionError)。 - 通用异常捕获:若不确定错误类型,可使用不带错误名的
except:,它会捕获所有异常类型,防止程序崩溃。
except ZeroDivisionError: print("身高不能为零,请重新运行程序。") except: print("发生了未知错误,请重新运行程序。")- 注意事项:
try-except语句在执行时是从上往下进行异常匹配的。
异常处理中的 else 与 finally 语句
Section titled “异常处理中的 else 与 finally 语句”- else 语句:
- 放置在
except块之后。 - 执行逻辑:仅当
try块中的代码没有发生任何异常时才会执行。 - 应用场景:适合放置在成功读取数据后需要执行的后续逻辑,例如打印计算结果。
- 放置在
- finally 语句:
- 放置在
except或else块之后。 - 执行逻辑:无论是否发生异常,也无论异常是否被成功捕获,
finally块中的代码总是会被执行。 - 应用场景:用于必须执行的清理工作(如关闭资源、打印结束语)。
- 放置在
异常处理完整结构示例
Section titled “异常处理完整结构示例”try:可能出错的代码
Section titled “可能出错的代码”user\_weight = float(input("请输入体重(kg): "))
user\_height = float(input("请输入身高(m): "))
user\_BMI = user\_weight / user\_height \*\* 2except ValueError:
print("输入不合规数字,请重新运行程序并输入正确数字。")except ZeroDivisionError:
print("身高不能为零,请重新运行程序。")except:
print("发生了未知错误,请重新运行程序。")else:
只有没报错时执行
Section titled “只有没报错时执行”print("您的BMI值为: " + str(user\_BMI))finally:
无论如何都会执行
Section titled “无论如何都会执行”print("程序结束运行。")调试与测试的重要性
Section titled “调试与测试的重要性”- 代码测试确保代码无误。
- 目标:在用户发现前快速发现并改正
bug。 - 1947年,格蕾丝·赫柏发现计算机故障原因是蛾子(英文
bug)进入继电器导致硬件问题。 Bug在计算机领域表示程序错误。
Assert 语句测试基础
Section titled “Assert 语句测试基础”- 验证新代码是否正确。
- 确认修改老代码后,不该受影响的部分仍按预期执行(避免牵一发而动全身)。
Assert 语法与执行逻辑
Section titled “Assert 语法与执行逻辑”- Assert:中文断言。
- 后跟布尔表达式(求值为 True 或 False)。
- True:无事发生,继续执行后续代码。
- False:抛出 AssertionError(断言错误),提醒“这里不符合预期”。
assert 1 == 1 # True,继续运行assert 1 == 2 # False,抛 AssertionError,程序终止Assert 局限性
Section titled “Assert 局限性”- 一旦抛 AssertionError,程序立即终止,后续代码不会执行。
使用专用测试库
Section titled “使用专用测试库”- Assert 的局限性:由于
assert抛出错误后会立即终止程序,不适合大规模、多用例的测试。 - 测试库的优势:
- 支持一次性运行多个测试用例。
- 能直观展示哪些用例通过,哪些未通过。
unittest 单元测试库
Section titled “unittest 单元测试库”- 定义:Python 自带的常用单元测试库,无需额外安装。
- 核心概念:
- 单元测试:对软件中最小可测试单元(如函数)进行验证,确保其表现符合预期。
- 导入方式:虽然是内置库,但仍需使用
import unittest引入。
- 工程规范:
- 代码分离:将测试代码与实现代码放在独立的
.py文件中,避免功能代码与测试逻辑混杂。 - 结构清晰:这种分离方式有助于更清晰地划分实现逻辑与验证逻辑。
- 代码分离:将测试代码与实现代码放在独立的
使用 unittest 编写测试
Section titled “使用 unittest 编写测试”- 代码导入与结构
- 在测试文件中,需通过
from 文件名 import 函数名/类名引入待测代码。 - 必须
import unittest以使用测试框架。
- 在测试文件中,需通过
- 创建测试类
- 定义一个继承自
unittest.TestCase的类,类名建议以Test开头。 - 继承该类后,即可使用其提供的各种断言和测试功能。
- 定义一个继承自
- 编写测试方法
- 每一个测试用例都是类中的一个方法。
- 方法名必须以
test_开头,unittest会自动识别并运行这些方法。
import unittestfrom my_calculator import my_adder
class TestMyAdder(unittest.TestCase): def test_positive_with_positive(self):在此编写测试逻辑
Section titled “在此编写测试逻辑” pass
def test\_negative\_with\_positive(self):在此编写测试逻辑
Section titled “在此编写测试逻辑” passunittest 单元测试实践
Section titled “unittest 单元测试实践”- 测试逻辑实现
- 继承
unittest.TestCase后,可以直接使用self.assertEqual(a, b)方法进行断言。 assertEqual的逻辑:若第一个参数与第二个参数相等,测试通过;否则测试不通过,但程序不会像assert那样直接终止,而是会记录失败信息并继续执行后续测试用例。
- 继承
- 运行测试用例
- 在编辑器终端输入以下命令运行测试:
python -m unittest- **自动发现机制**:该命令会自动搜索当前目录下所有继承自 `unittest.TestCase` 的子类,并运行其中所有以 `test_` 开头的方法。- 运行结果会显示测试用例的执行数量(如 `Ran 2 tests`)及执行耗时,直观反馈代码质量。unittest 测试结果解读
Section titled “unittest 测试结果解读”- 执行反馈:运行
python -m unittest后,系统会显示运行的测试用例总数及耗时。 - 点号表示法:输出中的点号(
.)代表测试用例通过。 - 失败提示:若测试未通过,会显示
FAIL并提供详细的错误回溯(Traceback),明确指出是哪个文件、哪个方法导致了失败以及失败原因。 - 一体化报告:
unittest提供了一体化的测试结果,包含所有测试用例的执行状态和详细的错误信息,极大地提高了单元测试的效率。
unittest 进阶价值
Section titled “unittest 进阶价值”- 自动化发现:无需手动调用每个测试函数,框架会自动识别并运行所有
test_开头的方法。 - 高效调试:通过详细的失败报告,开发者能快速定位问题所在,避免了手动运行代码检查的繁琐过程。
unittest 常用断言方法
Section titled “unittest 常用断言方法”除了 assertEqual,unittest.TestCase 还提供了多种断言方法以应对不同测试场景:
| 方法 | 类似于 | 适用场景 |
|---|---|---|
| assertTrue(A) | assert A is True | 验证条件是否为真 |
| assertIn(A, B) | assert A in B | 验证元素是否存在于序列中 |
| assertNotEqual(A, B) | assert A != B | 验证两个值不相等 |
| assertFalse(A) | assert A is False | 验证条件是否为假 |
| assertNotIn(A, B) | assert A not in B | 验证元素不在序列中 |
断言方法的选择策略
Section titled “断言方法的选择策略”- 万能替代:本质上
assertTrue可以替代所有其他断言方法(例如assertTrue(2 not in [1, 2])等同于assertNotIn(2, [1, 2]))。 - 推荐做法:应优先使用具有针对性的断言方法(如
assertNotIn)。 - 原因:当测试未通过时,针对性方法会给出更详细的失败原因,而
assertTrue只会报错“False is not true”,难以快速定位问题。
单元测试中的 Setup 方法
Section titled “单元测试中的 Setup 方法”- 解决重复代码:在测试类中,若多个测试方法都需要先实例化同一个对象,可以使用
setUp(self)方法。 - 执行机制:
setUp方法会在每一个以test_开头的方法运行前被自动调用一次,确保每个测试用例都在一个干净、独立的初始状态下运行。 - 属性共享:在
setUp中通过self.变量名 = 对象将对象设为类的属性,后续的测试方法即可直接通过self.变量名调用该对象,避免了在每个方法中重复编写实例化代码。
class TestSentence(unittest.TestCase): def setUp(self):每个测试方法运行前都会执行此初始化
Section titled “每个测试方法运行前都会执行此初始化” self.sentence = Sentence("hello world!")
def test\_str\_count(self):直接使用 setUp 中创建的 self.sentence
Section titled “直接使用 setUp 中创建的 self.sentence” self.assertEqual(self.sentence.str\_count(), 12)ShoppingList 单元测试实践
Section titled “ShoppingList 单元测试实践”测试文件创建与导入
Section titled “测试文件创建与导入”- 新建文件:
test_shortlist.py(以test_开头,便于 unittest 识别)。 - 导入模块:
import unittestfrom 文件名 import ShoppingList- 创建继承
unittest.TestCase的类。
ShoppingList 类方法
Section titled “ShoppingList 类方法”get_item_count():返回购物清单商品件数。get_total_price():返回购物清单商品总额。
getItemCount 方法单元测试
Section titled “getItemCount 方法单元测试”测试用例实现
Section titled “测试用例实现”- 方法名以
test_开头。 - 示例清单:纸巾8元、帽子30元、拖鞋15元(共3件商品)。
- 验证
getItemCount()返回3。
def test_getItemCount(self): self.assertEqual(self.shopping_list.getItemCount(), 3)get_total_price 方法单元测试
Section titled “get_total_price 方法单元测试”- 测试目标:验证
get_total_price()方法计算总价的准确性。 - 测试逻辑:使用包含“纸巾: 8, 帽子: 30, 拖鞋: 15”的购物清单,预期总价应为 53。
def test_get_total_price(self): self.assertEqual(self.shopping_list.get_total_price(), 53)利用 setUp 优化测试结构
Section titled “利用 setUp 优化测试结构”- 问题:在多个测试方法中重复实例化
ShoppingList对象会导致代码冗余。 - 解决方案:使用
setUp()方法在每个测试用例运行前自动初始化对象。 - 实现细节:
- 在
setUp中通过self.shopping_list = ShoppingList(...)将对象设为类属性。 - 后续测试方法直接通过
self.shopping_list调用,无需重复创建。
- 在
def setUp(self): self.shopping_list = ShoppingList({'纸巾': 8, '帽子': 30, '拖鞋': 15})unittest 测试运行与结果解读
Section titled “unittest 测试运行与结果解读”测试执行与通过反馈
Section titled “测试执行与通过反馈”- 终端命令:
python -m unittest。 - 运行2个测试用例,结果显示两个点号(
.),表示全部通过。
测试失败反馈
Section titled “测试失败反馈”- 故意修改数字为错值,重新运行命令。
- 结果显示F(failure),表示有测试失败。
- 框架自动展示失败的具体测试方法。
- 提供详细Traceback信息,包括出错文件、行号及原因(如
AssertionError: 53 != 55)。
单元测试失败反馈与调试
Section titled “单元测试失败反馈与调试”- 失败指标:当测试未通过时,终端显示
F(Failure) 而非.(Success)。 - 错误定位:框架会自动打印出失败的测试方法名称,帮助快速锁定问题区域。
- 详细追踪 (Traceback):
- 自动生成错误报告,明确指出出错的文件名、代码行号。
- 提供具体的断言失败原因,例如
AssertionError: 53 != 55,直接对比预期值与实际值,极大简化了排查逻辑错误的过程。
函数逻辑解耦与参数化
Section titled “函数逻辑解耦与参数化”函数职责分离的必要性
Section titled “函数职责分离的必要性”- 原有的函数同时负责“计算”与“打印”,导致扩展功能(如增加三次方计算)时代码结构变得冗余且难以维护。
- 核心思路:将计算逻辑从打印函数中剥离,作为参数传入,实现逻辑解耦。
函数作为参数传递
Section titled “函数作为参数传递”- 可以将计算函数(如求平方、立方或加法)直接作为参数传递给打印函数,使打印函数专注于输出格式,而无需关心具体的计算实现。
代码实现示例
Section titled “代码实现示例”def calculate_square(num): return num * num
def calculate_cube(num): return num * num * num
def calculate_plus_10(num): return num + 10
def calculate_and_print(num, calculator): result = calculator(num) print(f"数字参数 | {num} | 计算结果 | {result}")calculate_and_print(3, calculate_square)
calculate_and_print(3, calculate_cube)
- **优势**:打印函数不再需要使用 `if-elif` 判断逻辑,无论传入何种计算规则,打印函数均能通用,符合 DRY 原则。高阶函数 (Higher-Order Functions)
Section titled “高阶函数 (Higher-Order Functions)”- 定义:将函数作为参数传递给另一个函数的函数,称为高阶函数。
- 核心优势:通过将计算逻辑(如平方、立方、加法)从打印函数中剥离,实现了逻辑解耦,使代码更符合 DRY (Don’t Repeat Yourself) 原则。
- 调用规范:
- 传入函数本身时,不要带括号和参数(例如
calculate_square),否则会直接执行该函数并将结果作为参数传入,而非函数本身。 - 只有在函数内部需要执行时,才通过
calculator(num)形式进行调用。
- 传入函数本身时,不要带括号和参数(例如
扩展计算逻辑实践
Section titled “扩展计算逻辑实践”- 当需要增加新的计算功能(如乘以5)时,无需修改现有的
calculate_and_print函数,只需定义新的计算函数并作为参数传入即可。 - 甚至可以将格式化函数(如
print_with_vertical_bar)也作为参数传入,实现打印样式的动态切换。
def calculate_times_5(num): return num * 5动态传入计算函数
Section titled “动态传入计算函数”calculate_and_print(7, calculate_times_5)
动态传入格式化函数
Section titled “动态传入格式化函数”calculate_and_print(7, calculate_times_5, print_with_vertical_bar)
匿名函数 (Lambda)
Section titled “匿名函数 (Lambda)”- 定义与场景:当一个函数仅被调用一次,且逻辑非常简单时,专门定义一个具名函数显得过于正式且冗余。
- 核心特点:
- 无需名称:直接在需要的地方定义,即用即弃。
- 一次性:像一次性用品一样,使用后即销毁。
- 应用示例:在将函数作为参数传递给高阶函数时,若该函数仅在该处使用,使用
lambda可大幅简化代码结构。
传统具名函数方式
Section titled “传统具名函数方式”def calculate_times_5(num):
return num \* 5calculate_and_print(7, calculate_times_5)
使用匿名函数方式
Section titled “使用匿名函数方式”calculate_and_print(7, lambda num: num * 5)
匿名函数语法规则
Section titled “匿名函数语法规则”- 关键字:使用
lambda关键字定义。 - 结构:
lambda 参数: 返回值。 - 限制:仅支持单行表达式,自动返回表达式的结果,无需显式使用
return语句。
匿名函数 (Lambda) 实践
Section titled “匿名函数 (Lambda) 实践”- 定义方式:使用
lambda关键字,后跟参数,冒号分隔,最后是返回的表达式。 - 语法结构:
lambda 参数: 表达式。 - 核心优势:
- 无需命名:即用即弃,非常适合作为高阶函数的参数。
- 简洁性:无需编写
def和return,单行即可完成逻辑定义。 - 代码优化:将原本需要额外定义具名函数的场景压缩至一行,提升代码可读性。
使用 lambda 代替具名函数传入高阶函数
Section titled “使用 lambda 代替具名函数传入高阶函数”calculate_and_print(7, lambda num: num * 5)
匿名函数与具名函数的对比
Section titled “匿名函数与具名函数的对比”| 特性 | 具名函数 (def) | 匿名函数 (lambda) |
|---|---|---|
| 名称 | 必须有 | 无 |
| 定义方式 | 完整函数体 | 单行表达式 |
| 返回值 | 需显式 return | 自动返回表达式结果 |
| 适用场景 | 复杂逻辑、多次调用 | 简单逻辑、一次性调用 |
匿名函数的多参数扩展
Section titled “匿名函数的多参数扩展”- 若需多个参数,在
lambda关键字后用逗号分隔参数名即可。
多参数匿名函数示例
Section titled “多参数匿名函数示例”lambda num1, num2: num1 + num2
- **总结**:匿名函数本质上是“没有名字、占用行数更少的函数”,特别适合只需要一次性执行的简单逻辑。Lambda 直接调用示例
Section titled “Lambda 直接调用示例”- 调用方式:与普通函数相同,使用括号传入参数;前面的匿名函数需加括号表示整体。
(lambda num1, num2: num1 + num2)(2, 3)Lambda 的局限性
Section titled “Lambda 的局限性”- 单表达式限制:冒号后仅支持一个表达式,无法包含多语句、循环或递归。
- 适用场景:仅限简单逻辑;复杂多步骤逻辑使用具名函数(def),以确保灵活性和可读性。
- 可读性问题:复杂逻辑用 lambda 会导致代码难懂,应优先 def 定义普通函数。
Jupyter Notebook 简介
Section titled “Jupyter Notebook 简介”工具定位与核心功能
Section titled “工具定位与核心功能”- 定义:基于网页的交互式计算环境,广泛用于数据分析、数据科学及机器学习领域。
- 核心能力:
- 编写并运行 Python 代码。
- 查看代码输出与可视化数据。
- 编写并分享包含代码、公式与说明文档的报告。
为什么数据科学家偏爱 Jupyter Notebook
Section titled “为什么数据科学家偏爱 Jupyter Notebook”- 单元格执行机制:
- 优势:支持按单元格(Cell)独立运行代码,无需每次从头运行整个脚本。
- 场景:在处理大规模数据或耗时操作时,避免了重复读取数据或执行前置步骤的等待时间,极大提升了调试与分析效率。
- 对比:传统代码编辑器(如 PyCharm/VSCode)通常执行整个
.py文件,而 Jupyter 允许在修改分析公式后,仅重新运行特定单元格查看效果。
- 开发流程优化:
- 支持将不同的数据处理步骤(如读取、清洗、计算、保存)拆分到不同单元格中,实现灵活的交互式开发。
Jupyter Notebook 的交互式优势
Section titled “Jupyter Notebook 的交互式优势”- 代码片段执行:支持仅运行特定的单元格(Cell),无需重新执行整个脚本。这在处理大规模数据集或耗时的数据预处理步骤时,能显著节省重复等待的时间。
- 开发流优化:通过将读取、清洗、计算、可视化等步骤拆分为独立的单元格,开发者可以针对特定逻辑进行反复调试,极大提升了数据分析的效率。
Jupyter Notebook 的文档与展示功能
Section titled “Jupyter Notebook 的文档与展示功能”- 富文本支持:支持 Markdown 标记语言,可以编写带标题、层级、列表的说明文档,使代码逻辑与分析思路一目了然。
- 数学公式渲染:内置对 LaTeX 的支持,能够清晰地展示复杂的数学公式,便于学术交流与报告撰写。
- 结果持久化:将代码、输出结果(包括图表)和说明文档整合在同一份文件中,分享时对方无需重新运行代码即可查看完整的分析过程及结论。
Jupyter Notebook 安装步骤
Section titled “Jupyter Notebook 安装步骤”- Windows:打开 CMD,输入
pip install notebook回车安装。 - macOS:打开 Terminal,输入
pip3 install notebook回车安装。 - 启动:输入
jupyter notebook,浏览器自动打开界面即成功。 - 关闭:关闭浏览器不够,需在命令行 Ctrl+C 中止后台服务器。
Jupyter Notebook 的正确关闭方式
Section titled “Jupyter Notebook 的正确关闭方式”-
后台服务器中止:仅关闭浏览器窗口无法停止 Jupyter Notebook 服务,必须在运行它的终端(Terminal/CMD)中进行操作。
-
关闭步骤:
- 在运行 Jupyter 的终端窗口中,按下
Ctrl + C组合键。 - 系统会提示确认是否关闭(Shutdown this notebook server (y/n)?)。
- 输入
y并回车,即可安全终止后台服务。
- 在运行 Jupyter 的终端窗口中,按下
Jupyter Notebook 界面与文件管理
Section titled “Jupyter Notebook 界面与文件管理”- 主界面功能:
- 启动后显示的面板即为当前根目录,展示所有文件与文件夹。
- 支持通过点击文件夹名称进入子目录,实现层级管理。
- 创建新 Notebook:
- 在目标文件夹内,点击右上角的
New按钮,选择Python 3即可创建一个新的.ipynb文件。 - 系统会自动在浏览器打开编辑界面,并在对应目录下生成该文件。
- 在目标文件夹内,点击右上角的
- 文件重命名:
- 在编辑界面,直接点击顶部的标题(默认为
Untitled),在弹出的对话框中输入新名称即可修改。
- 在编辑界面,直接点击顶部的标题(默认为
- 界面布局:
- 标题栏下方依次为:菜单栏、工具栏、单元格(Cell)。
- 工具栏:集成了菜单栏中最常用的功能,便于快速操作。
Jupyter Notebook 单元格交互模式
Section titled “Jupyter Notebook 单元格交互模式”- 单元格功能:主要用于编写 Python 代码和 Markdown 文字说明。
- 编辑模式与命令模式切换:
- 编辑模式:点击单元格内部,外框变为绿色,可输入代码或文字。
- 命令模式:按
Esc键或点击单元格外部,外框变为蓝色,此时可对单元格进行操作(如删除、移动)。
工具栏常用操作
Section titled “工具栏常用操作”- 保存:点击磁盘图标保存当前 Notebook 内容。
- 新建单元格:点击
+号在当前单元格下方插入新单元格。 - 剪切/复制/粘贴:工具栏提供快捷按钮,支持对选中的单元格进行编辑。
- 多选操作:按住
Shift键可选中多个单元格,实现批量操作。 - 移动单元格:使用上下箭头按钮可调整单元格的排列顺序。
Jupyter Notebook 单元格执行机制
Section titled “Jupyter Notebook 单元格执行机制”- 执行状态标识:
- 运行中:单元格左侧显示
[*],表示代码正在执行。 - 执行完毕:
[*]会变为数字(如[1]),数字代表代码执行的顺序。
- 运行中:单元格左侧显示
- 灵活执行顺序:
- Jupyter 允许以任意顺序运行单元格,无需遵循从上到下的线性逻辑。
- 即使是已执行过的单元格,也可以随时返回重新运行。
- 执行顺序对变量的影响:
- 单元格左侧的数字记录了代码的实际执行先后顺序,这在调试时至关重要。
- 风险提示:如果先运行了后面的单元格(如第3格),再运行前面的单元格(如第1格),程序状态会基于当前的执行顺序更新。若后续代码依赖之前的变量,执行顺序的混乱可能导致数据未及时更新或逻辑错误。
Jupyter Notebook 交互式执行特性
Section titled “Jupyter Notebook 交互式执行特性”- 交互模式执行:代码无需显式调用
print()即可直接显示执行结果,适合快速查看变量值或中间计算结果。 - 单单元格多语句限制:当一个单元格内包含多条输出语句时,系统仅展示最后一行代码的输出结果。
- 强制打印:若需在单单元格中展示多项输出,必须显式使用
print()函数。
单元格控制与系统管理
Section titled “单元格控制与系统管理”- 程序中断:使用工具栏的“停止”(Interrupt)按钮可强制中止正在运行的单元格代码,适用于陷入死循环或执行时间过长的任务。
- 环境重置:
- 重启内核 (Restart):通过重启按钮清除所有已定义的变量和内存状态,相当于重置了当前的 Python 环境。
- 应用场景:当变量定义混乱或需要从零开始重新验证逻辑时,重启内核是确保代码运行环境纯净的有效手段。
Jupyter Notebook 单元格运行与 Markdown 支持
Section titled “Jupyter Notebook 单元格运行与 Markdown 支持”变量持久化与重启效果
Section titled “变量持久化与重启效果”- 多次运行:运行第二格输出对应值,变量在单元格间持久存在。
- 重启后:直接运行第二格提示变量不存在,单元格数字重置为
[1]表示已重启。
重启并运行所有单元格
Section titled “重启并运行所有单元格”- 按钮位置:单元格数字旁边。
- 实用性:从上到下完整执行所有代码,检查单元格顺序问题。
单元格类型切换
Section titled “单元格类型切换”- 右边下拉框:切换代码与Markdown单元格。
- Markdown 用途:添加文字样式,不限于代码。
Markdown 语法示例
Section titled “Markdown 语法示例”- 一级标题:
# 标题(井号空格),运行后自动加大加粗。 - 二级标题:
## 标题,双击单元格进入编辑模式修改并运行渲染。
Jupyter Notebook Markdown 进阶语法
Section titled “Jupyter Notebook Markdown 进阶语法”- 标题层级:
- Markdown 单元格支持通过井号 (
#) 定义标题层级,井号数量对应标题级别(如#为一级,##为二级)。 - 标题需在井号后添加空格才能正确渲染。
- Markdown 单元格支持通过井号 (
- 样式编辑:
- 渲染后的 Markdown 单元格可通过双击进入编辑模式,修改后再次运行即可更新样式。
- 文本格式化:
- Markdown 提供了丰富的文本修饰功能,除了标题外,还支持加粗、斜体、列表、链接等多种排版方式,便于在代码旁编写说明文档。
- 公式渲染:
- 支持 LaTeX 语法,可在 Markdown 单元格中通过特定的数学表达式语法(如使用美元符号包裹)渲染复杂的数学公式。
- 示例:
$f(x) = x^2 + y^2 = 1$可在单元格内渲染为数学公式。
快捷键管理与效率提升
Section titled “快捷键管理与效率提升”- 快捷键配置面板:
- 工具栏最右侧的键盘图标用于打开“快捷键配置”(Keyboard Shortcuts)面板。
- 通过此面板可以查看并自定义 Jupyter Notebook 的所有快捷操作,熟练使用快捷键能显著提升交互效率。
- 常用快捷操作(命令模式下):
A(Above):在当前单元格上方插入一个新单元格。B(Below):在当前单元格下方插入一个新单元格。- 掌握这些快捷键可避免频繁使用鼠标点击工具栏,保持编程流的连贯性。
Jupyter Notebook 命令模式快捷键实践
Section titled “Jupyter Notebook 命令模式快捷键实践”单元格删除操作
Section titled “单元格删除操作”- 双D删除:在命令模式下,连按两次
D键删除当前选中的单元格。 - 模式要求:必须在命令模式(外框蓝色)使用,若在编辑模式(外框绿色)则视为输入文字。
运行单元格快捷键
Section titled “运行单元格快捷键”- Shift + Enter:运行当前单元格(适用于代码或Markdown),效果等同工具栏运行按钮。
- 优势:自动跳转下一单元格,节省鼠标操作时间。
Notebook 文件分享
Section titled “Notebook 文件分享”- 可编辑分享:直接发送
.ipynb文件,对方可自行编辑运行。 - 只读分享:点击
File>Download as>HTML,生成网页格式报告,便于阅读无需运行环境。
重新打开现有 Jupyter Notebook
Section titled “重新打开现有 Jupyter Notebook”-
重新启动服务:关闭后浏览器页面失效,需在终端重新运行
jupyter notebook。 -
打开步骤:
- 进入存放 Notebook 的目录。
- 点击相应的
.ipynb文件,编辑界面即恢复。
-
他人 Notebook:过程相同,先运行
jupyter notebook,进入目录点击文件即可。
服务关闭后刷新效果
Section titled “服务关闭后刷新效果”- 浏览器刷新显示页面无效,因后台服务器已关闭。
Markdown 介绍与优势
Section titled “Markdown 介绍与优势”代码注释的格式限制
Section titled “代码注释的格式限制”- 注释无法加粗文字、超链接、标题或插入图片。
- 仅限纯文本,信息传递受限。
富文本编辑器的缺点
Section titled “富文本编辑器的缺点”- 如Word等工具功能强大,但文件臃肿。
- 打开Word文档远慢于记事本。
Markdown 的轻量级优势
Section titled “Markdown 的轻量级优势”- 轻量级标记语言,解决格式与文件大小问题。
- 支持丰富样式,适合代码旁文档编写。
LaTeX 支持
Section titled “LaTeX 支持”- 在文字单元提升表达能力,结合Markdown使用。
Markdown 标题语法实践
Section titled “Markdown 标题语法实践”Jupyter Markdown 单元格练习
Section titled “Jupyter Markdown 单元格练习”- 打开 Jupyter Notebook,将单元格切换为 Markdown 类型。
- 输入 Markdown 内容后,点击工具栏运行按钮或按 Shift + Enter 快捷键,内容立即渲染展示效果。
一级标题创建
Section titled “一级标题创建”- 使用单个
#创建:# 一级标题。 - 运行单元格后渲染为最大标题样式。
Markdown 基本格式符号
Section titled “Markdown 基本格式符号”- 标题层级:内容前加
#+ 空格控制层级,一级用单个#,最多六个######为最小标题。 - 粗体:用两个
*包围文字,如**粗体**。 - 斜体:用单个
*包围文字,如*斜体*。 - 删除线:用两个英文波浪号
~~包围文字(如~~删除线~~),注意用英文输入法的小波浪号,非中文大波浪号。 - 所有符号:Markdown 中均使用英文输入法符号。
- 纯文本:不加任何符号包围,为普通断行文字。
- 换行规则:单次换行仅显示一个空格;分不同行需在文字间加空行,或编辑时多打一次换行。
Markdown 列表与链接语法
Section titled “Markdown 列表与链接语法”- 列表创建:
- 无序列表:在列表项前添加短横线
-和空格。 - 有序列表:在列表项前添加数字、英文句号
.和空格。
- 无序列表:在列表项前添加短横线
- 链接添加:
- 直接显示:直接输入网址,Markdown 会自动识别并将其转换为可跳转链接。
- 自定义标题链接:使用
[标题](网址)格式,可直观展示链接指向的内容,而非显示原始 URL。 - 注意事项:完整的链接地址必须包含协议名(如
https://)。
Markdown 图片插入语法
Section titled “Markdown 图片插入语法”- 语法结构:
图片描述- 格式与链接非常相似,唯一区别是在最前方增加了一个英文感叹号
!。
- 格式与链接非常相似,唯一区别是在最前方增加了一个英文感叹号
- 图片描述的作用:当图片无法正常加载时,系统会显示该描述文字作为占位符,增强文档的健壮性。
Markdown 引用语法
Section titled “Markdown 引用语法”- 语法结构:使用右书名号
>加空格,后面紧跟引用的内容。 - 换行规则:引用块内的文字与普通段落一致,不会因为编辑时的换行而产生实际换行。
- 强制换行:若需在引用中换行,需在上一行的末尾添加两个空格。
Markdown 代码块语法
Section titled “Markdown 代码块语法”- 语法结构:使用反引号 `` ` `` 包裹代码。
- 反引号位于键盘左上角,与波浪号
~在同一个键位。
- 反引号位于键盘左上角,与波浪号
- 用途:专门用于在文字中插入代码片段,使其以等宽字体显示,便于阅读。
多行代码块语法高亮
Section titled “多行代码块语法高亮”- 三个反引号`` 包裹多行代码段落。
- 语言高亮`python ````),自动应用语法高亮。
Markdown 数学公式支持
Section titled “Markdown 数学公式支持”- 数据分析公式:复杂公式(如求和、根号)键盘难输入,直接写代码不美观。
- LaTeX 语法:支持根号、分数线等符号,提升公式表达直观性。
LaTeX 基本公式语法
Section titled “LaTeX 基本公式语法”- LaTeX 简介:排版系统,用于书籍、简历、论文等格式和布局。
- 示例:左侧原始文档内容,右侧编译效果。
- 公式写作:复杂公式用 LaTeX 编写。
- Jupyter 使用:在 Markdown 中插入公式,只需掌握公式相关语法。
基本运算符号
Section titled “基本运算符号”- 加号
+、减号-:直接用键盘符号。 - 乘号:
\times(times,相乘含义)。 - 除号:
\div(div,相除含义)。
- 上标(如平方、三次方):
^后跟内容(Shift + 6)。 - 下标:
_后跟内容。
LaTeX 上下标与高级符号
Section titled “LaTeX 上下标与高级符号”- 默认限制:LaTeX 默认的上标
^或下标_只会作用于紧跟其后的一个字符。 - 多字符组合:若需将多个字符作为整体处理,需使用花括号
{}将其包裹。- 示例:
x^{10}将10整体作为上标。
- 示例:
- 求和与求根符号:
- 求和:使用
\sum。 - 求根:使用
\sqrt(square root)。- 示例:
\sqrt[3]{x}表示对x开 3 次方。 - 根号内的长公式需用花括号
{}括起,否则横线只会延伸至第一个字符。
- 示例:
- 求和:使用
- 分数线:
- 使用
\frac{分子}{分母}表示,frac即 fraction 的缩写。 - 示例:
\frac{x+y}{x-y}。
- 使用
LaTeX 分数线语法
Section titled “LaTeX 分数线语法”- 语法结构:使用
\frac{分子}{分母}。frac是 fraction(分数)的缩写。
- 应用示例:
- 若要表示 $$\frac{x+y}{x-y}$
,在 LaTeX 中输入\frac{x+y}{x-y}`。 - 第一个花括号
{}存放分子内容,第二个花括号{}存放分母内容,系统会自动将其渲染为上下结构的数学分数形式。
- 若要表示 $$\frac{x+y}{x-y}$
LaTeX 公式符号支持
Section titled “LaTeX 公式符号支持”- 支持无数数学公式符号,可查阅符号表获取对应语法。
NumPy 数组介绍
Section titled “NumPy 数组介绍”NumPy 概述
Section titled “NumPy 概述”- NumPy:常用于科学及工程领域。
- 核心数据结构:N 维数组(N 维数据)。
1 维数组示例
Section titled “1 维数组示例”- 1 维数组类似于 Python 列表。
与 Python 内置列表的对比
Section titled “与 Python 内置列表的对比”- 通过索引
[]获取单个元素。 - 通过切片 获取某范围多个元素。
- 支持迭代 各个元素。
- NumPy 数组:元素必须同一类型(如全数字或全字符串)。
- Python 列表:无此类型限制。
- 执行效率:大规模数学运算时,NumPy 数组速度远高于内置列表。
- 提供大量数学运算函数,如求平均值、标准差等。
NumPy 安装与导入
Section titled “NumPy 安装与导入”- 安装:NumPy 是第三方库,需在终端(Windows 下为
cmd,macOS 下为Terminal)使用pip install numpy(macOS 可能需pip3 install numpy)进行安装。 - 导入与别名:
import numpy as np- 习惯上使用 `as np` 给库起别名,目的是在调用函数时减少输入量,使代码更简洁。创建 NumPy 数组
Section titled “创建 NumPy 数组”- 创建方法:使用
np.array()方法将列表转换为 NumPy 数组。 - 数组维度判断:
- 简单列表 → 1 维数组。
- 嵌套列表(列表内含列表) → 2 维数组。
- 简单判断:观察数组外层方括号的嵌套层数。
数组元素类型限制
Section titled “数组元素类型限制”- 强制转换:虽然
np.array()可以接收不同类型的元素(如字符串、布尔值、浮点数),但它会强制将所有元素转换为同一类型(通常为字符串类型)。 - 最佳实践:为了保证数据一致性与计算逻辑的正确性,建议从一开始就传入同类型元素。
NumPy 数组属性
Section titled “NumPy 数组属性”- ndim:返回数组的维度(如 1 或 2)。
- shape:返回一个元组,表示各个维度中元素的个数。
- 示例:对于 2 维数组,
shape返回(行数, 列数)。
- 示例:对于 2 维数组,
示例:查看数组维度与形状
Section titled “示例:查看数组维度与形状”import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr1.ndim) # 输出: 1
print(arr2.ndim) # 输出: 2
print(arr1.shape) # 输出: (3,)
print(arr2.shape) # 输出: (2, 3)
NumPy 数组属性与常用创建方法
Section titled “NumPy 数组属性与常用创建方法”- 属性查询:
size:返回数组中元素的总个数。dtype:返回数组元素的类型,例如int64表示 64 位整数。
- 快速创建数组的方法:
np.zeros(n):创建长度为n、元素全为0的数组。np.ones(n):创建长度为n、元素全为1的数组(注意:默认类型为浮点数,显示时带小数点)。np.arange(start, stop, step):功能类似于 Python 内置的range,用于创建数字序列数组。- 参数含义:起始值、结束值、步长。
NumPy 实践开始:导入与 arange 示例
Section titled “NumPy 实践开始:导入与 arange 示例”arange 示例
Section titled “arange 示例”np.arange(5, 10, 2)返回array([5, 7, 9])。- 结束值不包含:10 不在数组中,因结束值不会被包含在范围内。
import numpy as np- 运行单元格以激活导入。
- 下载课程资料中不带答案的 Notebook。
- 先自行练习创建数组与查看属性,再验证答案。
创建第一个 NumPy 数组实践
Section titled “创建第一个 NumPy 数组实践”导入 NumPy
Section titled “导入 NumPy”import numpy as np- 必须导入,否则使用 np. 函数时报错。
- 若运行时报 module not found error,在 cmd 或终端执行
pip install numpy。
arr1 = np.array([元素列表])- 最直接方法:传入列表创建。
- 交互环境(如 Jupyter)直接输入变量名显示结果,无需
print()。
创建二维 NumPy 数组
Section titled “创建二维 NumPy 数组”- 定义:二维数组即数组中包含数组,通过嵌套列表创建。
- 创建语法:使用
np.array()并传入嵌套列表。- 示例:
np.array([[1, 3, 5], [2, 4, 6]])
- 示例:
- 注意事项:确保外层方括号内包含两个内层方括号,每个内层列表代表二维数组的一行。
Jupyter Notebook 快捷键
Section titled “Jupyter Notebook 快捷键”- Shift + Enter:运行当前单元格并跳转至下一个单元格,比手动点击工具栏运行按钮更高效。
元组在 NumPy 数组属性中的特殊表示
Section titled “元组在 NumPy 数组属性中的特殊表示”- 元组特性:NumPy 的
shape属性返回一个元组,即使该元组仅包含一个元素,Python 也会在末尾添加一个逗号(如(7,)),这是为了明确标识其为元组而非普通的括号数字。 - 区分单一元素元组与数字:
(7):会被解释为数字 7。(7,):被明确识别为只有一个元素的元组。
- 实际应用:在查看一维数组形状时,
shape返回(n,),这清晰地表明它是包含n个元素的一维结构,而非单纯的数值。
二维数组维度验证实践
Section titled “二维数组维度验证实践”第一维度:2 个元素
Section titled “第一维度:2 个元素”- 外层数组包含两个子数组。
第二维度:每个子数组 3 个元素
Section titled “第二维度:每个子数组 3 个元素”- 进入第一个子数组,包含3 个元素,对应
shape元组的第二个数字3。
元素总数 (.size)
Section titled “元素总数 (.size)”- 打印
.size属性显示总数(如 6 个)。 - 等同手动计数:数逗号数量 +1(一维:3 个;二维:6 个)。
元素类型 (.dtype)
Section titled “元素类型 (.dtype)”- 使用
.dtype查看数组元素类型。
NumPy 数组属性详解
Section titled “NumPy 数组属性详解”- .dtype (数据类型)
- 返回数组中元素的具体类型,例如
int64表示 64 位整数。 - 64 代表数据长度(比特),不同电脑配置可能导致输出结果(如
int32或int64)存在差异,这属于正常现象。
- 返回数组中元素的具体类型,例如
NumPy 数组初始化方法
Section titled “NumPy 数组初始化方法”- np.zeros(n)
- 创建一个长度为
n的数组,所有元素初始化为0。
- 创建一个长度为
- np.ones(n)
- 创建一个长度为
n的数组,所有元素初始化为1。 - 注意:生成的元素默认带有小数点,表示其类型为浮点数(float)。
- 创建一个长度为
数组命名与管理
Section titled “数组命名与管理”- 变量命名:在 Jupyter Notebook 中,可以通过赋值语句(如
arr_all_0 = np.zeros(6))为生成的数组命名,以便后续调用。 - 交互式显示:在 Jupyter 中,直接输入变量名即可查看数组内容,无需显式调用
print()函数。 - 命名规范:变量名中包含小数点(如
arr_all_0)在 Python 中是合法的,但需注意避免与浮点数语法混淆。
NumPy 范围数组与浮点初始化
Section titled “NumPy 范围数组与浮点初始化”np.ones() 浮点特性
Section titled “np.ones() 浮点特性”- 生成的全1数组元素带有小数点,表示浮点数类型(float)。
np.arange() 创建偶数序列
Section titled “np.arange() 创建偶数序列”- 需求:10到20之间的偶数,包括20。
- 语法:
np.arange(10, 21, 2)- 起始值:10
- 结束值:21(不包含,故用21确保20包含)
- 步长:2(生成偶数)
- 与内置
range()参数一致,但针对 NumPy 数组。
arange 输出演示与实践总结
Section titled “arange 输出演示与实践总结”arange 输出执行
Section titled “arange 输出执行”np.arange(10, 21, 2)- 输出:
[10 12 14 16 18 20]。
忘记 np. 前缀修正
Section titled “忘记 np. 前缀修正”- NameError:直接调用
arange报错name 'arange' is not defined。 - 修正:添加
np.前缀,即np.arange()。
数组创建与属性实践回顾
Section titled “数组创建与属性实践回顾”- 掌握:
np.array()、np.zeros()、np.ones()、np.arange()等创建方法。 - 属性:
.shape、.size、.dtype等基本查询。
后续数组操作预告
Section titled “后续数组操作预告”- 学习常见操作,如切片、数学计算等。
NumPy 数组拼接 (concatenate)
Section titled “NumPy 数组拼接 (concatenate)”添加元素方法
Section titled “添加元素方法”- 将现有数组与新元素数组用
np.concatenate()拼接成新数组。 - 参数形式:将数组放入列表中传参,例如
np.concatenate([arr1, arr2])。 - 支持无限长度列表,可一次性拼接多个数组。
数据类型统一规则
Section titled “数据类型统一规则”np.zeros()生成float64类型数组(元素带小数点)。- NumPy 数组数据类型必须统一,拼接结果自动转为浮点数。
- 假设已有
arr1 = np.zeros(...)和arr_new = np.array([新元素]) - 调用:
np.concatenate([arr1, arr_new])→ 返回新拼接数组。
多数组拼接便利性
Section titled “多数组拼接便利性”- 传入列表长度不限,非常方便处理批量拼接。
NumPy 数组切片与基本运算
Section titled “NumPy 数组切片与基本运算”- 单个元素:方括号内放一个数字(索引)。
- 切片范围:方括号内放两个数字
start:end。start:范围开头索引。end:范围结束索引(不包含该位置元素)。- 返回:从
start到end-1的所有元素。
- 与列表切片机制一致。
数组数学运算
Section titled “数组数学运算”- NumPy 数组强项:支持加减乘除等基本运算。
- 规则:形状相同的一维数组,对应位置元素逐一运算,返回新数组。
- 示例:两个数组相加 → 相同位置元素相加的结果数组。
- 列表对比:列表无法如此便捷实现逐元素运算。
NumPy 数组与数值的运算
Section titled “NumPy 数组与数值的运算”- NumPy 数组支持与单个数字的数学运算。
- 广播机制 (Broadcasting):如
arr * 3,数字3会应用到数组每个元素,类似向量与标量运算。
聚合运算 (Aggregation)
Section titled “聚合运算 (Aggregation)”- 通过一组值计算得到单一值:
max():求最大值。min():求最小值。sum():求总和。mean():求平均值。
- 调用:
数组名.方法名()直接返回结果。
NumPy 条件筛选与逻辑运算
Section titled “NumPy 条件筛选与逻辑运算”- 条件筛选 (Boolean Indexing)
- 通过
arr[arr > 6]语法,利用布尔数组对原数组进行索引。 - 广播机制:比较运算符(如
> 6)会作用于数组的每一个元素,生成一个由True和False组成的布尔数组。 - 筛选原理:在方括号内放入布尔数组,NumPy 会自动筛选出对应位置为
True的元素,返回一个包含这些元素的新数组。
- 通过
- 逻辑运算与复杂筛选
- 若要实现多条件筛选(如“大于6且小于10”),需使用逻辑运算符的位运算版本:
- 与 (AND):
& - 或 (OR):
| - 非 (NOT):
~
- 与 (AND):
- 语法示例:
arr[(arr > 6) & (arr < 10)] - 注意:每个条件表达式必须用圆括号
()括起来,以确保逻辑运算的优先级正确。
- 若要实现多条件筛选(如“大于6且小于10”),需使用逻辑运算符的位运算版本:
NumPy 多条件筛选实践
Section titled “NumPy 多条件筛选实践”AND逻辑筛选
Section titled “AND逻辑筛选”- 多条件筛选示例:
(arr > 6) & (arr < 10)。 &为位运算与(and)符号,筛选符合所有条件的元素。- 每个条件用圆括号括起,确保优先级。
配套资源与练习
Section titled “配套资源与练习”- 本节Jupyter Notebook在课程配套文件下载。
- 下节视频进行巩固练习。
- 导入:
import numpy as np。
数组创建实践:指定元素
Section titled “数组创建实践:指定元素”- 若要创建包含特定元素的数组,最直接的方法是使用
np.array()函数并传入一个列表。
arr1 = np.array([1, 3, 2, 4, 9])数组创建实践:全0与全1数组
Section titled “数组创建实践:全0与全1数组”- 创建全1数组:使用
np.ones()方法,传入数组长度。
arr2 = np.ones(5)- 创建全0数组:使用
np.zeros()方法,传入数组长度。
arr3 = np.zeros(3)- 提示:这些方法生成的数组元素默认为浮点数类型。
ALE 数组排序与索引实践
Section titled “ALE 数组排序与索引实践”- 排序两种方法:NumPy 的 sort 函数(不改变原数组) vs. 数组自身的 sort 方法(改变原数组)。
- 此处要求改变原数组,使用
ale.sort()。 - 验证排序:运行后
print(ale),确认元素从小到大排序。
ale.sort()print(ale)- 打印第三个元素:索引为 2,值为 2。
print(ale[2]) # 输出: 2数组负索引与切片实践
Section titled “数组负索引与切片实践”- 负索引:最后一个元素索引为 -1,倒数第二个为 -2,以此类推。
- 打印第三个元素:使用 -3(倒数第三个),与正索引 2 相同。
print(ale[-3]) # 等同于 ale[2]- 切片操作:提取部分数组,语法
arr[start:end]。- 第一个数字:起始索引(包含)。
- 示例:从第二个元素到第四个元素(不包含第四个)。
print(ale[1:4]) # 第二个到第四个元素数组切片示例 (ale[1:4])
Section titled “数组切片示例 (ale[1:4])”- 从索引 1(第2个元素)开始,到索引 4(不包含第4个元素)。
- 实际提取第 2、3、4 个元素(索引1、2、3)。
print(ale[1:4]) # 输出第2、3、4个元素数组逐元素相加 (A1 + A2)
Section titled “数组逐元素相加 (A1 + A2)”- 两个数组 A1 和 A2 长度均为 5。
- 直接逐元素相加,生成新数组。
- 输出:L1 + L2
l1_plus_l2 = a1 + a2 # 或直接 print(a1 + a2)print(l1_plus_l2)NumPy 数组元素运算
Section titled “NumPy 数组元素运算”数组直接运算 vs 列表循环
Section titled “数组直接运算 vs 列表循环”- NumPy数组支持元素级加减乘除,直接操作(如
arr1 + arr2)。 - 前提:数组长度相同。
- 列表需嵌套for循环,如
for e1 in list1和for e2 in list2,逐元素相加,麻烦。
数组乘标量实践
Section titled “数组乘标量实践”- 任务:A2每个元素乘 -5。
- 直接:
a2 * -5,无需循环。
a2 * -5NumPy 数组聚合方法
Section titled “NumPy 数组聚合方法”- arr.max():求最大值
- arr.min():求最小值
- arr.sum():求和
- arr.mean():求平均值
- 直接输出只显示最后一个结果,需print每个才能看到所有
print(arr1.max())print(arr1.min())print(arr1.sum())print(arr1.mean())NumPy 布尔索引筛选 (速度数组示例)
Section titled “NumPy 布尔索引筛选 (速度数组示例)”- 原题目:从 speed 数组筛选 <5 或 >2 的数字(覆盖所有数字)。
- 修改后:筛选 <1 或 >3 的数字。
- 单条件测试:
arr1 < 1→ 返回布尔数组(True/False,对应每个元素是否<1)。 - 筛选应用:
arr1[arr1 < 1]→ 只保留**<1** 的元素。
arr1 < 1 # 生成布尔数组arr1[arr1 < 1] # 布尔索引筛选NumPy 多条件布尔索引 (OR 组合)
Section titled “NumPy 多条件布尔索引 (OR 组合)”- 空布尔数组:
ar1 < 1全False,筛选结果为空数组,符合预期。 ar1 > 3:生成布尔数组,可筛选所有>3的数字。- 条件组合:用括号包围每个条件,中间用或符号
|连接,筛选**<1 或 >3** 的数字。
(ar1 < 1) | (ar1 > 3) # 布尔数组ar1[(ar1 < 1) | (ar1 > 3)] # 筛选结果NumPy 布尔索引 OR 筛选
Section titled “NumPy 布尔索引 OR 筛选”- NumPy中OR逻辑使用竖线
|表示,与Python内置or不同。 - 语法:
(条件1) | (条件2),每个条件需用括号包围。
(ar1 < 1) | (ar1 > 3) # 生成布尔数组ar1[(ar1 < 1) | (ar1 > 3)] # 筛选<1 或 >3 的元素NumPy 布尔索引 AND 筛选
Section titled “NumPy 布尔索引 AND 筛选”- AND逻辑使用**&**符号:
arr[(arr < 1) & (arr > 3)]。 - 仅返回同时满足多个条件的元素,每个条件需括号包围。
(ar1 < 1) & (ar1 > 3) # 布尔数组ar1[(ar1 < 1) & (ar1 > 3)] # AND筛选结果Pandas 库介绍
Section titled “Pandas 库介绍”- Pandas基于NumPy构建,继承其高性能数组计算功能。
- 优势:结合NumPy计算能力,适用于数据分析场景。
Pandas 安装与导入
Section titled “Pandas 安装与导入”- 安装:在终端或命令行中使用
pip install pandas(macOS 可能需要pip3 install pandas),过程与安装 NumPy 一致。 - 导入:惯例使用
import pandas as pd,通过别名pd调用库内方法,简化代码书写。
Pandas 数据结构:Series
Section titled “Pandas 数据结构:Series”- 定义:Series 是 Pandas 的基础数据结构,类似于 NumPy 的一维数组,但在处理标签数据时更具优势。
- 创建 Series:使用
pd.Series()方法,传入一个列表作为参数。
s1 = pd.Series([5, 17, 3, 26, 31])- 命名规范:
Series首字母需大写,因为它本质上是一个类(Class)的构造函数。
Series 的结构特性
Section titled “Series 的结构特性”- Series 与 NumPy 数组的区别:
- Series 不仅展示元素内容,还会自动在左侧显示对应的索引(Index)。
- 底部会显示
dtype,明确标识 Series 中元素的类型。
获取 Series 的元素与索引
Section titled “获取 Series 的元素与索引”- 独立获取:
- 使用
.values属性获取所有元素值(返回 NumPy 一维数组)。 - 使用
.index属性获取所有索引信息(返回RangeIndex对象,包含 start、stop 和 step 信息)。
- 使用
Series 的切片与索引操作
Section titled “Series 的切片与索引操作”- 操作逻辑:与 Python 列表和 NumPy 数组高度相似。
- 索引访问:
s1[2]返回索引为 2 的单个元素值。 - 切片操作:
s1[1:3]返回从索引 1 到 2 的部分 Series(不包含结束索引 3)。
- 索引访问:
- 核心差异:索引操作返回单个元素值,而切片操作返回一个新的 Series 对象。
Series 自定义索引 (Index)
Section titled “Series 自定义索引 (Index)”- 自定义标签:在创建 Series 时,可以通过
index参数为每个元素指定标签,不再局限于默认的整数索引。
s1 = pd.Series([5, 17, 3, 26, 31], index=["a", "d", "b", "c", "e"])- 索引显示:输出 Series 时,左侧将显示自定义的标签,而非默认的 0-4 数字。
Series 的两种取值方式
Section titled “Series 的两种取值方式”- 标签索引 (Label Indexing):使用自定义的标签名称直接访问元素。
- 示例:
s1['b']返回3。
- 示例:
- 位置索引 (Positional Indexing):依然可以使用原始的整数位置进行访问。
- 示例:
s1[2]返回3。
- 示例:
- 区分概念:自定义的标签索引也被称为“标签索引”,它为数据访问提供了灵活性,同时保留了原有的位置索引功能。
Series 切片操作
Section titled “Series 切片操作”- 切片一致性:切片逻辑与列表、NumPy 数组相同,既支持标签切片,也支持位置切片。
- 标签切片示例:
s1['d':'c'](注意:标签切片通常包含结束位置)。 - 位置切片示例:
s1[1:3](不包含结束索引)。
- 标签切片示例:
Series 切片操作的差异
Section titled “Series 切片操作的差异”- 标签切片 (Label Slicing):使用自定义标签进行切片时,结束标签是包含在内的(例如
s1['d':'c']会包含标签 ‘c’ 对应的值)。 - 位置切片 (Positional Slicing):使用整数位置进行切片时,遵循 Python 惯例,不包含结束位置(例如
s1[1:3]不包含索引 3)。 - 重要提醒:这种行为差异与 NumPy 和 Python 列表不同,需格外注意以避免逻辑错误。
获取多个元素
Section titled “获取多个元素”- 若要获取不连续或特定顺序的多个元素,可以在方括号内传入一个列表:
s1'a', 'e', 'c' # 按标签列表提取 s10, 4, 3 # 按位置列表提取- 这种方式不受原始顺序限制,可以随意调整返回元素的排列。
整数标签的混淆风险
Section titled “整数标签的混淆风险”- 当自定义索引本身为整数时(例如
index=[1, 3, 5, 7, 9]),直接使用s1[3]进行索引或切片容易产生歧义。 - 歧义点:无法直观判断是指“标签为 3 的元素”还是“位置为 3 的元素”。
- 解决方案:Pandas 提供了专门的方法来明确意图:
loc:强制使用标签索引进行取值或切片。iloc:强制使用位置索引进行取值或切片。
明确使用标签索引
Section titled “明确使用标签索引”s2.loc[3] # 获取标签为 3 的值
s2.loc[1:3] # 获取标签从 1 到 3 的切片(包含结束)
明确使用位置索引
Section titled “明确使用位置索引”s2.iloc[3] # 获取位置为 3 的值
s2.iloc[1:3] # 获取位置从 1 到 2 的切片(不包含结束)
Series 索引与切片的歧义处理
Section titled “Series 索引与切片的歧义处理”- 问题核心:当自定义索引为整数时,使用方括号
s[3]进行索引或切片会产生歧义,难以区分是指“标签为3的元素”还是“位置为3的元素”。 - 解决方案:Pandas 提供了显式方法来明确意图,彻底消除歧义:
.loc:强制使用标签索引(Label-based)。.iloc:强制使用位置索引(Integer-based)。
.loc 与 .iloc 的使用差异
Section titled “.loc 与 .iloc 的使用差异”| 场景 | .loc[索引] | .iloc[索引] |
|---|---|---|
| 单点取值 | 按标签查找 | 按位置查找 |
| 切片操作 | 包含结束标签 | 不包含结束位置 |
Series 数据的修改
Section titled “Series 数据的修改”- 修改 Series 中的值与字典操作类似,通过标签或位置直接赋值即可。
- 最佳实践:为了避免与位置索引混淆,建议统一使用
.loc或.iloc进行修改。
s3.loc['青菜'] = 4.5 # 使用标签修改s3.iloc[0] = 4.5 # 使用位置修改Series 标签存在性检查
Section titled “Series 标签存在性检查”- 使用
in关键字检查某个标签是否存在于 Series 的索引中,返回布尔值。
'青菜' in s3 # 返回 True 或 False创建 Series 的进阶方式
Section titled “创建 Series 的进阶方式”- 通过字典创建:直接将字典传入
pd.Series()构造函数,字典的键会自动成为 Series 的标签索引,值则对应数据。
s3 = pd.Series({'青菜': 4.1, '白萝卜': 2.2, '西红柿': 5.3})Pandas Series 条件筛选
Section titled “Pandas Series 条件筛选”- Series 支持与 NumPy 类似的布尔索引筛选,通过传入布尔 Series 作为索引,可以过滤出符合条件的元素。
- 筛选逻辑:
s3[s3 > 5]会返回一个仅包含满足条件元素的新 Series。
Pandas 逻辑运算与条件组合
Section titled “Pandas 逻辑运算与条件组合”- 在 Series 中进行多条件筛选时,可以使用逻辑运算符
&(与)、|(或)、~(非)。 - 重要规则:每个条件表达式必须用括号
()包围,否则会因优先级问题导致报错。
筛选大于5或小于3的元素
Section titled “筛选大于5或小于3的元素”s3[(s3 > 5) | (s3 < 3)]
- 逻辑运算符 `|` (或) 和 `&` (与) 在 Series 筛选中是必须的,不能直接使用 Python 原生的 `or` 或 `and` 关键字。Series浮点数示例与属性演示
Section titled “Series浮点数示例与属性演示”- 创建s1:
s1 = pd.Series([-1.2, 3.7, 8.5, -8.2, 6.3]),打印显示每个元素旁对应索引。 - 输出底部显示dtype: float64,表示浮点数类型,64bit长度。
s1.index # 返回所有索引s1.values # 返回所有元素值(NumPy数组)Series 反向自定义索引实践
Section titled “Series 反向自定义索引实践”- 创建示例:元素
[1,2,3,4,5],索引从5到1反向指定。
s = pd.Series([1, 2, 3, 4, 5], index=[5, 4, 3, 2, 1])- 效果:左侧索引显示
5,4,3,2,1,不再是默认0,1,2,3,4。 - 后续:取出指定元素任务。
Series 整数标签索引陷阱实践
Section titled “Series 整数标签索引陷阱实践”- 陷阱示例:自定义索引
[5,4,3,2,1]对应元素[1,2,3,4,5],位置第二个元素为2。 - 直接
s[1]按标签索引取值,返回5(标签1对应5),非预期位置值2。 - 原因:Series同时支持标签索引与位置索引,易混淆(讲者承认设计此陷阱)。
- 解决方案:用
.iloc[1]明确位置索引,返回2。
s.iloc[1] # 返回位置1的元素:2- 建议:索引取值始终用
.loc(标签)或.iloc(位置),避免歧义。
Series 标签切片实践 (5:3 示例)
Section titled “Series 标签切片实践 (5:3 示例)”- 位置索引成功:使用
.iloc[1]提取第二个位置元素 2。 - 标签切片:
s.loc[5:3]获取标签 5,4,3 对应的前三个元素。 - 切片陷阱:
- 位置切片(
.iloc):结束值不包含。 - 标签切片(
.loc):结束值包含在内。
- 位置切片(
Series 字典初始化演示
Section titled “Series 字典初始化演示”- 字典创建:直接传入字典到
pd.Series(),键自动成为标签索引。- 方法不变,仍用
pd.Series()。
- 方法不变,仍用
- 输入提示:打中文需切换输入法,但标点符号仍用英文。
s = pd.Series({5: 1, 4: 2, 3: 3}) # 键为标签- 当前状态:已创建字典初始化的 Series。
S3 小张标签更新实践
Section titled “S3 小张标签更新实践”- 更新操作:通过索引将小张对应值改为95,再输出新Series。
s3["小张"] = 95 # 或类似赋值print(s3)- 视觉确认:小张值变为95。
- 推荐使用&;
.loc:明确标签索引,避免方括号歧义(S3中文标签清晰,S2整数标签易混淆)。
s3.loc["小张"] = 95print(s3)S3 筛选 80-90 区间元素
Section titled “S3 筛选 80-90 区间元素”- 任务:输出 S3 中所有大于80 且小于90的元素。
- 布尔筛选原理:
s3 > 80返回布尔 Series,每个位置对应原标签,True 表示原值 >80,False 表示 ≤80。
- 完整条件:用
&(与)组合两个条件,每个用括号包围:
condition = (s3 > 80) & (s3 < 90)result = s3[condition]Series 间的算术运算
Section titled “Series 间的算术运算”- 自动对齐机制:对两个 Series 进行加减乘除运算时,Pandas 会根据索引 (Index) 自动对齐。
- 缺失值处理:
- 若某个索引只存在于其中一个 Series 中,运算结果在该位置会显示为
NaN(Not a Number)。 NaN表示无法得到计算值。
- 若某个索引只存在于其中一个 Series 中,运算结果在该位置会显示为
- 运算示例:
假设 s1 和 s2 是两个 Series
Section titled “假设 s1 和 s2 是两个 Series”result = s1 + s2
使用 fill_value 处理缺失值
Section titled “使用 fill_value 处理缺失值”- 方法替代运算符:当需要为缺失值指定默认值时,不能使用符号(如
+),必须使用.add()等方法。 - fill_value 参数:在方法中传入
fill_value参数,可以指定缺失位置的填充值。 - 优势:允许在计算过程中进行额外的参数填充,避免直接产生
NaN。
将缺失值填充为 0 后相加
Section titled “将缺失值填充为 0 后相加”s1.add(s2, fill_value=0)
- **运算一致性**:此逻辑同样适用于减法 (`sub`)、除法 (`div`) 等其他算术运算。Series 统计方法
Section titled “Series 统计方法”- NumPy 兼容性:Pandas Series 对象支持与 NumPy 数组相同的统计方法,能快速获取核心数据指标。
| 方法 | 功能 |
|---|---|
| .max() | 获取最大值 |
| .min() | 获取最小值 |
| .sum() | 获取总和 |
| .mean() | 获取平均值 |
describe() 方法
Section titled “describe() 方法”- 功能:提供 Series 数据的全面统计摘要,是 NumPy 中没有的特有方法。
- 输出内容:包含元素个数 (
count)、平均值 (mean)、标准差 (std)、最小值 (min)、四分位数 (25%,50%,75%) 及最大值 (max)。 - 数据类型:输出结果包含
dtype信息(如float64)。
Series 广播机制 (Broadcasting)
Section titled “Series 广播机制 (Broadcasting)”- 逐元素运算:当对 Series 与单个数字进行算术运算(如
s1 * 3)时,Pandas 会自动将该操作应用到 Series 中的每个元素,无需手动循环。 - 广播原理:此机制与 NumPy 的广播一致,极大地简化了批量数据处理。
Series 条件逻辑与函数映射
Section titled “Series 条件逻辑与函数映射”- 复杂逻辑处理:当需要根据 Series 的值进行复杂分类(如成绩评级)时,不能直接使用简单的数学运算。
- 自定义函数映射:
- 定义一个处理单个数值的函数(如
get_grade_from_score)。 - 编写逻辑判断(
if-elif-else)来返回对应的分类结果。 - 只要定义好该函数,即可将其应用到 Series 的每个元素上,实现基于分数的等级转换。
- 定义一个处理单个数值的函数(如
使用 apply() 方法处理 Series 元素
Section titled “使用 apply() 方法处理 Series 元素”- 场景:当需要对 Series 中的每个元素应用复杂逻辑(如成绩等级分类)而无法通过简单的数学运算实现时,可以使用
apply()方法。 - 核心机制:
apply()接收一个函数作为参数。- 它会自动遍历 Series 中的每个元素,将该元素作为参数传入函数中进行调用。
- 返回一个新的 Series,其元素为函数调用的结果。
- 代码示例:
定义处理逻辑的函数
Section titled “定义处理逻辑的函数”def get_grade_from_score(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "D"将函数应用到 Series 的每个元素
Section titled “将函数应用到 Series 的每个元素”grades = scores.apply(get_grade_from_score)
- **注意事项**: - `apply()` 不会改变原始 Series,而是返回一个新的 Series。 - 对于简单的逻辑,也可以直接使用 `lambda` 匿名函数作为 `apply()` 的参数,例如 `scores.apply(lambda x: x*x)`。 - `apply()` 极大增强了操作 Series 的灵活性。Series 创建与练习
Section titled “Series 创建与练习”- 导入Pandas:使用
import pandas as pd。 - 创建Series:向
pd.Series()传入列表,即可得到对应Series。 - 练习准备:下载课程资料中的Not Do(不带答案版),暂停练习后验证答案。
- 后续内容:更多Series操作练习。
Series 创建与 S1/S2 加法介绍
Section titled “Series 创建与 S1/S2 加法介绍”- 指定索引创建:使用
index=参数传入索引列表,直接创建对应标签的 Series。 - 打印验证:创建 S1 和 S2 后,使用
print()输出确认结构。
S1 + S2 加法机制
Section titled “S1 + S2 加法机制”- 相同索引相加:直接
s1 + s2实现相同索引位置元素相加。 - 索引对齐规则:Series 默认按索引对齐进行运算。
- NaN 产生原因:若某个索引只存在于一个 Series 中,对应位置产生 NaN(缺失值)。
Series 算术运算与缺失值处理
Section titled “Series 算术运算与缺失值处理”- 直接运算的局限性:使用
+等算术运算符时,若索引无法对齐,Pandas 会产生NaN(Not a Number) 值,表示无法计算。 - 使用 add() 方法处理缺失值:
- 若要避免
NaN,应使用.add()等算术方法替代运算符。 - 通过
fill_value参数可以为缺失值指定默认值(如0),从而实现补齐计算。 - 示例:
s1.add(s2, fill_value=0)会将缺失的索引位置视为 0 进行加法运算。
- 若要避免
- 适用范围:此逻辑同样适用于
sub()(减法)、mul()(乘法) 和div()(除法) 等方法。
S1 统计描述实践
Section titled “S1 统计描述实践”- 单独调用方法:
s1.max()获取最大值,s1.min()获取最小值。 - 便捷方法:
s1.describe()一行输出完整统计摘要。 - 输出指标:
count:元素个数mean:平均值std:标准差min:最小值25%:第一四分位数50%:中位数75%:第三四分位数max:最大值
Series 分数等级计算实践
Section titled “Series 分数等级计算实践”-
需求:根据分数 Series 计算对应的等级(90分以上 A,80-90分 B,70-80分 C,70分以下 D)。
-
解决方案:
- 定义一个普通 Python 函数,根据传入的分数返回对应的等级字符串。
- 使用
apply()方法将该函数映射到 Series 的每一个元素上。
-
关键点:
apply()接收函数名作为参数,返回一个新的 Series,不会改变原始数据。- 若逻辑简单,可配合
lambda匿名函数使用,语法为lambda 参数: 返回值。 - 这种方式比手动循环遍历 Series 更高效且灵活。
Series 广播机制
Section titled “Series 广播机制”- 标量运算:当 Series 与单个数值(标量)进行运算时,该操作会自动应用到 Series 的每一个元素上,无需显式循环。
Series 分数等级计算逻辑实现
Section titled “Series 分数等级计算逻辑实现”- 函数定义:使用
def定义一个处理分数的函数,通过if-elif逻辑链判断分数区间并返回对应的等级字符串(A/B/C/D)。 - 逻辑优化:在
elif判断中,由于前面的条件(如score >= 90)若满足会直接return结束函数,后续的判断(如score >= 80)默认隐含了score < 90的条件,因此无需显式使用and score < 90进行区间限制。 - 代码简化:
def get_grade(score): if score >= 90: return "A" elif score >= 80: return "B" elif score >= 70: return "C" else: return "D"等级函数测试与S1应用
Section titled “等级函数测试与S1应用”- 测试:
get_grade(85)返回 “B”;get_grade(55)返回 “不及格”。 - 应用到S1:
s1.apply(get_grade)将函数映射到 S1 每个元素,生成新等级 Series。 - apply特性:相当于高级的逐元素函数应用,不会修改原 S1。
apply() 函数传递规则
Section titled “apply() 函数传递规则”- 无括号传递:传入函数名时不要加括号
(),因为不是传递函数调用结果,而是传递函数本身,让apply()对每个 Series 元素自动调用。 - 运行演示:
s1.apply(get_grade)输出新 Series:每个成绩对应等级(如 A/B/C/D),旁边保留原始标签/索引,便于追踪原值对应关系。
下节预告:DataFrame 介绍
Section titled “下节预告:DataFrame 介绍”- Pandas 最强大结构:DataFrame(下一视频学习)。
DataFrame 基础结构
Section titled “DataFrame 基础结构”DataFrame 与 Series 的关系
Section titled “DataFrame 与 Series 的关系”- 数据结构层级:DataFrame 是由多个 Series 组成的二维数据结构,类似于表格。
- 核心优势:相比 NumPy 的二维数组(要求数据类型必须一致),DataFrame 的不同列可以存储不同的数据类型,是数据分析中最常用的结构。
DataFrame 的特性
Section titled “DataFrame 的特性”- 索引与列名:不仅拥有行索引(Index),还拥有列名(Columns),使其更像是一个由多个 Series 组成的字典。
- 结构类比:可以理解为以列名为键、Series 为值的字典结构。
创建 DataFrame
Section titled “创建 DataFrame”使用 Pandas 创建 DataFrame
Section titled “使用 Pandas 创建 DataFrame”- 方法:使用
pd.DataFrame()函数。 - 参数传递:传入一个字典,其中键为列名,值为对应的 Series 数据。
df = pd.DataFrame({“学号”: s_id, “班级”: s_class, “成绩”: s_grade})
- **输出效果**:执行后会生成一个排版整齐的表格,包含行索引(0, 1, 2...)和指定的列名。DataFrame 创建的灵活性
Section titled “DataFrame 创建的灵活性”- 数据源多样性:除了使用
Series字典创建 DataFrame,还可以直接传入列表 (List) 作为数据源。 - 索引对齐:DataFrame 默认的行索引(Index)与传入的 Series 索引保持一致;若传入列表,则默认从 0 开始递增。
- 保留标签索引:若传入的 Series 本身带有自定义标签索引,DataFrame 会自动继承这些标签作为行索引,保持数据关联性。
嵌套字典创建 DataFrame
Section titled “嵌套字典创建 DataFrame”- 多层级数据结构:可以通过传入“嵌套字典”(字典中包含字典)来一次性创建包含索引和列名的 DataFrame。
- 结构映射:
- 最外层字典的键(Key)对应 DataFrame 的 列名 (Columns)。
- 内层字典的键对应 DataFrame 的 行索引 (Index)。
- 内层字典的值对应具体的 数据值 (Values)。
获取 DataFrame 属性
Section titled “获取 DataFrame 属性”- 查看索引:使用
df.index获取所有行索引标签。 - 查看列名:使用
df.columns获取所有列名。
示例:通过嵌套字典创建
Section titled “示例:通过嵌套字典创建”df4 = pd.DataFrame({
"学号": {"小明": "01", "小红": "02"},
"班级": {"小明": "一班", "小红": "二班"}})
获取DataFrame的值与转置
Section titled “获取DataFrame的值与转置”- 获取原始数据:使用
.values属性可获取 DataFrame 中的所有数据,返回类型为 NumPy 数组,这意味着所有针对 NumPy 数组的操作(如切片、聚合运算)均可直接作用于该属性。 - DataFrame 转置:使用
.T属性(注意是大写字母 T)可实现行列互换,即行变列、列变行。
- 方括号提取:使用
df['列名']即可提取对应列,返回类型为 Series,且该 Series 会自动继承 DataFrame 的行索引(Index)。 - 点号提取:除了方括号,也可以使用
df.列名的语法来获取列数据,这在列名符合变量命名规则时更为简洁。
DataFrame 列提取的注意事项
Section titled “DataFrame 列提取的注意事项”- 属性访问法:由于每列 Series 实际上是 DataFrame 的属性,可以直接使用
df.列名获取,效果与df['列名']一致。 - 列名限制:若列名包含空格或特殊符号,则无法使用点号属性访问,此时必须使用方括号
df['列名']。
DataFrame 多列提取
Section titled “DataFrame 多列提取”- 列表传入:在方括号内传入一个包含多个列名的列表(例如
df'列名1', '列名2'),即可提取多个列。 - 返回值类型:提取多列后返回的是一个 DataFrame(而非 Series),因为结果由多个 Series 组成。
DataFrame 行提取
Section titled “DataFrame 行提取”- 索引定位:提取列使用列名,提取行则应使用索引。
- loc 与 iloc:
.loc['标签']:根据行标签索引提取。.iloc[位置]:根据行位置(整数)索引提取。
- 行数据类型:提取出的单行数据类型为 Series,这与提取单列数据的逻辑一致。
DataFrame 切片与多行提取
Section titled “DataFrame 切片与多行提取”- 切片规则:
- iloc (位置索引):切片遵循 Python 惯例,不包含结束位置(左闭右开)。
- loc (标签索引):切片包含结束标签(闭区间)。
- 多行提取:
- 若需提取不连续的行,可向
loc或iloc传入一个包含多个标签或位置的列表。 - 示例:
df.loc'小明', '小红'或df.iloc0, 2。
- 若需提取不连续的行,可向
DataFrame 元素级提取
Section titled “DataFrame 元素级提取”- 行列精准定位:
- 在
loc或iloc的方括号内使用逗号分隔两个参数:第一个表示行,第二个表示列。 - 格式:
df.loc[行标签, 列名]或df.iloc[行位置, 列位置]。
- 在
- 应用场景:此方法用于获取表格中特定单元格的数值,返回结果为该单元格的具体值(如字符串或数字)。
提取多列数据的技巧
Section titled “提取多列数据的技巧”- 方括号嵌套:若要提取多列,需使用双重方括号
df'列名1', '列名2',这在逻辑上等同于传入一个包含列名的列表,返回的是一个 DataFrame 对象。
DataFrame loc/iloc 双参数切片
Section titled “DataFrame loc/iloc 双参数切片”- 语法:
df.loc[行切片, 列切片]或df.iloc[行切片, 列切片],第一个参数行切片,第二个列切片,可截取表格任意部分。 - 切片规则:标签切片(loc)包含结束值;位置切片(iloc)不包含结束值(左闭右开)。
全范围省略技巧
Section titled “全范围省略技巧”- 保留所有行提取部分列:
df.loc[:, '列名']或df.iloc[:, 列位置],省略切片前后值,直接用冒号&;:表示全部范围。
不相邻行/列提取
Section titled “不相邻行/列提取”- 列表指定:
df.loc[[标签1, 标签2], '列名']或df.iloc[[位置1, 位置2], 列位置],通过位置或标签传入列表提取不相邻行/列。 - 灵活性:支持切片与列表混合,截取任意子集。
DataFrame 条件筛选
Section titled “DataFrame 条件筛选”条件筛选逻辑
Section titled “条件筛选逻辑”- 筛选原理:通过传入一个布尔 Series 作为行索引,DataFrame 会返回所有对应值为
True的行。 - 筛选语法:
df[df['列名'] > 阈值]。 - 行与列的筛选差异:
- 筛选行是基于条件逻辑,返回符合条件的行子集。
- 筛选列是基于列名,返回特定的列数据。
为什么筛选行而非列
Section titled “为什么筛选行而非列”- 数据分析意义:在数据分析流程中,行通常代表一个实例(如学生、城市),列代表属性(如身高、人口)。筛选符合特定条件的行(如“成绩大于80分的学生”)是提取符合业务逻辑的实例,这比单纯提取某一列属性更为常见且实用。
筛选实现示例
Section titled “筛选实现示例”筛选成绩大于80的行
Section titled “筛选成绩大于80的行”df[df[‘成绩’] > 80]
与 NumPy/Series 的一致性
Section titled “与 NumPy/Series 的一致性”- 逻辑相似性:DataFrame 的条件筛选逻辑与 NumPy 数组及 Pandas Series 的布尔索引完全一致,利用了相同的广播机制进行逐元素比较。
DataFrame 条件筛选原理
Section titled “DataFrame 条件筛选原理”- 筛选机制:通过传入一个布尔 Series 作为行索引,DataFrame 会保留所有对应值为
True的行。 - 代码语法:
df[df['列名'] > 阈值]。 - 行筛选的意义:行通常代表数据实例(如学生),列代表属性(如成绩)。筛选行是为了提取符合业务逻辑的实例,这比筛选列更具分析价值。
- 一致性:该筛选逻辑与 NumPy 数组及 Pandas Series 的布尔索引完全一致,利用广播机制进行逐元素比较。
逻辑运算符在 DataFrame 筛选中的应用
Section titled “逻辑运算符在 DataFrame 筛选中的应用”- 多条件组合:可结合逻辑运算符
&(与)、|(或)、~(非) 进行复杂筛选。 - 注意事项:
- 每个条件必须用括号
()包围,以确保运算优先级正确。 - 逻辑运算符与 Python 原生
and/or不同,需使用位运算符。
- 每个条件必须用括号
- 示例:
筛选成绩大于80且班级为三班的行
Section titled “筛选成绩大于80且班级为三班的行”df[(df[‘成绩’] > 80) & (df[‘班级’] == ‘三班’)]
DataFrame 快速预览方法
Section titled “DataFrame 快速预览方法”- head() 方法:用于快速查看 DataFrame 的前 N 行数据。
- 用途:在处理大型数据集时,通过
df.head()快速检查数据结构和内容,避免直接打印全部数据造成界面混乱。 - 示例:
df.head() # 默认返回前5行 df.head(2) # 返回前2行head() 方法参数详解
Section titled “head() 方法参数详解”参数指定行数
Section titled “参数指定行数”- 用法:
df.head(n),通过参数n指定查看前n行。
大数据集实用性
Section titled “大数据集实用性”- 场景:实际数据常达几千、几万甚至几十万行,直接打印易导致界面混乱。
- 价值:快速查看开头几行,了解数据包含的信息及各列变量特点。
df.head(2) # 查看前2行- 下载课程资料的无答案 Notebook,先自行练习创建 DataFrame 及操作,再验证答案。
- 第一步:熟悉
import pandas as pd引入。
通过 Series 作为列创建 DataFrame
Section titled “通过 Series 作为列创建 DataFrame”Series 创建基础
Section titled “Series 创建基础”- 语法:
pd.Series(数据列表, index=标签列表)。 - 示例:
s = pd.Series(['数据1', '数据2'], index=['小陈', '小李'])‘小陈’ 标签对应 ‘数据1’
Section titled “‘小陈’ 标签对应 ‘数据1’”DataFrame 列组合
Section titled “DataFrame 列组合”- 方法:多个 Series 分别作为 DataFrame 的列。
- 注意:代码中引号、逗号使用英文标点(非中文)。
标签对应规则
Section titled “标签对应规则”index参数为列表,顺序一一对应数据元素。- 示例:标签
['小陈', '小李']对应数据['值1', '值2']。
分类变量标签指定实践 (gender & hide)
Section titled “分类变量标签指定实践 (gender & hide)”gender 变量标签
Section titled “gender 变量标签”- 使用相同方法指定标签。
- 标签顺序反转:从 006 到 001(屏幕显示 001 到 006)。
hide 变量标签
Section titled “hide 变量标签”- 使用相同方法。
- 类型为分类数。
- 标签范围:001 到 005(故意少给一个数据)。
- 输入后必须运行,否则变量不会被创建。
使用 Series 构建 DataFrame
Section titled “使用 Series 构建 DataFrame”- 构建逻辑:通过
pd.DataFrame()传入一个字典,其中键(Key)为列名,值(Value)为对应的 Series 对象。 - 标签自动对齐:当使用多个 Series 创建 DataFrame 时,Pandas 会自动根据索引(index)标签进行对齐。
- 数据缺失处理:若某些标签在某个 Series 中缺失,Pandas 会自动将其标记为
NaN(Not a Number),处理方式与 Series 运算一致。
示例:将多个 Series 合并为 DataFrame
Section titled “示例:将多个 Series 合并为 DataFrame”df = pd.DataFrame({‘姓名’: name, ‘性别’: gender, ‘身高’: height})
DataFrame 预览与结构检查
Section titled “DataFrame 预览与结构检查”- 查看数据:使用
df直接输出整个表格的内容。 - 数据对齐验证:通过观察输出结果,检查不同 Series 的标签是否正确对齐,以及缺失数据是否被正确识别为
NaN。
DataFrame 的自动对齐机制
Section titled “DataFrame 的自动对齐机制”- 自动对齐原理:当使用多个 Series 创建 DataFrame 时,Pandas 会根据索引(index)标签自动进行对齐。
- 数据缺失处理:若某个标签在某个 Series 中缺失,Pandas 不会报错,而是自动将其标记为
NaN(Not a Number)。 - 对齐示例:
即使 Series 的索引顺序不同或长度不一,Pandas 也会根据标签自动匹配
Section titled “即使 Series 的索引顺序不同或长度不一,Pandas 也会根据标签自动匹配”students = pd.DataFrame({‘姓名’: name, ‘性别’: gender, ‘身高’: height})
- **观察输出**:通过直接打印 DataFrame,可以清晰地看到不同 Series 的标签对齐结果以及缺失值(NaN)的填充位置。DataFrame 索引与标签的灵活性
Section titled “DataFrame 索引与标签的灵活性”- 标签顺序不一致:即使传入的 Series 索引顺序不同(例如一个为 001-006,另一个为 006-001),Pandas 依然能根据标签正确拼凑出每一行数据。
- 索引对齐逻辑:创建时,Pandas 会取所有 Series 索引的并集作为 DataFrame 的索引,未匹配到的位置自动填充
NaN。
DataFrame 索引与列名属性及转置
Section titled “DataFrame 索引与列名属性及转置”.index 与 .columns 属性
Section titled “.index 与 .columns 属性”- 行索引:
df.index获取 DataFrame 的行索引。 - 列名:
df.columns获取 DataFrame 的列名。
- 语法:
df.T(属性,不加括号)。 - 效果:行变为列,列变为行。
df.T # 直接输出转置结果NaN 含义回顾
Section titled “NaN 含义回顾”- NaN:Not a Number,表示不存在真实值(缺失数据)。
DataFrame 身高列访问方法
Section titled “DataFrame 身高列访问方法”- 语法:
df.列名(如df.名字.身高)。 - 效果:直接输出身高数据。
方括号访问法
Section titled “方括号访问法”- 语法:
df['列名'](如df['名字'])。 - 优势:更通用,适用于列名含空格情况(如“身高 空格”)。
- 原因:点号法无法识别空格为列名一部分。
多列输出示例
Section titled “多列输出示例”- 输入姓名后加冒号,同时输出性别和身高。
DataFrame 多列提取实践
Section titled “DataFrame 多列提取实践”- 语法结构:在
df后使用方括号[],内部传入一个包含多个列名的列表。 - 代码示例:
同时提取性别和身高两列
Section titled “同时提取性别和身高两列”df’性别’, ‘身高’
- **关键点**:方括号内必须嵌套一个列表(`[[]]`),否则会因为参数数量不匹配而报错。DataFrame loc 列表提取介绍 (非连续行/列)
Section titled “DataFrame loc 列表提取介绍 (非连续行/列)”切片提取的局限
Section titled “切片提取的局限”- 非连续行问题:003和005不挨着,不能用
003:005,否则会包含004。 - 非连续列问题:姓名和身高不挨着,也无法用切片。
loc 列表提取方法
Section titled “loc 列表提取方法”- 使用
loc传入两个列表:- 第一个列表:行标签(如
[003, 005])。 - 第二个列表:列名(如
['姓名', '身高'])。
- 第一个列表:行标签(如
df.loc[ [行列表], [列列表] ]- 优势:loc 和 iloc 很万能,能提取任意指定位置。
DataFrame loc 全列输出实践
Section titled “DataFrame loc 全列输出实践”loc 提取非连续行所有列
Section titled “loc 提取非连续行所有列”- 场景:提取行标签
003, 005的所有列(全变量)。 - 切片语法:
df.loc[['003', '005'], '姓名':'身高']。
省略切片默认规则
Section titled “省略切片默认规则”- 省略冒号前:默认从首列(姓名)开始。
- 省略冒号后:默认到末列(身高)结束。
- 全列简写:
df.loc[['003', '005'], :]。
df.loc[['003', '005'], :] # 输出 003,005 行的所有列- 优势:无需逐列指定,高效输出完整行数据。
使用布尔 Series 进行条件筛选
Section titled “使用布尔 Series 进行条件筛选”- 场景:当需要根据特定条件(如身高大于165)筛选 DataFrame 中的行时,可以使用布尔 Series。
- 实现逻辑:
- 表达式
students['身高'] > 165会生成一个布尔 Series,其中每一行对应True或False。 - 将此 Series 传入
students.loc[]或直接作为索引,即可筛选出符合条件的行。
- 表达式
示例:筛选身高大于 165 的学生
Section titled “示例:筛选身高大于 165 的学生”students.loc[students[‘身高’] > 165]
- **特点**: - 返回结果是一个新的 DataFrame,仅包含满足条件的行。 - 这种方式非常直观,适合在数据分析过程中根据业务逻辑快速提取子集。多条件筛选与逻辑运算
Section titled “多条件筛选与逻辑运算”- 逻辑组合:可以使用
&(AND) 和|(OR) 运算符结合多个条件。 - 语法注意事项:
- 每个条件表达式必须用圆括号
()包裹,以确保正确的运算优先级。
- 每个条件表达式必须用圆括号
示例:筛选身高大于 165 且性别为女的学生
Section titled “示例:筛选身高大于 165 且性别为女的学生”students.loc[(students[‘身高’] > 165) & (students[‘性别’] == ‘女’)]
- **应用价值**:在复杂的数据分析任务中,能够灵活利用逻辑运算符进行多维度筛选是高效提取信息的关键。DataFrame 条件筛选:缺失值处理与 & 连接
Section titled “DataFrame 条件筛选:缺失值处理与 & 连接”缺失值筛选机制
Section titled “缺失值筛选机制”- 缺失值在比较运算中按 False 处理。
- 符合预期:缺失值不会出现在筛选结果中。
条件放入 .loc[] 方括号
Section titled “条件放入 .loc[] 方括号”- 将条件表达式放入
students.loc[条件]的方括号内。 - 效果:仅保留条件为 True 的行。
添加性别条件(布尔 Series)
Section titled “添加性别条件(布尔 Series)”- 第二个条件:
students['性别'] == '女',生成布尔 Series。
条件间 & 连接
Section titled “条件间 & 连接”- 多条件用 & 符号连接。
- 每个条件需用圆括号
()包裹,确保运算优先级。
DataFrame head() 方法与筛选验证实践
Section titled “DataFrame head() 方法与筛选验证实践”多条件筛选验证
Section titled “多条件筛选验证”- 示例:
(students['身高'] > 165) & (students['性别'] == '女') - 语法:用
&连接,每个条件必须用括号包围。 - 输出结果:仅筛选出小李(符合身高>1.6米且女性条件)。
head() 方法预览数据
Section titled “head() 方法预览数据”- 作用:快速查看数据开头。
- 语法:
df.head(n),显示前n行。
students.head(5) # 显示前5行 students.head() # 默认前5行- 优势:无需参数即可预览,便于快速检查数据集结构。
DataFrame 高级操作预告与数据分析实践
Section titled “DataFrame 高级操作预告与数据分析实践”DataFrame 常用操作概览
Section titled “DataFrame 常用操作概览”- 数据分析过程中,DataFrame 的操作非常频繁,掌握其高级用法能极大提升开发效率。
- 后续学习将深入探讨更多针对 DataFrame 的实用操作技巧。
更新 DataFrame 的列值
Section titled “更新 DataFrame 的列值”- 方法:通过重新赋值(Re-assignment)更新某一列的数据。
- 语法:
df['列名'] = 新的Series。 - 注意事项:
- 若 DataFrame 具有标签索引(Index),被赋值的 Series 也必须包含对应的索引属性。
- 确保新 Series 的索引与 DataFrame 的索引匹配,以保证数据的正确对齐。
示例:更新 ‘成绩’ 列
Section titled “示例:更新 ‘成绩’ 列”df1[‘成绩’] = pd.Series([90, 91, 83, 95, 94, 85], index=[‘001’, ‘002’, ‘003’, ‘004’, ‘005’, ‘006’])
DataFrame 列更新:列表与标签对齐
Section titled “DataFrame 列更新:列表与标签对齐”更新列的两种方式
Section titled “更新列的两种方式”- Series赋值:需标签对齐,否则产生缺失值。
- 列表赋值:自动按顺序对齐,无需标签,长度匹配DataFrame行数即可。
- 不存在列名时不报错,自动新增列,列名为指定名称。
- 通过loc/iloc提取行后同样可更新。
- Series赋值行:需标签与列名对齐,否则缺失值。
- 列表赋值行:按顺序对齐,更省事。
列更新示例:列表直接赋值
Section titled “列更新示例:列表直接赋值”df[‘新列’] = [值1, 值2, …] # 自动顺序对齐,或创建新列
df.loc[0] = [新值序列] # 列表按列顺序对齐
DataFrame 删除操作 (drop 方法)
Section titled “DataFrame 删除操作 (drop 方法)”- 语法:
df.drop(行标签)删除指定行。 - 多行删除:传入标签列表
df.drop(['标签1', '标签2'])。
- 语法:
df.drop('列名', axis=1)。 - axis=1 表示操作列(默认 axis=0 操作行)。
- drop() 仅返回新 DataFrame,不修改原数据。
- 永久删除:重新赋值
df = df.drop(...)。
示例:删除行
Section titled “示例:删除行”df = df.drop(‘标签名’)
df = df.drop([‘标签1’, ‘标签2’])
df = df.drop(‘列名’, axis=1)
DataFrame 的 axis 参数理解
Section titled “DataFrame 的 axis 参数理解”- 轴的概念:DataFrame 是二维结构,可以看作由两个轴组成:
axis=0:垂直方向,即纵向(行)。axis=1:水平方向,即横向(列)。
- 默认行为:大多数 DataFrame 方法(如
drop)默认axis=0,即默认对行进行操作。 - 统计与操作一致性:当沿纵向(axis=0)操作时,数据通常具有相同的含义和类型(如所有身高数据均为浮点数),这使得统计计算更为合理。
drop 方法的 axis 应用
Section titled “drop 方法的 axis 应用”- 删除行:
df.drop('标签')(默认 axis=0)。 - 删除列:
df.drop('列名', axis=1)。 - 逻辑记忆:将 axis 理解为“操作方向”,
axis=0是沿着索引向下,axis=1是沿着列名向右。
为什么需要 axis 参数
Section titled “为什么需要 axis 参数”- 灵活性:由于 DataFrame 的二维特性,明确指定 axis 可以消除操作歧义。
- 统一接口:许多后续的统计和数据处理方法都会频繁使用
axis参数,掌握此概念是与 Pandas 交互的基础。
DataFrame 与 DataFrame 算术运算
Section titled “DataFrame 与 DataFrame 算术运算”自动对齐机制
Section titled “自动对齐机制”- 列名对齐:相同列名(如A、B、C)直接对应计算,不同列(如DF1无D)在结果中填充NaN。
- 索引对齐:保留双方所有标签(如DF1: 001、003、005、007;DF2: 012),不匹配位置产生NaN。
- DF1 + DF2:
- 共同列A、B、C正常计算。
- DF1独有列或DF2独有D列全为NaN。
- 索引合并后,不对齐处为NaN。
result = df1 + df2 # 自动对齐列名与索引与Series一致性
Section titled “与Series一致性”- 类似Series + Series的索引对齐逻辑,扩展到二维结构同时处理行索引 + 列名。
DataFrame 算术运算的 fill_value 参数
Section titled “DataFrame 算术运算的 fill_value 参数”- 问题背景:直接进行
df1 + df2运算时,若索引或列名无法对齐,结果会产生NaN(缺失值)。 - 解决方案:使用
add()方法替代+运算符,通过fill_value参数指定填充值。- 语法:
df1.add(df2, fill_value=0) - 作用:在运算前,将无法对齐的位置填充为 0,从而避免结果中出现大面积
NaN。
- 语法:
缺失值计算的局限性
Section titled “缺失值计算的局限性”- 双重缺失场景:如果某个位置在两个 DataFrame 中都不存在(即双方都为
NaN),即使设置了fill_value=0,该位置的计算结果仍为NaN。- 原因:因为该位置在两个数据源中均无有效数值,无法进行加法运算,因此无法进行替换。
DataFrame 算术运算方法扩展
Section titled “DataFrame 算术运算方法扩展”- 除了
add()方法,Pandas 同样支持sub()(减),div()(除),mul()(乘) 等方法。 - 这些方法与
add()一样,均接受fill_value参数,用于处理运算中因索引或列名不匹配产生的缺失值。
DataFrame 与 Series 的算术运算
Section titled “DataFrame 与 Series 的算术运算”- 广播机制:当 DataFrame 与 Series 进行运算时,Pandas 会自动进行对齐。
- 对齐规则:
- Series 的索引会与 DataFrame 的列名进行对齐。
- 运算会应用到 DataFrame 的每一行上。
- 对齐失败的位置(即索引与列名不匹配)会产生
NaN。
广播机制原理
Section titled “广播机制原理”-
这种操作是 NumPy 广播机制在 Pandas 中的体现,允许不同形状的数据结构进行高效的逐元素运算。
-
运算过程:
- 匹配 Series 的索引与 DataFrame 的列名。
- 将该 Series 的操作广播到 DataFrame 的每一行。
- 无法对齐的部分填充为
NaN。
DataFrame 与标量运算注意事项
Section titled “DataFrame 与标量运算注意事项”- DataFrame 与单个数字运算时,操作自动广播到每一项数据。
数据类型注意
Section titled “数据类型注意”- 确保操作适用于所有数据类型:DataFrame可能含多种类型,同一操作在不同类型上效果不同或报错。
- 解决方案:先提取类型一致的部分DataFrame再运算。
创建 students DataFrame
Section titled “创建 students DataFrame”导入与数据准备
Section titled “导入与数据准备”import pandas as pd # 每次都需要导入使用字典创建 DataFrame
Section titled “使用字典创建 DataFrame”- 复制数据到中间变量
buildendata students = pd.DataFrame(buildendata)- 字典外层键自动成为列名
DataFrame 转置修正学生数据结构
Section titled “DataFrame 转置修正学生数据结构”嵌套字典默认结构问题
Section titled “嵌套字典默认结构问题”- 外层键 → 列名:如 ‘考试1’、‘考试2’ 成为列。
- 内层键 → 行索引:如 ‘001’、‘002’ 成为索引。
- 问题:需求要求学号为索引,但当前结构反转(学号成列名)。
T 属性转置解决方案
Section titled “T 属性转置解决方案”- 使用
students.T将行和列互换。 - 转置后:学号成为索引,考试科目成为列名。
students = pd.DataFrame(student_data).T # 转置并赋值- 转置后结构符合需求:学号为索引,科目为列。
DataFrame 添加新列实践
Section titled “DataFrame 添加新列实践”使用列表添加列
Section titled “使用列表添加列”- 先指定列名(如 ‘考试4’)。
- 用列表直接赋值,按行索引顺序依次填充数据。
students['考试4'] = [80, 90, 85] # 按索引 '001','002','003' 顺序添加Series 添加列的 NaN 问题
Section titled “Series 添加列的 NaN 问题”- 若用 Series 赋值,因索引不匹配(Series 索引如 ‘002’,‘003’),未匹配行变 NaN。
- 示例:
考试4列全为 NaN。
添加后结构验证
Section titled “添加后结构验证”print(students)- 新列成功添加,DataFrame 扩展为包含 ‘考试4’ 的完整结构。
DataFrame Series 索引对齐与行添加
Section titled “DataFrame Series 索引对齐与行添加”Series 索引对齐问题
Section titled “Series 索引对齐问题”- 默认无法对齐,需设置
index=[001, 002, ...]让 Series 索引匹配 DataFrame。
.loc 添加/更新行
Section titled “.loc 添加/更新行”.loc["007"]可获取行、更新行、添加行。- 标签 007 不存在时,等同添加新行,直接赋值列表。
students.loc["007"] = [列表数据] # 添加行DataFrame loc 添加行运行验证
Section titled “DataFrame loc 添加行运行验证”- 使用
.loc["007"] = [80, 75, 90, 85]添加新行。 - 运行后,新行成功出现。
students.loc["007"] = [80, 75, 90, 85] # 标签 007 不存在,执行添加操作DataFrame drop 删除多行
Section titled “DataFrame drop 删除多行”删除多行语法
Section titled “删除多行语法”- 使用
drop(列表, axis=0)删除指定行。 - axis=0:沿索引纵向操作(删除行)。
- axis=1:沿列名横向操作(删除列)。
students.drop(["006", "007"], axis=0) # 删除多行DataFrame axis 理解与操作
Section titled “DataFrame axis 理解与操作”- 二维结构轴线:DataFrame 可看作拥有两个轴线,纵向(行)为
axis=0,横向(列)为axis=1。 - 默认参数:大多数 DataFrame 方法默认
axis=0,因为沿纵向操作时,同列数据通常含义一致(如均为身高),利于统计。 - 删除操作差异:
drop(..., axis=0):沿索引纵向操作,删除行。drop(..., axis=1):沿列名横向操作,删除列。
DataFrame 算术运算机制
Section titled “DataFrame 算术运算机制”- 自动对齐:运算时(如
+,-,*,/)会根据列名和索引标签进行自动对齐,缺失部分默认填充为NaN。 - fill_value 参数:使用
add(),sub(),mul(),div()等方法时,可指定fill_value=0替代缺失值,但若两边该位置均为NaN,结果仍为NaN。 - 广播机制 (Broadcasting):
- DataFrame 与 Series:Series 的索引与 DataFrame 列名对齐,运算应用至每一行。
- DataFrame 与标量:数值运算直接应用至 DataFrame 的每一个元素,需确保数据类型一致以避免报错。
DataFrame drop 练习结果与 axis=1 指定
Section titled “DataFrame drop 练习结果与 axis=1 指定”删除 006/007 行结果
Section titled “删除 006/007 行结果”- 执行
drop(["006", "007"])(默认 axis=0),结果中这两行消失。 - 原始&;
students&;不变:drop返回新 DataFrame,未修改原数据。
axis=1 删除列预告
Section titled “axis=1 删除列预告”- 下一题:
drop(["考试2", "考试4"], axis=1)删除指定列。
Bonus Series 创建与加分实践
Section titled “Bonus Series 创建与加分实践”Bonus Series 定义
Section titled “Bonus Series 定义”- Bonus 表示考试加分:考试一全班+2分,考试二+3分,以此类推。
- 使用
pd.Series()创建,索引匹配 DataFrame 列名。
bonus = pd.Series({ "考试一": 2, "考试二": 3, ... }) # 键为列名,值为加分与 DataFrame 相加
Section titled “与 DataFrame 相加”students + bonus:广播加分到对应考试列。- 每个学生的该列分数自动增加对应加分值。
result = students + bonus # 输出加分后结果更新 DataFrame 列:广播加分实践
Section titled “更新 DataFrame 列:广播加分实践”-
场景:老师见考试四成绩太差,整体提升10分。
-
步骤:
- 提取列:
exam4 = students['考试四'](得到Series)。 - 广播加分:
exam4 + 10(每项统一+10)。 - 赋值更新:
students['考试四'] = exam4 + 10。
- 提取列:
exam4 = students['考试四']students['考试四'] = exam4 + 10 # 72 → 82- 效果:直接修改原DataFrame对应列,所有考试四分数增加10。
Jupyter Notebook 交互式执行与结果重置
Section titled “Jupyter Notebook 交互式执行与结果重置”- 交互式执行风险:
- 反复运行同一个单元格会导致数据(如分数)被重复累加。
- 逻辑一旦执行多次,结果会偏离预期,导致数据混乱。
- 重置与清理:
- 当数据状态混乱时,点击工具栏中的 Restart & Run All 按钮(重启内核并重新运行所有代码块)。
- 该操作会清空当前内存中的所有变量,并从头开始依次执行所有代码块,确保数据回到初始状态。
- 最佳实践:
- 尽量避免对单一单元格进行反复执行操作。
- 通过重启内核来验证代码逻辑的健壮性,确保无论运行多少次,最终结果均保持一致。
DataFrame 统计方法
Section titled “DataFrame 统计方法”统计函数概述
Section titled “统计函数概述”- 与 Series 类似,支持 max()、min()、sum()、mean() 等。
axis 参数控制方向
Section titled “axis 参数控制方向”- 二维特性:指定操作轴向
axis=0(默认):纵向,计算各列统计值(沿行方向)。axis=1:横向,计算各行统计值(沿列方向)。
df.mean():默认axis=0,返回各列均值(Series)。
DataFrame 统计方法的 axis 参数应用
Section titled “DataFrame 统计方法的 axis 参数应用”- 横向操作 (axis=1):
- 当指定
axis=1时,计算方向变为横向(沿列名方向)。 - 此时函数会对每一行数据进行统计(如计算每个学生的平均分)。
- 返回结果:返回一个 Series,其索引与原始 DataFrame 的行索引(Index)一一对应。
- 当指定
df.mean(axis=1) # 计算每一行的平均值复杂数据处理示例:去掉最高分与最低分
Section titled “复杂数据处理示例:去掉最高分与最低分”- 场景:在比赛评分中,通常需要去掉一个最高分和一个最低分后再计算平均值。
- 实现逻辑:
- 编写自定义函数
trim_mean(data),利用sum()、max()、min()和len()计算去极值后的平均值。 - 难点:DataFrame 本身没有内置此方法,且不应直接修改第三方库代码。
- 编写自定义函数
def trim_mean(data): data_len = len(data) data_sum = data.sum() max_num = data.max() min_num = data.min() return (data_sum - max_num - min_num) / (data_len - 2)使用 apply() 方法扩展 DataFrame 功能
Section titled “使用 apply() 方法扩展 DataFrame 功能”- apply() 的作用:将自定义函数应用到 DataFrame 的每一行或每一列。
- 执行机制:
- 当对 DataFrame 调用
apply()时,它会将每一行或每一列作为 Series 传入自定义函数。 - 配合
axis参数,可以灵活控制函数作用的维度。
- 当对 DataFrame 调用
将 trim_mean 应用到每一行 (axis=1)
Section titled “将 trim_mean 应用到每一行 (axis=1)”df.apply(trim_mean, axis=1)
- **逻辑优势**:通过 `apply()`,无需修改 Pandas 源码即可实现复杂的自定义统计逻辑,保持了代码的模块化与 DRY (Don't Repeat Yourself) 原则。DataFrame apply() 与 applymap() 区别
Section titled “DataFrame apply() 与 applymap() 区别”apply() 默认列操作
Section titled “apply() 默认列操作”- 默认行为:
axis=0(默认),每列数据依次传入函数。 - 示例:
trim_mean应用于每列,进行纵向去最高/最低求平均。
trim_mean(df, axis=0) # 每列作为参数,纵向统计axis=1 行操作
Section titled “axis=1 行操作”- 每行数据作为函数参数,实现横向统计(如每学生平均分)。
trim_mean(df, axis=1) # 每行传入函数applymap() 元素级应用
Section titled “applymap() 元素级应用”- 区别:函数应用于每一个元素,而非行/列。
- 示例:加5函数 → 所有数字元素+5。
df.applymap(lambda x: x + 5) # 每个元素独立处理- 返回新 DataFrame,原 DataFrame 不变。
- apply():行/列级;applymap():元素级。
DataFrame 的 describe() 方法
Section titled “DataFrame 的 describe() 方法”统计信息快速概览
Section titled “统计信息快速概览”df.describe()方法可一次性返回 DataFrame 中所有数值列的统计信息。- 包含指标:
count:非空元素个数mean:平均值std:标准差min/max:最小值与最大值25%/50%/75%:各分位数(50% 即中位数)
自动数据筛选特性
Section titled “自动数据筛选特性”- 智能忽略非数值列:若 DataFrame 中包含非数值类型(如字符串),
describe()会自动忽略这些列,仅对数值列进行统计计算。 - 无需手动处理:无需预先提取数值列,直接对整个 DataFrame 调用即可,极大简化了数据探索流程。
Series 字典组合创建学生平均分
Section titled “Series 字典组合创建学生平均分”- 数据已准备好,两个 Series 通过字典创建 DataFrame。
- 字典方式允许指定列名(如 student average)。
- 创建后查看结果,即为期望的学生平均分 Series。
后续:第二高分 Series
Section titled “后续:第二高分 Series”- 使用 max() 找每次考试最高分,输出第二高分 Series。
第二高分自定义函数实现
Section titled “第二高分自定义函数实现”无现成函数,建议用 lambda
Section titled “无现成函数,建议用 lambda”- 无内置函数获取第二高分。
- 建议结合匿名函数 (lambda) 创建,自行定义逻辑。
提取分数列与 apply 应用
Section titled “提取分数列与 apply 应用”- 用 loc 提取 DataFrame 的分数列。
- 用 apply() 应用函数到每列(
axis=0,默认值)。
获取 DataFrame 每列第二高分实践
Section titled “获取 DataFrame 每列第二高分实践”-
逻辑实现:由于 Pandas 没有直接获取“第二高值”的内置函数,需通过
apply()配合lambda匿名函数自定义逻辑。 -
操作步骤:
- 使用
.loc提取包含分数的子 DataFrame。 - 调用
.apply()方法,默认axis=0(纵向操作,即按列处理)。 - 在
lambda函数内部实现排序并取倒数第二位元素(或次大值)的逻辑。
- 使用
示例逻辑:对每列数据排序后取倒数第二个值
Section titled “示例逻辑:对每列数据排序后取倒数第二个值”df.apply(lambda x: x.sort_values().iloc[-2])
第二高分代码运行验证与等级函数引入
Section titled “第二高分代码运行验证与等级函数引入”运行与输出验证
Section titled “运行与输出验证”- 运行代码后查看结果,对比原始分数确认输出为每列第二大值。
- 可手动检查准确性。
清理与下一步
Section titled “清理与下一步”- 删除测试代码。
- 新需求:根据规则输出每个分数的等级。
- 先定义分数转等级函数。
分数等级函数定义
Section titled “分数等级函数定义”- 复杂场景下,用具名函数(如
gethrate)替代匿名函数。 - 对每个元素应用函数,使用 applymap() 方法传入函数名。
- 注意:直接运行会因非数值列(如姓名)报错。
def gethrate(score):函数定义逻辑
Section titled “函数定义逻辑”passdf.applymap(gethrate)
iloc 提取分数列与等级映射
Section titled “iloc 提取分数列与等级映射”数值限制与列提取
Section titled “数值限制与列提取”- 函数仅接受数字,非数字列传入会报错。
- 先用 .iloc 提取分数相关列。
applymap 应用与运行
Section titled “applymap 应用与运行”- 对分数列应用 applymap() 函数。
- 运行代码后得到分数等级。
df.iloc[...].applymap(gethrate)describe() 统计信息局限
Section titled “describe() 统计信息局限”最终任务:展示统计信息
Section titled “最终任务:展示统计信息”- 调用 describe() 方法。
输出仅 4 行
Section titled “输出仅 4 行”- Count:元素个数。
- Unique:独特值(非重复值)。
- 缺少:平均值、标准差、四分位数等完整统计信息。
Pandas describe() top/freq 与类型转换
Section titled “Pandas describe() top/freq 与类型转换”top 与 freq 含义
Section titled “top 与 freq 含义”- top:最常见的值(众数)。
- freq:最常见值出现的频次(频率)。
统计仅针对数值列
Section titled “统计仅针对数值列”- describe() 只对数字类型列展示统计信息。
- 无法对字符串求平均值或标准差。
分数列类型检查
Section titled “分数列类型检查”- 分数列类型为 object(宽泛类型,包括字符串、数字)。
- Pandas 中字符串常用 object 类型表示。
- 数字若为 object 类型,不会展示统计信息。
类型转换必要性
Section titled “类型转换必要性”- 需要将 object 类型分数列转换为数值类型,启用完整统计显示。
Series S-type 类型转换
Section titled “Series S-type 类型转换”describe() 对 object 列的处理机制
Section titled “describe() 对 object 列的处理机制”- 非数字列自动忽略:仅在 DataFrame 既有数字列又有非数字列时忽略非数字列。
- 纯 object 列情况:Pandas 认为无数字列,统一显示 object 类型信息(count、unique、top、freq)。
S-type 方法转换
Section titled “S-type 方法转换”- Series 方法:
S-type(int)将 object 类型分数列转换为整数类型。 - 效果:转换后
describe()显示完整统计(平均值、标准差等)。 - 后续应用:数据清理环节常用此方法。
数据获取方法与存储格式
Section titled “数据获取方法与存储格式”获取途径选择
Section titled “获取途径选择”- 优先API:网站提供时,直接获取结构化数据,更高效。
- 备选爬虫:无API时,从网页提取数据。
- 获取后存为csv、json等格式,便于后续读取修改。
- 网上下载数据也多为不同格式。
文件格式重要性
Section titled “文件格式重要性”- 不同格式需不同读取方法,先了解格式再用代码读取。
- 常见格式:txt、mp3、pdf、zip等。
文件名后缀与格式的本质
Section titled “文件名后缀与格式的本质”- 后缀的作用:文件名后缀(如
.txt,.mp3)仅是文件名的一部分,用于提示操作系统调用对应的默认程序打开文件。 - 修改后缀的后果:更改后缀名不会改变文件内部的实际数据格式或编码。如果将
.txt改为.mp3,系统会尝试用音乐播放器打开文本文件,导致无法正常读取。 - 数据格式的定义:数据格式不仅指后缀,更核心的是文件内部内容所遵循的特定规则(如 JSON 格式遵循 JavaScript 对象表示法规则)。
JSON (JavaScript Object Notation) 数据格式
Section titled “JSON (JavaScript Object Notation) 数据格式”JSON 概述
Section titled “JSON 概述”- 定义:全称为 JavaScript Object Notation,是一种轻量级的数据交换格式。
- 应用场景:广泛用于存储和交换信息,特别是在通过 API 获取数据时,数据通常以 JSON 格式返回。
- 优势:体积小,且能轻松被多种编程语言转换为其内部结构(如 Python 的字典和列表)。
JSON 与 Python 数据结构的对应
Section titled “JSON 与 Python 数据结构的对应”- JSON 对象:对应 Python 的字典(使用大括号
{})。 - JSON 数组:对应 Python 的列表(使用中括号
[])。
JSON 对象语法
Section titled “JSON 对象语法”- 基本结构:使用大括号
{}包裹,内部由键值对(Key-Value Pair)组成。 - 键值对规则:
- 格式为
"键": 值。 - 键必须是字符串,使用双引号包裹。
- 多个键值对之间使用逗号
,分隔。
- 格式为
{ "id": "1", "type": "article", "title": "Working with JSON data", "created": "2099-12-18T14:56:29.000Z"}JSON 数据格式规范与细节
Section titled “JSON 数据格式规范与细节”- 键的强制性规则:
- JSON 对象中的键(Key)必须是字符串,且必须使用双引号包裹。
- 相比之下,Python 字典的键可以使用数字或不可变数据类型,且引号使用较灵活。
- 嵌套规则:
- 该双引号规则不仅适用于顶层键,同样适用于嵌套在 JSON 对象或数组内部的所有键。
- 数据类型限制:
- JSON 值仅支持以下几种类型:
- 字符串(必须双引号)
- 数字(整数或浮点数)
- 布尔值(
true或false,注意 Python 为大写True/False) - 数组(
[]) - 对象(
{}) - 空值(
null,对应 Python 的None)
- JSON 值仅支持以下几种类型:
JSON 数据类型与 Python 的差异
Section titled “JSON 数据类型与 Python 的差异”- 布尔值 (Boolean):
- JSON 使用小写
true或false。 - Python 使用首字母大写的
True或False。
- JSON 使用小写
- 空值 (Null):
- JSON 使用
null。 - Python 使用
None。
- JSON 使用
- 数据类型兼容性:
- JSON 的值支持:字符串(必须双引号)、数字(整数/浮点数)、布尔值、数组 (
[])、对象 ({}) 和null。
- JSON 的值支持:字符串(必须双引号)、数字(整数/浮点数)、布尔值、数组 (
JSON 数据的嵌套与复杂结构
Section titled “JSON 数据的嵌套与复杂结构”- 嵌套支持:JSON 结构支持无限嵌套,例如对象内可以包含数组,数组内也可以包含对象。
- 数据交换优势:由于 JSON 的简洁性,它能被几乎所有主流编程语言轻松解析并转换为该语言内部对应的数据结构(如 Python 的列表或字典)。
JSON 练习与验证
Section titled “JSON 练习与验证”- 练习逻辑:通过判断给定的数据结构是否符合 JSON 规范(如键是否加双引号、布尔值大小写是否正确、是否存在重复键)来巩固理解。
- 常见错误:
- 键名未加双引号。
- 使用了单引号。
- 键名重复(JSON 标准中对象键应唯一)。
JSON 有效性判断示例
Section titled “JSON 有效性判断示例”第二个示例(无效)
Section titled “第二个示例(无效)”- 键未用双引号:学号、性别等键缺少双引号包围,必须是字符串形式。
- 布尔值错误:‘已毕业’ 值使用大写,与JSON要求的小写
true/false不符。
第三个示例(有效)
Section titled “第三个示例(有效)”- JSON 数组:以
[]开头结尾。 - 内容:三个
null值,JSON 支持此类型。
- 判断提示:需仔细查看细节才能确定是否有效。
JSON 数组有效性验证示例
Section titled “JSON 数组有效性验证示例”- 外层结构:中括号
[开头和]结尾,为数组。 - 第一个值(对象):
- 键使用双引号包围,为字符串。
- 值1:数字(整数)。
- 值2:内嵌数组,包含布尔值
true(小写)和整数 3。
- 第二个值:浮点数 3.14。
- 第三个值:数组,包含两个字符串。
- 最后一个值:布尔值(有效类型)。
结论:所有结构和值类型符合JSON规范,为有效JSON。
JSON 与 Python 的差异与解析
Section titled “JSON 与 Python 的差异与解析”JSON 与 Python 数据结构的差异
Section titled “JSON 与 Python 数据结构的差异”- 布尔值不匹配:JSON 使用小写
true/false,Python 使用大写True/False。 - 直接使用问题:JSON 数据直接传入 Python 会报错,无法识别小写布尔值。
- 解析步骤:需对 JSON 进行解析,才能转换为 Python 字典/列表进行分析。
- 解析优势:步骤简单,使用 Pandas 操作丝滑便捷。
JSON 优势回顾
Section titled “JSON 优势回顾”- 体积小:轻量级数据交换格式。
- 易转换:轻松转为编程语言内部结构(如 Python 的字典和列表)。
Pandas 解析预告
Section titled “Pandas 解析预告”- 使用 Pandas 读取和解析 JSON 数据,操作流畅,下节详解。
Pandas 读取 JSON 文件
Section titled “Pandas 读取 JSON 文件”read_json 函数
Section titled “read_json 函数”- Pandas 提供了
pd.read_json()函数,专门用于读取 JSON 文件并将其直接转换为 DataFrame。 - 该函数自动完成文件读取、JSON 解析以及 DataFrame 构建的全流程,避免了手动编写复杂解析代码的需求。
import pandas as pd将 JSON 文件路径作为参数传入
Section titled “将 JSON 文件路径作为参数传入”survey_df = pd.read_json(“./cell_phones_survey.json”)
JSON 与 DataFrame 的映射关系
Section titled “JSON 与 DataFrame 的映射关系”- 原始 JSON 结构:通常是一个包含多个对象的 JSON 数组。
- 映射规则:数组中的每一个 JSON 对象都会自动转换为 DataFrame 中的一行,对象的键(Key)对应列名(Column Name),值(Value)对应单元格数据。
为什么使用 Pandas 读取
Section titled “为什么使用 Pandas 读取”- 自动化处理:无需手动解析 JSON 格式中的嵌套结构或布尔值差异。
- 效率提升:如果不用 Pandas,解析 JSON 每一行数据并将其转化为 DataFrame 格式可能需要编写多行代码,而
read_json仅需一行即可完成。
JSON 对象与 DataFrame 的行映射机制
Section titled “JSON 对象与 DataFrame 的行映射机制”- 映射逻辑:JSON 数组中的每个对象自动对应 DataFrame 中的一行。
- 结构对齐:
- JSON 对象中的 Key(键)自动转换为 DataFrame 的 列名 (Column Name)。
- JSON 对象中的 Value(值)自动填充为对应单元格的 数据。
- 数据实例的一致性:这种结构天然契合 DataFrame 的设计理念,即每一行代表一个独立的数据实例,极大简化了从非结构化 JSON 到结构化表格的转换过程。
数据缺失与不规则处理
Section titled “数据缺失与不规则处理”- 非强制一致性:JSON 格式并不要求数组内所有对象拥有完全相同的键(Key)。
- Pandas 的处理策略:当某些对象缺少特定的键时,Pandas 会自动在 DataFrame 中对应位置填入
NaN(Not a Number),表示数据缺失,无需手动进行繁琐的预处理。
自动化数据分析流程
Section titled “自动化数据分析流程”- read_json 的优势:
- 传统方式:手动解析 JSON 嵌套结构、处理布尔值大小写差异、手动构建字典列表。
- Pandas 方式:仅需一行代码
pd.read_json()即可完成读取、解析、类型对齐及 DataFrame 构建,极大地提升了数据处理效率。
单个JSON对象解析为DataFrame
Section titled “单个JSON对象解析为DataFrame”键值映射规则
Section titled “键值映射规则”- JSON 键名 对应 DataFrame 的列名。
- 值 填充对应列的数据。
列表值展开机制
Section titled “列表值展开机制”- 当键值对的值为列表(如 Languages 长度为3)时:
- Pandas 将列表每个元素视为独立数据实例。
- 展开为3行,不能仅占一行。
数据对齐处理
Section titled “数据对齐处理”- 表格要求每列行数一致。
- 其他属性值自动复制3份,填充对齐。
- 结果:获得结构规则的表格。
总结:已学会将JSON文件转换为DataFrame,下节处理实际数据。
JSON vs CSV:数据格式偏好对比
Section titled “JSON vs CSV:数据格式偏好对比”程序员偏好 JSON
Section titled “程序员偏好 JSON”- JSON 结构易转换为编程语言原生结构。
- Python 示例:
- JSON 对象 → 字典。
- JSON 数组 → 列表。
- Pandas 支持:JSON → DataFrame,一步到位后续分析。
数据分析师偏好 CSV
Section titled “数据分析师偏好 CSV”- CSV 是数据分析师最爱格式(非 JSON)。
- 悬念:CSV 优势下期分解。
CSV (Comma-Separated Values) 格式解析
Section titled “CSV (Comma-Separated Values) 格式解析”CSV 的结构特性
Section titled “CSV 的结构特性”- 纯文本本质:CSV 文件本质上是纯文本,不包含复杂的格式信息(如字体、颜色等)。
- 表格化结构:虽然看起来杂乱,但通过逗号分隔,其结构就是一个标准的表格。
- 数据对齐:当 CSV 数据对齐后,每一行代表一条记录,每一列代表一个属性,结构非常直观。
CSV 的名称含义
Section titled “CSV 的名称含义”- 全称:Comma-Separated Values(逗号分隔值)。
- 设计逻辑:利用逗号作为字段间的分隔符,这种简单的设计使得 CSV 成为数据交换的通用格式。
CSV 与 Excel 的交互
Section titled “CSV 与 Excel 的交互”- 直接查看:无需手动处理分隔符,通过 Excel 等表格软件打开 CSV 文件,即可直接以表格形式展示数据。
CSV 文件结构规范
Section titled “CSV 文件结构规范”- 表头行:通常文件的第一行是表头(Header),用于定义每一列的名称(如 CustomerID, Gender, Age 等)。
- 数据行:后续行即为实际数据,与表头列一一对应。
- 灵活性:CSV 也可以没有表头,直接从数据行开始。
CSV 与 DataFrame 行对应与有效性
Section titled “CSV 与 DataFrame 行对应与有效性”行与值的直接对应
Section titled “行与值的直接对应”- CSV 行与 DataFrame 行直接对应。
- 每行数据包含的值数量必须相同,即逗号分割符数量一致。
CSV 有效性规则
Section titled “CSV 有效性规则”- 行数多或少,即为不合格无效的 CSV。
数据中逗号的处理
Section titled “数据中逗号的处理”- 若值内含英文逗号,用引号包围整个值,避免误解析为分隔符。
- 值含控制符,用两个逗号相邻表示中间内容存在。
CSV 结构优势
Section titled “CSV 结构优势”- CSV 为规整二维结构,一眼看出对应表格形状。
- DataFrame 也是二维,与之契合;JSON结构灵活、多层嵌套,难以直观对应表格。
CSV 文件创建与纯文本特性
Section titled “CSV 文件创建与纯文本特性”手动创建CSV文件
Section titled “手动创建CSV文件”- 使用代码编辑器或文本编辑器按CSV规则编写。
- 保存为**.csv**结尾文件。
纯文本格式优势
Section titled “纯文本格式优势”- CSV/JSON/TXT均为纯文本(重文本):无粗体、下划线、字号等格式。
- 益处:减少文件体积,读取时避免格式干扰。
- 非纯文本:Excel格式(含样式信息)。
编程数据格式偏好
Section titled “编程数据格式偏好”- 编程分析优先CSV/TXT等纯文本,或SQLite数据库。
Excel 与 CSV 兼容性
Section titled “Excel 与 CSV 兼容性”- Excel 可读取/修改/导出CSV。
- 多数系统默认用Excel打开CSV文件。
- 可在Excel编辑后导出为CSV。
大文件处理策略
Section titled “大文件处理策略”- Excel 的局限性:当 CSV 文件达到 GB 级别时,Excel 在加载数据、渲染格式及处理复杂功能时容易崩溃。
- 代码编辑器方案:处理超大文件时,优先使用代码编辑器或纯文本编辑器打开,避免 Excel 的性能瓶颈。
- Pandas 高效处理:
- 核心思路:将数据读取并转换为
DataFrame后,利用 Pandas 的方法(如head())仅查看部分数据,而非一次性加载所有内容。 - 优势:按需读取,显著降低内存占用,避免系统卡顿。
- 核心思路:将数据读取并转换为
使用 pandas 读取 CSV 文件
Section titled “使用 pandas 读取 CSV 文件”- 核心函数:使用
pd.read_csv()函数直接读取 CSV 文件并转换为DataFrame。 - 优势:
- 自动化处理:该函数自动处理文件读取、解析分隔符、构建 DataFrame 的全过程。
- 内存优化:通过
head()等方法仅加载并查看部分数据,避免一次性读取超大文件导致内存溢出或程序崩溃。
CSV 处理的性能对比
Section titled “CSV 处理的性能对比”- Excel 的局限:
- 面对 GB 级别的大文件,Excel 尝试渲染所有数据和格式会导致性能瓶颈,甚至程序崩溃。
- 适合小规模数据编辑,不适合海量数据分析。
- 代码方案的优势:
- 纯文本读取:Pandas 处理 CSV 时仅读取文本数据,无额外样式渲染开销。
- 按需加载:通过代码可以精准控制读取的数据量,实现高效的数据探索。
pd.read_csv() 大文件实践与 header 参数
Section titled “pd.read_csv() 大文件实践与 header 参数”16 万条数据读取演示
Section titled “16 万条数据读取演示”- 执行效率:传入 CSV 文件路径,几秒内将 16 万条数据文件转换为 DataFrame。
- 结果验证:前几行显示每条数据一行,属性值对齐。
header=None 参数处理
Section titled “header=None 参数处理”- 无表头文件:若 CSV 第一行无表头(直接数据开始),设置
header=None。 - 列名规则:首行视为第一条数据,列名自动用 0 开始的数字代替。
CSV 读取与索引优化
Section titled “CSV 读取与索引优化”- 自定义索引 (Index):
- 默认情况下
pd.read_csv()使用从 0 开始的整数作为行索引。 - 若 CSV 中某列(如
player_id)具有唯一标识属性,可在读取时指定index_col参数,将其设为索引。
- 默认情况下
pd.read_csv("./fifa_players.csv", index_col="player_id")- **优势**:读取后可直接通过 `df.loc[id]` 快速定位球员数据,无需依赖位置索引。DataFrame 显示优化
Section titled “DataFrame 显示优化”- 列显示限制:
- Pandas 默认隐藏中间的列(用省略号表示),这在列数较多时会丢失信息。
- 使用
pd.set_option可以调整显示的列数上限。
pd.set_option('display.max_columns', 50) # 将显示上限提升至 50 列- 场景:当数据包含大量特征列且需要全览时,此设置能有效避免自动省略带来的信息缺失。
调整 DataFrame 列显示上限
Section titled “调整 DataFrame 列显示上限”- Pandas 默认隐藏中间的列(显示为省略号),可通过
pd.set_option调整显示上限以查看所有特征列。
pd.set_option("display.max_columns", 150) # 设置显示列数上限为 150调整 DataFrame 列宽显示
Section titled “调整 DataFrame 列宽显示”- 当单元格内容过长(如球员标签或特征描述)导致显示不全时,可调整
display.max_colwidth参数。 - 默认字符上限为 50,可根据需要增加,例如设置为 500。
pd.set_option("display.max_colwidth", 500)获取 DataFrame 开头数据
Section titled “获取 DataFrame 开头数据”- 使用
head()方法快速预览 DataFrame 的前几行数据。 - 参数可传入整数以指定显示的行数,默认显示前 5 行。
获取 DataFrame 概况
Section titled “获取 DataFrame 概况”df.info(): 查看 DataFrame 的整体概况,包括行数、列数、每列的数据类型以及内存占用情况。- 对于列数较多的 DataFrame,该方法会仅显示部分概况信息。
- 如果数据量较小,该方法还会返回每列具体的数据类型及非空值的统计。
统计描述方法
Section titled “统计描述方法”df.describe(): 针对数值型数据列进行统计分析,一次性输出多种统计信息。- 输出内容包括:计数 (count)、平均值 (mean)、标准差 (std)、最小值 (min)、25%/50%/75% 分位数以及最大值 (max)。
- 仅适用于包含数值的列,对于非数值列,该方法会自动忽略。
代码计算速度优势
Section titled “代码计算速度优势”大数据处理性能对比
Section titled “大数据处理性能对比”- 110个变量数据:Pandas 计算不到1秒完成。
- Excel局限:无法瞬时处理,容易卡顿崩溃。
- 代码优势:高效处理海量数据,远超Excel。
数据清洗引入
Section titled “数据清洗引入”数据质量评估
Section titled “数据质量评估”- 数据获取后不立即分析。
- 先检查数据是否干净整洁。
- 如同买菜后检查泥土:先清洗泥垢虫子,再烹饪。
- 数据清洗:去除脏数据,确保质量。
数据结构评估
Section titled “数据结构评估”评估两个方面
Section titled “评估两个方面”- 结构:检查数据是否符合整洁标准。
- 内容:后续评估数据值质量。
乱数据 vs 整洁数据
Section titled “乱数据 vs 整洁数据”- 乱数据:结构不符合规范的原始数据。
- 整洁数据:符合埃德加·科德第三范式的三个特点:
- 每列是一个变量(如贷款金额)。
- 每行是一个观察值(如客户A的贷款)。
- 每个单元格是一个值。
贷款表格示例
Section titled “贷款表格示例”- 每列:贷款相关变量。
- 每行:一条贷款信息观察值。
- 每个单元格:单一值,符合整洁数据特点。
乱数据与整洁数据的转换
Section titled “乱数据与整洁数据的转换”- 乱数据的特征:
- 一列包含多个变量(如姓名、年龄、地址混在一起)。
- 一行包含多个观察值(如不同人的信息在同一行)。
- 单元格包含多个值,导致数据难以直接分析。
- 转换逻辑:
- 将乱数据拆解,使每一列仅代表单一变量。
- 将原本横向排列的多个观察值转化为纵向的独立行。
- 为什么需要转换:
- 整洁数据并非为了人类阅读方便,而是为了让代码能高效处理、分析和计算。
- 很多直观的 Excel 表格在数据分析标准下属于“乱数据”,必须先进行重构。
复杂结构数据的清洗
Section titled “复杂结构数据的清洗”- 多变量列处理:
- 遇到列中包含多个变量(如“人数”和“年龄组”混合)时,需将其拆分为独立的列。
- 整洁数据的核心价值:
- 统一格式后,计算机能更高效地进行聚合、筛选和统计计算。
- 避免了因结构不规范导致的逻辑错误或复杂解析。
数据内容质量评估
Section titled “数据内容质量评估”- 结构与内容双重检查:
- 结构评估:是否符合整洁数据规范(第三范式)。
- 内容评估:检查数据值本身是否存在缺失、异常或错误。
- 数据清洗的必要性:
- 即使结构整洁,若数据值存在错误(如录入错误、异常值),分析结果仍会偏离事实。
- 清洗过程是对原始数据进行纠错、补全或剔除,确保后续计算准确。
数据清洗的常见问题
Section titled “数据清洗的常见问题”- 数据缺失:
- 某些单元格为空值(NaN)。
- 需评估缺失值对分析的影响,决定是填充、删除还是保留。
- 数据重复:
- 同一观察值在数据集中出现多次。
- 需根据唯一标识符(如学号、ID)进行去重,避免统计偏差。
- 数据不一致:
- 同一变量在不同记录中格式或单位不统一(如日期格式混用、单位不一致)。
- 需进行标准化处理,确保数据可比性。
数据内容质量评估:不一致数据
Section titled “数据内容质量评估:不一致数据”- 定义:同一变量在不同记录中格式、单位或含义不统一。
- 常见场景:
- 单位不统一:例如身高数据有的以厘米为单位,有的以米为单位。
- 格式混用:如日期格式(YYYY-MM-DD 与 DD/MM/YYYY)或数字格式(中文数字与阿拉伯数字混用)。
- 全称与简称混用:例如“北京大学”与“北大”在同一列数据中并存。
- 清洗策略:必须进行标准化处理,统一单位、格式或命名规范,确保数据具有可比性。
无效或错误数据
Section titled “无效或错误数据”- 无效数据:脱离现实规则的数据,例如人的身高为负数。
- 错误数据:虽然符合格式规范,但数值逻辑不合理,例如成年人的体重记录为 3 公斤。
数据评估与清洗的自动化
Section titled “数据评估与清洗的自动化”- 手动评估的局限:当面对成千上万条数据时,肉眼检查效率极低,无法完成评估。
- 代码化处理:通过编写代码(如 Pandas)进行自动化清洗,能够快速识别并处理缺失、重复、不一致以及无效错误数据,是高效数据分析的前提。
DataFrame 数据评估方法
Section titled “DataFrame 数据评估方法”info() 方法
Section titled “info() 方法”- 提供列名、数据类型等概况信息。
- 快速了解结构:如列名
销售额小华星2010包含销售额和年份两个变量,不符合每列一个变量规则。
head() 和 tail() 方法
Section titled “head() 和 tail() 方法”- head():查看数据开头部分。
- tail():查看数据结尾部分。
- 通过部分数据评估整洁规则:每列一个变量、每行一个观察值、每个单元格一个值。
sample() 方法
Section titled “sample() 方法”- 参数传入行数,返回随机选出的行。
- 每次运行结果不同,用于全面评估数据质量。
检查 DataFrame 结构与缺失值发现
Section titled “检查 DataFrame 结构与缺失值发现”display() 展示限制与调整
Section titled “display() 展示限制与调整”- DataFrame 列数太多或值太长时,display() 展示不全。
- 使用 set_option() 方法调整列数或值长度上限。
info() 发现缺失值
Section titled “info() 发现缺失值”- info() 方法列出每列非空值数量。
- 与总行数对比,即可判断该列是否存在空缺值。
isna() 检查空缺值
Section titled “isna() 检查空缺值”- Series 或 DataFrame 调用 isna()。
- 返回布尔 Series/DataFrame:空缺值为 True,非空为 False。
- 检查原数据中每个值是否为空缺。
使用 isnull() 与 sum() 评估缺失值数量
Section titled “使用 isnull() 与 sum() 评估缺失值数量”- isnull() 局限性:直接调用
isnull()返回布尔值 DataFrame,对于大数据集难以直观判断缺失规模。 - sum() 聚合统计:在
isnull()后链式调用sum(),可统计每列缺失值的具体数量。- 对 Series 调用:返回单个缺失值总数。
- 对 DataFrame 调用:返回每列缺失值的 Series。
- 原理:Python 将
True视为 1,False视为 0。sum()通过对布尔值求和,将“是否存在缺失”转化为“缺失了多少个”。
布尔值在数学运算中的行为
Section titled “布尔值在数学运算中的行为”- True/False 的数值映射:在数学计算中,
True等同于 1,False等同于 0。- 示例:
True + 5结果为 6,False + 5结果为 5。
- 示例:
- 应用价值:此特性使得利用
sum()进行逻辑统计(如计算缺失值、统计满足条件的行数)变得非常高效。
缺失值数量统计实践
Section titled “缺失值数量统计实践”单列缺失值统计
Section titled “单列缺失值统计”- 提取某列 Series:
df['col']。 - 调用
isna()返回布尔 Series,再调用sum()得到空缺值个数。
全表缺失值统计
Section titled “全表缺失值统计”- 直接
df.isna().sum():- 返回 Series,索引为列名,值为各列空缺值数量。
- 因 DataFrame 列即 Series,逐列统计。
提取有空缺值的行
Section titled “提取有空缺值的行”- 使用条件筛选:
df[df['col'].isna()]。 - 提取符合条件的行,查看空缺值详情。
- 每列为 Series,可对特定列调用
isna()方式。
重复数据检查
Section titled “重复数据检查”duplicated() 方法
Section titled “duplicated() 方法”- Series 调用:返回布尔Series,检查当前值是否在前面出现过。
- 首次出现:False。
- 重复出现:True。
- DataFrame 调用:检查整行是否与前面某行完全相同。
- 仅当所有列值一致时标记为 True。
布尔条件筛选机制
Section titled “布尔条件筛选机制”- 将条件放入
df[condition]:保留所有 True 对应行。 - 示例:针对某列缺失值,提取包含空缺的行以深入分析。
重复数据检测
Section titled “重复数据检测”duplicated() 多列重复检查
Section titled “duplicated() 多列重复检查”- 常见场景:姓名重复可能是同名,地址重复可能是室友,但姓名+地址同时重复才算数据重复。
- 使用
duplicated(subset=[列1, 列2]):传入列列表,仅当指定多列同时重复时返回 True。 - 原理:布尔 Series 作为筛选条件,DataFrame 仅保留 True 对应行。
分类数据变种评估
Section titled “分类数据变种评估”- 难点:无法预测变种值(如拼写差异)。
- 应对:Series.value_counts() 返回各值频次统计,帮助识别异常变种。
评估不一致数据
Section titled “评估不一致数据”- 核心问题:不同数据值可能代表同一目标(如单位不一致、全称与简称混用、中文与阿拉伯数字混用)。
- 评估挑战:人工检查大型数据集不可行,需依赖代码自动化评估。
评估无效与错误数据
Section titled “评估无效与错误数据”- 无效数据:不符合逻辑规则的数据(如身高为负数)。
- 错误数据:符合格式规则但事实不准的数据(如成年人体重为 3 公斤)。
使用 Series.sort_values() 发现异常值
Section titled “使用 Series.sort_values() 发现异常值”- 原理:通过排序将极小值或极大值排在首尾,便于直观发现离群点。
- 应用:结合常识检查排序后的边界值是否合理。
使用 describe() 评估数值分布
Section titled “使用 describe() 评估数值分布”- 功能:快速展示数值列的最小值、最大值、均值等统计信息。
- 价值:通过极值(min/max)快速判断是否存在异常数据,无需手动遍历。
数据清洗:从评估到行动
Section titled “数据清洗:从评估到行动”评估后的清洗策略
Section titled “评估后的清洗策略”- 评估的目的是为了确定清洗的动作,遵循“有泥就冲水,有虫就摘虫”的原则。
- 清洗不仅仅是确认脏乱程度,而是基于评估结果制定具体的修复计划。
数据清洗的逻辑转换
Section titled “数据清洗的逻辑转换”- 评估(Assessment)是发现问题的阶段。
- 清洗(Cleaning)是解决问题的阶段。
- 结构性问题(如变量混杂)通常需要进行数据重构(如宽表转长表)。
- 内容性问题(如缺失、重复、异常)则需要针对性地删除、填充或修正。
持续的技能迭代
Section titled “持续的技能迭代”- 数据清洗技能随处理数据量的增加而变得熟练。
- 随着处理经验的积累,对数据异常的敏感度会提升,评估与清洗的效率也会随之提高。
数据清洗顺序:结构优先
Section titled “数据清洗顺序:结构优先”列名检查与优化
Section titled “列名检查与优化”- 处理内容前,先检查**列名(或行名)**是否有意义。
- 若列名乱七八糟,需重命名或重新排序,便于理解数据。
清洗优先级:结构先行
Section titled “清洗优先级:结构先行”- 一般顺序:先解决结构性问题,再处理内容性问题。
整洁数据 (Tidy Data) 原则
Section titled “整洁数据 (Tidy Data) 原则”- 每列一个变量。
- 每行一个观察值。
- 每个单元格一个值。
- 不符合以上三点均为乱数据。
结构性问题修复
Section titled “结构性问题修复”- 列=观察者、行=变量:需转置(行列对调)。
- 一列含多个变量:拆分列,将多变量分到其他列。
- 有时拆分不够:需进一步调整结构。
整洁数据结构规则与重塑实践
Section titled “整洁数据结构规则与重塑实践”- 确保每列只包含一种变量。
- 确保每行是一个观察值:若一行为多个观察值,需拆分行让每个独立成行。
- 有时光拆分不够,需重塑确保每行仅一观察值。
- 宽数据(清理前)→ 长数据(清理后):为程序高效处理,而非人类直观。
- 建议暂停审视清理前后例子差异。
缺失值处理策略
Section titled “缺失值处理策略”- 人工填充:当缺失值有明确的替代逻辑或真实值可考时,可手动填入。
- 不处理:若缺失值不影响当前分析目标,可选择忽略。
- 删除缺失行:若缺失的是关键变量,且该行数据对分析无贡献,直接删除该行。
- 统计值填充:利用平均值、中位数或众数等统计指标替代空缺值,以保持数据规模。
重复数据处理
Section titled “重复数据处理”- 直接删除:通过
duplicated()识别重复项后,直接删除重复行即可。 - 保留策略:若不删除,需意识到重复数据可能导致分析结果偏差(如计数翻倍)。
数据清洗流程总结
Section titled “数据清洗流程总结”- 人工填写缺失值
- 不处理缺失值
- 删除含缺失值的行
- 用统计值(如平均数)填充缺失值
针对不同数据和分析目的,清洗步骤存在差异,需根据实际情况灵活选择。
不一致数据标准化与异常处理
Section titled “不一致数据标准化与异常处理”不一致数据处理
Section titled “不一致数据处理”- 标准化原则:统一同义表达,只保留一种方式,其余替换。
无效/错误数据策略
Section titled “无效/错误数据策略”- 删除异常值:如异常身高记录拉低平均值,直接删除该行。
- Pandas NaN 特性:自动忽略空缺值,删除异常后平均值反而更准。
- 替换异常值:用当前平均数等合理值替换。
数据类型转换问题
Section titled “数据类型转换问题”- 读取时 Pandas 可能将手机号误识为数值型,导致可求 max/min(不符合实际)。
- 需手动转换类型,确保逻辑正确。
数据类型转换与列名清理实践
Section titled “数据类型转换与列名清理实践”字符串到布尔型转换
Section titled “字符串到布尔型转换”- 调查表中**‘是/否’字符串替换为True/False**。
- 数据本身无问题,但布尔型便于后续分析和逻辑判断。
Pandas实际清理操作预告
Section titled “Pandas实际清理操作预告”- 拆分列、删除重复行、处理缺失值、数据类型转换。
- 数据列名乱七八糟时,用**DataFrame.rename()**方法重命名。
使用 rename() 重命名索引和列名
Section titled “使用 rename() 重命名索引和列名”- 功能:通过传入字典参数修改 DataFrame 的索引 (
index) 或列名 (columns)。 - 语法:
df1.rename(index={old_name: new_name})
df1.rename(columns={old_name: new_name})
- **机制**:字典的键 (key) 为原名称,值 (value) 为新名称。- **注意事项**: - `rename()` 方法默认返回一个新的 DataFrame,**不会**修改原始数据。 - 若需原地修改,可使用 `inplace=True` 参数,或将结果重新赋值给原变量(如 `df1 = df1.rename(...)`)。rename() 方法进阶用法
Section titled “rename() 方法进阶用法”- inplace=True 优化:设置
inplace=True时,直接修改原 DataFrame,无需重新赋值;方法不返回新对象,避免复制开销。 - 字典重命名局限:适合少数列名修改;批量处理几十上百列时,手动编写字典过于繁琐。
- 函数重命名优势:传入针对 Series 的函数(Pandas 内置或自定义),原列名作为参数,函数返回值即新列名,实现高效批量处理。
rename() 方法的函数式批量处理
Section titled “rename() 方法的函数式批量处理”- 核心优势:当需要批量修改数十或上百个列名时,手动编写字典过于繁琐,利用函数进行批量转换更高效。
- 实现逻辑:
- 将现有的索引或列名作为参数传入指定的函数(如 Pandas 内置字符串方法或自定义函数)。
- 函数的返回值将自动作为新的索引或列名。
- 示例应用:
使用 str.upper 将所有列名批量转换为大写
Section titled “使用 str.upper 将所有列名批量转换为大写”df.rename(columns=str.upper, inplace=True)- **逻辑依据**:利用函数映射机制,将列名处理逻辑从“手动定义映射表”转变为“定义转换规则”,极大提升了大规模数据清洗的自动化程度。DataFrame 排序方法:sort_index()
Section titled “DataFrame 排序方法:sort_index()”- 默认行为:不指定
axis时,默认axis=0,沿着**行(索引)**纵向排序。 - 指定&;
axis=1:按列名排序。 - 关键特性(与
rename()类似):- 默认返回新 DataFrame,不修改原始数据。
- 使用
inplace=True:直接修改原 DataFrame,不返回新对象(无需赋值返回结果)。
索引与列名操作方法
Section titled “索引与列名操作方法”- set_index():将 DataFrame 中的某一列数据设置为索引,返回一个新的 DataFrame。
- reset_index():与
set_index()相反,将当前的索引重置为默认的整数序列,并将原索引作为一列数据添加回 DataFrame。
DataFrame 排序操作
Section titled “DataFrame 排序操作”- sort_index():对索引或列名进行排序。
- 默认行为:
axis=0(默认),按行索引(index)进行纵向排序。 - 列名排序:设置
axis=1,按列名(columns)进行横向排序。 - 原地修改:与
rename()一致,默认返回新对象。若需直接修改原 DataFrame,需设置inplace=True,此时方法不返回任何值。
- 默认行为:
数据清洗方法论总结
Section titled “数据清洗方法论总结”- 结构优先原则:在处理数据内容(脏数据)之前,必须先修复结构性问题(如行列转置、列名重命名、索引设置)。
- 整洁数据 (Tidy Data) 定义:
- 每列是一个变量。
- 每行是一个观察值。
- 每个单元格是一个值。
- 宽数据 vs 长数据:清洗过程常涉及将“宽数据”转换为“长数据”以利于程序处理,即便有时宽数据对人类阅读更直观。
- 缺失值处理策略:
- 忽略:Pandas 计算时自动跳过缺失值,适用于非关键变量。
- 删除:若关键变量缺失,直接移除该行。
- 填充:使用平均值、中位数或众数填补空缺。
- 不一致与异常数据处理:
- 标准化:将多种表达方式统一为一种(如将“是/否”字符串转换为
True/False布尔值,便于逻辑判断)。 - 异常处理:对于严重偏离的异常值(如身高记录错误),可选择删除或替换,防止其拉低整体统计指标。
- 标准化:将多种表达方式统一为一种(如将“是/否”字符串转换为
使用 str.split() 拆分列
Section titled “使用 str.split() 拆分列”- 适用场景:当某一列包含多个变量(例如“人口密度”列包含总人口和面积)时,需要将其拆分为独立的列。
- 基本语法:
针对字符串拆分
Section titled “针对字符串拆分”df[‘column’].str.split(‘/’)
- **返回结果**:默认返回一个包含列表的 Series,每个元素都是拆分后的子字符串列表。利用 expand 参数实现列扩展
Section titled “利用 expand 参数实现列扩展”- 问题:如果直接使用
str.split(),结果仍为 Series,无法直接作为 DataFrame 的多列存在。 - 解决方案:设置
expand=True参数。
将拆分后的结果直接扩展为 DataFrame 的多列
Section titled “将拆分后的结果直接扩展为 DataFrame 的多列”df[‘column’].str.split(‘/’, expand=True)
- **效果**:将拆分后的数据直接转化为一个新的 DataFrame,每一部分对应一列,便于后续分析。数据清洗总结
Section titled “数据清洗总结”- 结构重塑:在处理内容错误前,必须先完成列名重命名、索引设置、数据转置及多变量列的拆分。
- 整洁数据 (Tidy Data) 标准:确保每列仅代表一个变量,每行代表一个观察值,每个单元格仅包含一个值,这是后续高效计算的前提。
DataFrame 拆分列合并、删除与拼接实践
Section titled “DataFrame 拆分列合并、删除与拼接实践”新DataFrame 多列合并回原表
Section titled “新DataFrame 多列合并回原表”- 将拆分后的新DataFrame合并进原DataFrame:
df'col1', 'col2' = new_df # new_df 包含对应列- 列名存在时:更新列数据。
- 列名不存在时:添加新列。
删除拆分前原列
Section titled “删除拆分前原列”- 拆分后原列仍保留,使用drop删除:
df.drop('original_col', axis=1)- 完成结构性问题清洗。
Series 列拼接 (str.cat 方法)
Section titled “Series 列拼接 (str.cat 方法)”- Series的**
.str.cat()方法拼接另一个Series**。 - 后续:重复添加列 + 删除多余列操作。
宽数据转长数据 (Melt)
Section titled “宽数据转长数据 (Melt)”- 核心需求:将“宽数据”(多列表示同一类变量的不同取值)转换为“长数据”(将列名转换为变量值,便于分析和绘图)。
- 方法:
pd.melt(df, ...) - 关键参数:
id_vars:指定不需要转换、需保留的“标识列”(如:国家代码、年份)。var_name:转换后,原列名所在的新列的名称(例如:“年龄组”)。value_name:转换后,原单元格数值所在的新列的名称(例如:“肺结核病例数”)。
- 转换逻辑:
pd.melt将除id_vars之外的所有列名作为“变量”放入一列,并将对应的数值放入另一列。- 这种重塑使得数据更符合“整洁数据”原则,便于后续基于特定变量(如年龄组)进行分组聚合计算。
使用 melt() 进行宽数据转长数据
Section titled “使用 melt() 进行宽数据转长数据”- 核心需求:将“宽数据”(多列表示同一类变量的不同取值)转换为“长数据”(将列名转换为变量值),以便于后续分组聚合分析。
- 转换逻辑:
pd.melt将除id_vars之外的所有列名作为“变量”放入一列,并将对应的数值放入另一列。 - 关键参数:
id_vars:指定不需要转换、需保留的“标识列”(如:国家代码、年份)。var_name:转换后,原列名所在的新列的名称(例如:“年龄组”)。value_name:转换后,原单元格数值所在的新列的名称(例如:“肺结核病例数”)。
- 数据特性:
melt不改变原始 DataFrame,如需保存结果需重新赋值。
行拆分方法 explode()
Section titled “行拆分方法 explode()”- 适用场景:当 DataFrame 的某一列值是“列表”而非单一值时,需要将列表中的每个元素拆分为独立的一行。
- 实现方法:使用
df.explode('列名')。 - 优势:将原本包含多个课程的列表行,拆解为多个单行记录,便于针对“课程”进行统计(如计算某课程被选择的次数)。
行或列的删除方法 drop()
Section titled “行或列的删除方法 drop()”- 基本用法:
df.drop(labels, axis=...)。 - 参数说明:
axis=0(默认):删除行。axis=1:删除列。
- 特性:与
rename()一致,默认返回新对象,不修改原始 DataFrame;若需原地修改,需设置inplace=True。
处理缺失数据
Section titled “处理缺失数据”- 整列统一填充:针对整列缺失值,直接赋值统一值。
df['列名'] = 统一值所有元素替换为指定值。
- 特定位置填充:用 .loc[] 或 .iloc[] 定位后赋值。
- .loc 语法:
.loc[行标签, 列名] = 新值 - 示例:单个缺失值替换、指定位置填充。
- .loc 语法:
- 切片或部分替换:.loc/.iloc 提取的部分均可通过赋值填充或替换。
- 适用于单值、范围或条件选区。
- 大缺失场景:需自行定位位置,手动处理效率低。
自动化填充缺失值 (fillna)
Section titled “自动化填充缺失值 (fillna)”- Series.fillna():自动寻找所有 NaN 值并根据指定参数进行填充,无需手动逐个定位。
- 常量填充:
df['B'].fillna(0)将列中所有 NaN 替换为 0。 - 计算填充:可传入计算结果(如平均值),例如
df['B'].fillna(df['B'].mean())。
- 常量填充:
- DataFrame.fillna():支持对整个 DataFrame 进行全局填充,所有缺失值会被统一替换为传入的参数。
- 字典映射填充:支持传入字典,实现按列指定不同的填充值(例如
df.fillna({'A': 0, 'B': 10}))。
fillna() 方法的 inplace 参数
Section titled “fillna() 方法的 inplace 参数”- 默认行为:与
rename()和drop()一致,fillna()默认返回填充后的新 DataFrame(或 Series),不会修改原始数据。 - 原地修改:若需直接在原 DataFrame 上进行填充,可设置
inplace=True参数。
df4 = df4.fillna(0) # 重新赋值方式 df4.fillna(0, inplace=True) # 原地修改方式缺失值处理的决策逻辑
Section titled “缺失值处理的决策逻辑”- 填充 (fillna):适用于缺失值可以用特定值(如 0)或统计值(如平均值)合理替代的情况。
- 删除 (dropna):当缺失值出现在对分析目标至关重要的关键数据列中,且无法通过填充进行合理推断时,必须选择丢弃这些包含缺失值的观测值。
dropna() 方法应用
Section titled “dropna() 方法应用”- 核心功能:用于删除包含缺失值(NaN)的行或列。
- 默认行为:调用
df.dropna()时,默认删除所有包含至少一个 NaN 值的行。 - 适用场景:在清理数据时,如果某一行中任何一个关键指标缺失,调用此方法可以确保后续分析基于完整数据进行。
- 局限性:若数据清理更关注特定列的完整性,直接使用
dropna()可能会误删包含其他非关键列缺失值的行,需结合具体列名进行筛选。
使用 subset 参数精细化删除缺失值
Section titled “使用 subset 参数精细化删除缺失值”- 问题:直接调用
dropna()会删除包含至少一个 NaN 的整行,这可能导致非关键列的缺失误删了关键数据。 - 解决方案:使用
subset参数指定需要检查缺失值的列。
df.dropna(subset=['工资'])- **逻辑**:仅在 `subset` 指定的列中检查缺失值。如果这些关键列存在 NaN,则删除该行;若非关键列存在 NaN,则保留该行。dropna() 的 axis 参数控制
Section titled “dropna() 的 axis 参数控制”- 默认行为:
axis=0,沿着行索引操作,删除包含缺失值的行。 - 列操作:设置
axis=1,沿着列名操作,删除包含缺失值的列。- 应用场景:当某列大部分数据缺失且不具备分析价值时,可直接按列删除。
DataFrame 重复数据删除
Section titled “DataFrame 重复数据删除”duplicated() 与 drop_duplicates() 方法
Section titled “duplicated() 与 drop_duplicates() 方法”- drop_duplicates():删除 Series 中的重复值或 DataFrame 中的重复行。
- 默认行为:不传参数时,只有整行所有变量完全相同才视为重复并删除。
subset 参数指定列检查
Section titled “subset 参数指定列检查”- 语法:
df.drop_duplicates(subset=['列名1', '列名2']) - 逻辑:仅检查
subset列表中的列,若这些列值重复(即使其他列不同),则删除重复行。 - 示例:行 0 和行 4 的年龄不同,但若
subset=['姓名', '性别']相同,则视为重复删除。 - 特性:类似
dropna(),默认返回新 DataFrame,需inplace=True修改原数据。
drop_duplicates() keep 参数与删除规则
Section titled “drop_duplicates() keep 参数与删除规则”- 默认删除逻辑:相同行出现多次时,首次出现保留,后续重复删除。
- keep 参数控制:
- 默认
keep='first':删除第二遍及之后。 keep='last':保留最后一次,删除之前重复。
- 默认
- 不修改原数据:需重新赋值或设置
inplace=True。
Pandas replace() 方法
Section titled “Pandas replace() 方法”- 通用用法:适用于 Series 和 DataFrame,用法和效果相似。
- 单个值替换:传入两个值(如数字或字符串),将前者全部替换为后者。
df.replace(旧值, 新值)- 列表批量替换:第一个参数为列表,所有列表值替换为单一新值,实现同一替换。
df.replace([旧值1, 旧值2], 新值)- 字典映射替换:传入字典,指定不同旧值对应不同新值。
df.replace({旧值1: 新值1, 旧值2: 新值2})inplace 参数
Section titled “inplace 参数”- 默认行为:不修改原数据,返回新对象,需重新赋值。
- 原地修改:设置
inplace=True。
df.replace(旧值, 新值, inplace=True)Series 数据类型转换
Section titled “Series 数据类型转换”- 必要性:某些方法(如求平均值)仅适用于特定类型,不能对字符串求平均。
- astype() 方法:传入目标类型,如
int、float、str、bool。
s.astype(float)Pandas 类型检查与 Category 介绍
Section titled “Pandas 类型检查与 Category 介绍”type() 函数
Section titled “type() 函数”- 返回对象的类型名称。
- 忘记类型拼写时,可通过
type()查看。
Pandas 字符串类型
Section titled “Pandas 字符串类型”- Python 字符串在 Pandas 中显示为
object类型。 - 使用
astype(str)转换后,结果为object。
Category 类型
Section titled “Category 类型”- 分类数据:包含有限数量不同类别的数据。
- 示例:出生性别(仅两种类型)。
- 数据分为分类数据与数值数据。
Category 数据类型应用
Section titled “Category 数据类型应用”- 存储优势:将具有有限类别的列(如性别、部门、国家)转换为
category类型,可以显著节省内存空间。 - 分析优势:在后续进行统计分析或可视化时,Pandas 会自动选择最合适的统计方法或图表类型。
- 转换方法:使用
astype()方法进行转换。
将列转换为 category 类型
Section titled “将列转换为 category 类型”s1.astype(“category”)
Category 转换注意事项
Section titled “Category 转换注意事项”- 非内置类型:
category是 Pandas 库特有的类型,而非 Python 内置类型。 - 字符串引用:在
astype()中调用时,必须使用引号将其作为字符串传入(例如"category"),否则会报错。
数据分类逻辑
Section titled “数据分类逻辑”- 数值数据 (Numerical Data):指通过测量得到的观测值,具有具体的数值,支持求和、求平均值等数学运算(例如身高、人数)。
- 分类数据 (Categorical Data):指种类有限的数据,通常用于描述属性(例如性别、颜色、公司部门)。
保存清洗后的数据
Section titled “保存清洗后的数据”- 好处:清洗后保存干净版本,下次分析直接读取,避免重复评估和清洗步骤,节省时间。
- 本质:将 DataFrame 写入新建空白文件,对应
pd.read_csv()的写入方法。 - 方法:
to_csv(),传入文件路径参数。
df.to_csv('cleaned_file.csv')- 应用场景:完成清洗后立即保存,支持后续多种分析方式。
to_csv() 参数详解
Section titled “to_csv() 参数详解”- index 参数:
to_csv()默认会将 DataFrame 的索引(Index)一并保存到 CSV 文件中。如果不希望保存索引,可设置index=False。 - header 参数:默认保存列名。若不需要列名,可设置
header=False。
df.to_csv("cleaned_sales_data.csv", index=False)读写 CSV 的一致性问题
Section titled “读写 CSV 的一致性问题”- 索引偏移:若保存时包含索引(默认),读取时 Pandas 会自动将索引列识别为数据列(通常命名为
Unnamed: 0),导致列数增加。 - 解决方案:在读取时使用
index_col参数指定哪一列作为索引,或在保存时明确设置index=False以避免生成多余索引列。
CSV 索引列处理技巧
Section titled “CSV 索引列处理技巧”- 有意义索引恢复:读取CSV时若索引列被误认数据列,用
rename()为其换有意义名字,再用set_index()设为DataFrame索引。 - 写入时忽略索引:
to_csv(index=False)自动忽略索引写入,仅保存数据内容。 - 默认索引优势:下次读取无多余索引列(Unnamed: 0),无需额外处理。
- 有意义索引风险:若原索引含关键信息,
index=False会导致丢失;默认从0开始的索引则无此问题。
课程实践项目开启
Section titled “课程实践项目开启”- 经过数据评估原则与清洗方法学习后,上手实践评估和清理真实数据集。
- 实际项目:复习前面知识,通过动手深刻掌握数据相关技能。
更多数据集资源
Section titled “更多数据集资源”- 除了整理好的数据集,前视频提到的数据社区链接在文档中。
- 包括百度旗下平台、阿里旗下平台及数据科学相关社区。
- 探索更多有趣数据,可在不同平台查找。
- 下一节:开启第一个实际项目(时辰项目)。
实战项目总结与报告分享
Section titled “实战项目总结与报告分享”- 项目回顾:通过实战复习数据评估与清洗流程,综合运用之前技巧。
- 报告表达重要性:数据分析中需清晰表达逻辑与思路,关注报告结构与表达。
- .ipynb分享不便:文本编辑器打开内容不直观不可读;需用Jupyter Notebook或代码编辑器打开。
- 分享解决方案:上传到D号,便于他人查看。
GitHub 注册剩余步骤与仓库创建
Section titled “GitHub 注册剩余步骤与仓库创建”- 仅支持字母、数字、短横杠(-)。
- 输入中文不行。
邮件偏好与验证
Section titled “邮件偏好与验证”- 是否接受宣传邮件:输入 Y(想)或 N(不想)。
- 真人验证:点击验证按钮,旋转动物图片,点击提交。
- 点击 create account。
- 邮箱收到验证码,在页面输入完成注册。
登录后仓库创建
Section titled “登录后仓库创建”- 登录 github.com 主页。
- 创建仓库:点击 new 按钮。
- 仓库概念:相当于项目文件夹,所有项目相关文件存放在仓库下。
- 文件不能直接上传,必须在仓库之下。
GitHub 新建仓库选项配置
Section titled “GitHub 新建仓库选项配置”- 仓库名:仅字母、数字、英文句号、下滑线、短线,如
Python Data Analysis。 - Description:简短说明仓库内容,可用中文。
- Public/Private:Public 分享可见,Private 仅自己。
- Add a README file:提供项目介绍(.md Markdown 文件,使用前面学过的语法)。
GitHub 仓库初始化配置细节
Section titled “GitHub 仓库初始化配置细节”- README.md 的作用:作为项目的说明文档,支持 Markdown 语法,用于向访问者介绍项目背景、功能及使用方法。
- 初始化选项:
- Add .gitignore:可暂时选择忽略(None),后续根据需要添加。
- Choose a license:用于规定代码的使用权限(如是否允许商用、是否必须署名等)。
- License 资源推荐:若不确定选择哪种协议,可访问 choosealicense.com 查看不同开源协议的含义与适用场景。
- 仓库创建完成:配置完成后点击 Create repository,即可生成包含 README 文件的初始代码仓库,后续可直接在此基础上进行代码上传与管理。
GitHub 项目代码上传实践
Section titled “GitHub 项目代码上传实践”- 上传 Notebook 文件:
- 在仓库主页点击
Add file->Upload files。 - 将
.ipynb文件直接拖拽进上传区域。 - 支持一次性上传多个文件,包括 CSV 数据文件。
- 在仓库主页点击
- 提交记录 (Commit):
- 必须填写提交说明(Commit message),用于记录本次变更的内容。
- 提交后,GitHub 会自动渲染
.ipynb文件,使其在网页端即可直接阅读,无需本地环境。
GitHub 仓库文件管理
Section titled “GitHub 仓库文件管理”- 文件查看与交互:
- 点击仓库中的 Notebook 文件,GitHub 会将其渲染为可读的静态页面,保留了单元格代码与输出结果的排版。
- 文件删除操作:
- 进入具体文件,通过界面提供的删除选项(通常在文件预览页面的菜单中)即可移除不再需要的文件。
- Markdown 实时预览:
- 在 GitHub 编辑
README.md时,可以使用Edit模式配合Preview标签页,实时查看 Markdown 渲染效果,确保项目说明文档格式正确。
- 在 GitHub 编辑
GitHub 文件删除与 Markdown 实时预览
Section titled “GitHub 文件删除与 Markdown 实时预览”- 文件删除操作:
- 进入需要删除的文件页面。
- 点击右上角的“三点”菜单(通常包含
Delete file选项)。 - 注意:删除操作仅在点击
Commit changes按钮后才会正式生效,这体现了 Git 的版本控制逻辑。
- Markdown 实时预览:
- 在编辑
README.md等 Markdown 文件时,GitHub 提供Edit和Preview标签页。 - 通过在
Edit模式下修改内容并切换至Preview标签,可实时查看渲染效果,确保文档排版符合预期。
- 在编辑
数据分析报告分享链接
Section titled “数据分析报告分享链接”- 上传报告后获取GitHub链接。
- 将链接嵌入电子简历文字中。
- 查看者点击文字直接跳转项目,查看具体内容。
- 操作便捷。
DataFrame join方法简介
Section titled “DataFrame join方法简介”- join是方法,需在DataFrame上调用,非独立函数。
- 默认多列匹配(如客户ID等所有列)。
- 参数指定合并类型:left, right, inner, outer。
DataFrame join 重名列错误与后缀处理
Section titled “DataFrame join 重名列错误与后缀处理”- 重名列报错:CustomerDS4 和 OrderDS4 共享 CocoID 列,join 保留两表所有列导致冲突,直接报错。
- 后缀参数解决:
lsuffix:指定左表(CustomerDS4)后缀。rsuffix:指定右表(OrderDS4)后缀。
- 区分作用:结果中明确标识列来源,避免混淆。
- 与 merge 差异:join 不自动添加默认后缀,必须手动指定,否则报错。
课程回顾与数据重塑预告
Section titled “课程回顾与数据重塑预告”- 已学合并方法:
- concat:用于拼接(军阶)。
- merge:根据列值合并。
- join:根据所有列合并。
- 随着数据表增多,merge 使用频率增加,常用于复杂场景如数据不查。
超市销售数据示例
Section titled “超市销售数据示例”- 数据包含:超市分店、不同时间段、商品类别的销售额和销售数量。
- 数据本身整洁。
- 常见需求:查看不同分店的销售情况。
分属区操作引入
Section titled “分属区操作引入”- 分属区(pivot)和操作在数据分析中非常常见。
- 下一节学习更多数据重塑方法,提升 DataFrame 操作灵活性。
Pandas groupby() 分组操作
Section titled “Pandas groupby() 分组操作”- 问题:同一分店数据分散在多行,难以分析。
- 解决方案:使用
df.groupby('分电编号'),自动将相同值的行组合在一起。- 示例:所有001编号行聚合成组,所有002行聚合成组。
df.groupby('分电编号')- 结果:得到 DataFrameGroupBy 实例,不是 DataFrame。
- 原因:分组后每个组有多个数据,不是有效表格,无法直接查看结构。
聚合函数 (Aggregation Functions)
Section titled “聚合函数 (Aggregation Functions)”- 定义:指能够对一组数据进行汇总计算的函数,将多个数据点转化为单一结果。
- 常见聚合函数:
- 计数:
count() - 求和:
sum() - 平均值:
mean() - 最大/最小值:
max(),min() - 中位数:
median() - 标准差/方差:
std(),var() - 首尾元素:
first(),last()
- 计数:
- 应用场景:在
groupby分组后,通过调用聚合函数对各组数据进行统计。
分组聚合实践
Section titled “分组聚合实践”- 操作流程:先通过
groupby对数据进行分组,再调用聚合函数计算。 - 代码示例:
计算各分店销售额的平均值
Section titled “计算各分店销售额的平均值”df.groupby(‘分店编号’)[‘销售额’].mean()
- **逻辑**:`groupby` 生成 `DataFrameGroupBy` 实例,调用聚合函数后,Pandas 会自动对每一组内的数据应用计算逻辑,并返回一个包含统计结果的 `Series` 或 `DataFrame`。DataFrame 分组聚合运算逻辑
Section titled “DataFrame 分组聚合运算逻辑”- 分组后的状态:
groupby()返回的DataFrameGroupBy实例仅是逻辑上的分组,并不直接呈现为表格,必须配合聚合函数(如.mean())才能得到最终的Series或DataFrame结果。 - 聚合结果的维度:
- 若聚合前指定了单个变量,结果为
Series。 - 若聚合前指定了多个变量,结果为
DataFrame。
- 若聚合前指定了单个变量,结果为
- 索引规则:无论结果类型如何,分组变量(如“分店编号”)会自动成为结果的索引。
多变量分组聚合实践
Section titled “多变量分组聚合实践”- 可以在
groupby()中传入一个列表,实现基于多个变量的分组。
示例:同时对分店编号、销售额和销售数量进行分组聚合
Section titled “示例:同时对分店编号、销售额和销售数量进行分组聚合”df.groupby([‘分店编号’])’销售额’, ‘销售数量’.mean()
- **逻辑要点**:分组的完整逻辑是“分组 -> 聚合”,中间的 `DataFrameGroupBy` 状态仅用于定义分组规则,不包含实际的数据表格结构。自定义聚合函数
Section titled “自定义聚合函数”- 核心逻辑:除了内置的
mean()、sum()等聚合函数,还可以通过apply()方法传入自定义函数,实现更复杂的统计需求。 - 实现要求:自定义函数必须满足将
Series(一组数据)转换为单一数值的逻辑。
自定义函数实践示例
Section titled “自定义函数实践示例”def max_plus_10(nums): return nums.max() + 10在分组后使用 apply 调用自定义函数
Section titled “在分组后使用 apply 调用自定义函数”df.groupby(‘分店编号’)[‘销售额’].apply(max_plus_10)
- **适用场景**:当内置聚合函数无法直接满足业务逻辑(如本例中需在最大值基础上加 10)时,自定义函数提供了极高的灵活性。- **注意点**:`apply` 能够处理 `groupby` 生成的每个组,将该组的 `Series` 作为参数传递给自定义函数,并返回计算后的结果。Pandas pivot_table 透视表介绍
Section titled “Pandas pivot_table 透视表介绍”- pivot_table:Pandas 的聚合函数,中文为透视表,类似于 Excel 透视表功能。
- 作用:基于原始数据重塑表格结构并进行聚合运算,提升数据分析灵活性。
超市销售数据重塑示例
Section titled “超市销售数据重塑示例”- 场景:展示生鲜和休闲食品在不同分店及不同时间段的销售情况。
- 需求:直观查看各类商品在各分店、各时间段的销售总额。
- 实现参数:
- index=‘分店编号’(第一层索引)
- columns=‘时间段’(第二层索引)
- values=‘销售额’(求和值)
- aggfunc=‘sum’(聚合操作:求和)
- 效果:改变原始表结构,生成汇总透视表,便于分析。
ppppp 函数参数调用实践
Section titled “ppppp 函数参数调用实践”- 函数调用:传入
index、columns、values、rkfok参数。 - index:列表
['分店编号', '时间段']。 - columns:
'商品类别'。 - values:
'balance'。 - rkfok:
numpide.sum(求总额)。
ppppp( index=['分店编号', '时间段'], columns='商品类别', values='balance', rkfok=numpide.sum)- 原因:Series 底层实现就是 numpide 数组,所以针对数组的函数也可以用在 Series 上。
pivot_table 数据传递与默认 aggfunc 实践
Section titled “pivot_table 数据传递与默认 aggfunc 实践”- 关键错误:忘记传入
df,代码无法指定操作数据,必须传入df.pivot_table(...)。 - 默认行为:不传入
aggfunc时,默认使用mean()(求平均),运行正常生成表,无报错。 - 验证方式:运行无
aggfunc代码,观察表结构与行/列匹配设定。 - 实验建议:调整
index、columns、values、aggfunc参数,重塑表结构。 - 变换示例:
index='商品类别',columns='分店编号',继续计算聚合。
pivot_table 与 groupby 的对比
Section titled “pivot_table 与 groupby 的对比”- 功能重叠:两者均可用于分组聚合运算。
- 差异点:
- pivot_table:除分组外,支持将特定变量作为列 (columns) 进行重塑,生成更直观的二维透视表,便于阅读和理解。
- groupby:分组后,分组变量只能作为索引 (index),无法直接重塑为列,主要用于纯粹的聚合计算。
- 应用场景:当目标不仅是聚合,还需要改变表格结构以提升数据展示直观性时,首选
pivot_table。
分组聚合操作逻辑与实践建议
Section titled “分组聚合操作逻辑与实践建议”- 变量选择逻辑:想分析地区差异时,用地区变量分组聚合;想分析年龄差异时,用年龄变量分组聚合,直观直接。
- 初学者理解建议:分组聚合概念需时间消化,未完全理解可多看几遍或用 DataFrame 多操作实践。
- 核心价值:数据分析必备方法,根据分析切入点灵活选择分组变量。
pd.cut() 分箱返回 category Series
Section titled “pd.cut() 分箱返回 category Series”- pd.cut() 调用:传入 df1 的 年龄 Series + 已创建的分箱标准(bins)。
- 返回值:新的 Series,数据类型为 category(表示有限种类,如年龄范围、性别、公司部门)。
- category 优势:比字符串类型更节约内存空间。
- 结果依据:根据传入 bins 的划分生成区间类别。
pd.cut() 分箱操作详解
Section titled “pd.cut() 分箱操作详解”-
分箱目的:解决连续数值(如年龄)因取值过多导致分组后类别过于细碎的问题。
-
实现逻辑:
- 定义分箱边界列表(如
age_bins = [0, 10, 20, 30, 40, 50, 60, 120])。 - 使用
pd.cut(series, bins)将数值映射到预定义的区间中。
- 定义分箱边界列表(如
-
返回值特性:
- 返回一个
category类型的Series。 - 内存优势:相较于字符串(object)类型,
category类型在处理有限种类数据(如年龄段、性别、部门)时能显著节省内存。
- 返回一个
区间表示符号含义
Section titled “区间表示符号含义”- 圆括号&;
():表示不包含该端点值(开区间)。 - 方括号&;
[]:表示包含该端点值(闭区间)。 - 示例:
(40, 50]表示大于 40 且小于等于 50 的范围。
自定义分箱标签
Section titled “自定义分箱标签”- 需求:默认的区间表示(如
(40, 50])较为数学化,不够直观。 - 解决方案:通过
labels参数传入自定义名称列表(如['儿童', '少年', '青年', ...])。 - 实现代码:
age_labels = ['儿童', '少年', '青年', '中年', '中老年', '老年'] pd.cut(df['年龄'], bins=age_bins, labels=age_labels)- 优势:将抽象的数字区间转换为具有实际业务含义的分类标签,便于后续分组统计。
pd.cut() labels 执行结果与 DataFrame 列添加
Section titled “pd.cut() labels 执行结果与 DataFrame 列添加”- 结果验证:
pd.cut()返回 category 类型 Series,值替换为指定 labels(如age_labels)。 - 标签对应规则:
- 第一个标签
'儿童'→ 第一个区间(0, 10] - 第二个标签
'青少年'→ 第二个区间(10, 20] - 依此类推,按 bins 顺序一一映射。
- 第一个标签
- 分组应用:添加为 DataFrame 新列(如
'年龄段'),后续按年龄范围轻松分组聚合分析。
分组聚合的层级索引 (Hierarchical Indexing)
Section titled “分组聚合的层级索引 (Hierarchical Indexing)”- 多变量分组现象:当
groupby()使用多个变量(如['分店编号', '时间段'])进行分组时,生成的DataFrame会自动产生层级索引。 - 层级索引提取:
- 依然可以使用方括号
[]配合标签索引来提取特定行。 - 使用
.loc访问时需注意层级结构,例如grouped_df.loc['001']可以提取分店 001 的所有时间段数据。
- 依然可以使用方括号
- 外层索引与切片:当使用
.loc对外层索引进行切片(如grouped_df.loc['001':'002'])时,可以一次性获取多个分店的数据,操作逻辑与普通DataFrame一致。
层级索引重置与内层提取
Section titled “层级索引重置与内层提取”- 内层索引提取:对多层级结果使用内层索引继续提取特定行,如
grouped_df.loc['001', '上午']获取单行数据。 - reset_index() 方法:重置层级索引为普通整数索引(从0开始),原层级索引转为新列数据。
- 效果:消除层次化结构,所有索引值变为独立列,便于后续操作。
DataFrame query() 方法介绍
Section titled “DataFrame query() 方法介绍”- query() 功能:获取符合条件的行组成的 DataFrame。
- 与布尔索引等价:结果同将 布尔 Series 传入
df[]筛选 True 行,但写法更简洁直观。 - 调用语法:
df.query('字符串条件'),query 是 DataFrame 方法,传入字符串表达式。 - 示例:用字符串替换复杂布尔条件,直接过滤数据。
DataFrame query() 方法语法细节
Section titled “DataFrame query() 方法语法细节”- 列名引用:在
query()的字符串表达式中,列名直接使用,无需引号包围,也无需通过df['列名']引用。 - 字符串值处理:
- 若
query()外部使用单引号,内部字符串值应使用双引号(反之亦然),以避免引号嵌套冲突。 - 若内外引号类型必须一致,可在内部引号前使用反斜杠 `` 进行转义(例如 `‘性别 == “男”’
或’性别 == \‘男\’’`)。
- 若
- 逻辑连接:
query()支持直接使用and和or关键字进行多条件逻辑连接,相比布尔索引的&和|符号,语义更接近自然语言。
Netflix美剧数据集项目实践
Section titled “Netflix美剧数据集项目实践”- 项目目标:使用真实 Netflix美剧数据集 进行数据整理,复习知识并掌握数据技能。
- 数据集内容:包含 两个数据文件(用于练习数据连接)+ 数据集介绍的 Jupyter Notebook 文件。
- 准备步骤:
- 下载数据集和 Notebook 文件。
- 创建 单独文件夹 保持文件结构整洁,将所有文件放入同一目录。
- 启动实践:打开并运行 Jupyter Notebook,开始实际数据整理。
Netflix 数据集分析目标
Section titled “Netflix 数据集分析目标”- 分析任务:
- 按流派整理影视作品(喜剧片、动作片、纪录片等)。
- 计算各流派中不同演员出演作品的平均IMDb评分。
- 找出各流派评分最高的演员。
- IMDb 解释:国外版豆瓣,用户为影视作品打分。
- 应用场景:导演选角,如查看喜剧片平均评分最高的演员。
- 数据集特点:聚焦Netflix电视剧与电影(相当于国外腾讯视频/爱奇艺),包含两个数据文件。
Netflix 数据集文件结构与关联
Section titled “Netflix 数据集文件结构与关联”- titles.csv:包含影视作品核心信息(ID、标题、类型、描述、流派、IMDb评分等)。
- credits.csv:包含演职人员信息(姓名、角色、所属作品ID)。
- 关联机制:两表通过“影视作品ID”进行关联,确保能将演员信息与具体作品及其评分对应起来。
数据分析目标与应用
Section titled “数据分析目标与应用”- 核心任务:
- 按流派(喜剧、动作、纪录片等)归类作品。
- 计算各流派中演员的平均 IMDb 评分。
- 识别各流派中评分最高的演员。
- 分析价值:
- 选角决策:导演可通过数据分析,筛选特定流派中平均评分最高的演员,优化选角策略。
- 背景知识:IMDb 相当于国外版“豆瓣”,Netflix 相当于国外版“腾讯视频/爱奇艺”。
数据清洗与分析策略
Section titled “数据清洗与分析策略”- 数据清洗原则:
- 始终结合分析目标进行清洗,目标决定了处理缺失值或异常值的具体策略(如:删除无效行 vs. 填充数据)。
- 结构化问题(如列名、数据格式)应优先于内容质量问题进行处理。
- 逻辑转换:数据清洗不仅仅是技术操作,更是将原始数据转换为“整洁数据 (Tidy Data)”以支持后续分析的逻辑过程。
项目数据处理流程
Section titled “项目数据处理流程”- 核心变量:作品所属流派、演员、演员参演作品的 IMB评分。
- 下一步流程:阅读数据每列变量含义 → 读取数据 → 评估数据 → 清理数据 → 整理数据。
- 演示简化:已预先完成读取、评估、清理步骤,避免演示冗长。
- 评估+清洗方式:同步进行(发现问题立即清理),比上个项目分开更省事;具体操作见课程配套文件。
Netflix 数据清洗实战:genres 列拆分
Section titled “Netflix 数据清洗实战:genres 列拆分”- 问题背景:原始数据中的
genres列包含多个流派(如['drama', 'crime']),直接进行分组统计会导致数据混乱,无法精确分析单一流派的特征。 - 清洗思路:
- 目标是让每个流派在各自的行中独立存在,实现“一行一流派”。
- 使用
str.split()将列表字符串拆分,配合apply(pd.Series)将拆分结果扩展为多列,最后通过stack()或类似重塑方法将其转换为长格式。
Netflix 数据清洗实战:credits 表处理
Section titled “Netflix 数据清洗实战:credits 表处理”- 清洗目标:
credits表包含演职人员姓名、角色及作品 ID,通过清理缺失值和格式化,确保后续能与titles表准确关联。 - 操作要点:
- 保持数据结构与原始表相似,但通过清理异常值和格式化列名,提高数据可读性。
- 确保
person_id和id字段的完整性,这是进行表连接(Merge)的关键。
数据分析的逻辑闭环
Section titled “数据分析的逻辑闭环”- 分析与清洗的关联:数据清洗的所有决策(如删除行、填充缺失值)都必须服务于最终的分析目标(计算各流派演员平均 IMDb 评分)。
- 清洗顺序:先确保结构整洁(Tidy Data),再处理内容质量(缺失值、异常值),最后进行统计分析。
Netflix 数据集整理:表连接策略
Section titled “Netflix 数据集整理:表连接策略”- 数据关联需求:
cleaned_titles包含影视作品信息,但缺乏演职员信息。cleaned_credits包含演职员信息,但缺乏作品流派信息。- 必须通过关联两表以实现“流派-演员-评分”的综合分析。
- 连接键 (Key):
- 两表均包含
id变量,该字段代表影视作品的唯一标识,是进行merge操作的连接键。
- 两表均包含
- 连接决策:
- 在进行连接前,必须明确连接方式(
inner,outer,left,right),这取决于分析目标中对数据完整性的要求。 - 决策依据:分析目标决定了连接方式,例如是否需要保留没有演职员信息的作品,或没有对应作品的演职员记录。
- 在进行连接前,必须明确连接方式(
Netflix 数据集表连接实践
Section titled “Netflix 数据集表连接实践”- 连接策略:
- 使用
pd.merge()函数将cleaned_titles和cleaned_credits进行关联。 - 连接键 (Key):使用
id作为共同字段。 - 连接方式 (How):需根据分析目标选择
inner(内连接)、outer(外连接)、left(左连接)或right(右连接)。 - 代码实现:
- 使用
使用 merge 进行内连接
Section titled “使用 merge 进行内连接” credits\_with\_titles = pd.merge(cleaned\_credits, cleaned\_titles, on='id', how='inner')- **连接后的价值**: - 连接后即可获得包含“演员-流派-IMDb评分”的完整数据集。 - 通过 `head()` 方法可以快速预览合并后的结构,确保数据对齐正确,为后续的分组聚合分析(计算平均评分)做好准备。使用 merge() 进行内连接实践
Section titled “使用 merge() 进行内连接实践”- 操作逻辑:通过
pd.merge()函数将cleaned_credits和cleaned_titles两个 DataFrame 进行关联,以整合演职员信息与作品流派及评分数据。 - 连接键 (Key):使用
id作为共同字段,该字段在两表中均代表影视作品的唯一标识。 - 连接方式 (how=‘inner’):
- 决策依据:必须保留两表均存在的记录。若 ID 仅存在于
titles中,则缺失演员信息;若仅存在于credits中,则缺失流派信息。 - 采用内连接 (inner join) 可确保合并后的数据集包含完整的“流派-演员-评分”分析链路。
- 决策依据:必须保留两表均存在的记录。若 ID 仅存在于
- 代码实现:
credits_with_titles = pd.merge(cleaned_credits, cleaned_titles, on='id', how='inner')- 验证:使用
head()查看合并后的 DataFrame,确认数据对齐情况,为后续按流派分组计算演员平均 IMDb 评分做好准备。
使用 query() 筛选特定角色
Section titled “使用 query() 筛选特定角色”- 筛选需求:在合并后的数据集中,
role列包含ACTOR(演员)和DIRECTOR(导演)等多种身份,分析目标仅关注演员,因此需要过滤数据。 - 实现方式:利用
query()方法,直接筛选role == 'ACTOR'的行,并将结果保存为新变量供后续使用。
筛选 role 为 ACTOR 的记录
Section titled “筛选 role 为 ACTOR 的记录”actor_with_titles = credits_with_titles.query(“role == ‘ACTOR’”)
数据分组与聚合分析准备
Section titled “数据分组与聚合分析准备”- 分组逻辑:为了计算各流派中演员的平均 IMDb 评分,需要按“流派”和“演员”进行分组。
- 分组依据:
- 演员姓名(
name或person_id):person_id比姓名更准确,可避免重名带来的统计偏差。 - 影视流派(
genres):已在前期清洗中完成拆分,确保每个流派独立。
- 演员姓名(
- 分析目标:通过分组聚合,找出特定流派中平均评分最高的演员,为选角决策提供数据支持。
使用 groupby() 进行多变量分组聚合
Section titled “使用 groupby() 进行多变量分组聚合”- 分组逻辑:为了计算各流派中演员的平均 IMDb 评分,需要先对流派进行分组,再对演员进行分组。
- 分组键选择:
- 推荐使用
person_id而非name进行分组,因为person_id是唯一标识,能有效避免重名或拼写错误导致的统计偏差。
- 推荐使用
- 代码实现:
按流派和演员ID进行分组
Section titled “按流派和演员ID进行分组”grouped\_data = actor\_with\_titles.groupby(['genres', 'person\_id'])- **聚合分析**: - 分组后,可对 IMDb 评分列调用聚合函数(如 `mean()`)计算平均值。 - 最终目标是识别出每个流派中平均评分最高的演员,为选角决策提供依据。分组聚合计算平均评分
Section titled “分组聚合计算平均评分”- 计算逻辑:在完成按流派 (
genres) 和演员 ID (person_id) 分组后,对imdb_score列调用mean()函数。 - 代码实现:
计算每个流派中每位演员的平均 IMDb 评分
Section titled “计算每个流派中每位演员的平均 IMDb 评分”imdb_score_grouped = grouped_data[‘imdb_score’].mean()
- **结果结构**: - 结果是一个包含多层索引(MultiIndex)的 Series。 - 外层索引为 `genres`,内层索引为 `person_id`。 - 这种结构虽然清晰,但由于索引是层级化的,直接操作可能不如常规 DataFrame 方便。索引重置与数据重塑
Section titled “索引重置与数据重塑”- 问题背景:当前的
imdb_score_grouped是一个带有层级索引的 Series,如果需要将genres和person_id变回普通列以便后续筛选或排序,需要进行索引重置。 - 解决方案:使用
reset_index()方法将索引转换为列。 - 操作示例:
将层级索引重置为普通列,转换回 DataFrame
Section titled “将层级索引重置为普通列,转换回 DataFrame”imdb_score_df = imdb_score_grouped.reset_index()
- **转换意义**:重置索引后,数据变回标准的 DataFrame 格式,每一行代表一个“流派-演员”组合及其对应的平均评分,便于后续直接使用 `sort_values()` 查找特定流派中评分最高的演员。各流派最高分演员查找逻辑
Section titled “各流派最高分演员查找逻辑”-
继续使用现有 DataFrame。
-
目标:查找各流派(如动作片)中 RMDBScore 的最大值。
-
然后回查最高分对应的演员。
-
已知各流派平均最高分,但不知具体演员 → 通过 PACEID 和 RMDBScore 对值,与前 DataFrame 再次连接。
-
聚合注意事项:分组后聚合操作(如
max())会应用于所有列。若包含person_id,会计算max(person_id),但这无意义。 -
正确步骤:
- 仅对
imdb_score求每流派最大值(排除person_id)。 - 用双键连接(
genres+imdb_score)将最大值结果与原详细DataFrame合并,回查对应person_id和演员姓名。
- 仅对
-
连接键:
genres(流派)和imdb_score(最高平均分),确保匹配精确演员。
查找各流派最高分演员的逻辑优化
Section titled “查找各流派最高分演员的逻辑优化”-
分组聚合的陷阱:直接在
groupby后对整个 DataFrame 使用聚合函数(如.max())会导致所有列(包括person_id)都被执行最大值计算,这在逻辑上是无意义的。 -
正确查找路径:
- 提取最大值:仅对
imdb_score列求各流派的最大值(grouped_data['imdb_score'].max()),得到各流派的最高平均分。 - 双键连接回查:将上述结果与包含详细演员信息的 DataFrame 进行
merge,连接键设为['genres', 'imdb_score']。 - 获取目标演员:通过双键匹配,即可准确回溯到该流派最高分所对应的
person_id和演员姓名,避免了错误计算person_id的最大值。
- 提取最大值:仅对
最高分演员姓名关联与排序优化
Section titled “最高分演员姓名关联与排序优化”person_id 提取与去重
Section titled “person_id 提取与去重”- 先提取 person_id(PACEID)。
- 删除重复记录,确保演员ID与名字一一对应。
与最高分数据连接
Section titled “与最高分数据连接”- 将演员ID和名字数据与前面最高分数据连接。
- 连接键:PACEID。
- 结果:获取各流派平均分最高的演员名字。
排序问题与优化
Section titled “排序问题与优化”- 当前结果:不同流派顺序混乱,按演员名字排序,不便一眼看出各流派最高分演员。
- 解决方案:使用 DataFrame.sort_values() 方法,按指定变量排序(如评分)。
- 示例:传入排序变量,查看这张网(表格)。
演员姓名关联实践
Section titled “演员姓名关联实践”- 数据准备:
- 从原始
cleaned_credits中提取person_id和name列。 - 使用
drop_duplicates()去除重复项,确保每个person_id仅对应一个唯一姓名,防止连接后数据冗余。
- 从原始
最终结果整合与排序
Section titled “最终结果整合与排序”- 连接操作:
- 将处理后的演员姓名 DataFrame 与包含各流派最高平均分的 DataFrame 进行
merge。 - 连接键:
person_id。
- 将处理后的演员姓名 DataFrame 与包含各流派最高平均分的 DataFrame 进行
- 排序优化:
- 原始结果默认按演员姓名排序,不便于查看各流派表现。
- 使用
sort_values()方法按评分(或流派)进行排序,使各流派最高分演员一目了然。
实战总结与练习建议
Section titled “实战总结与练习建议”- 实战价值:本次为复杂数据整理实践,接近数据分析,帮助复习连接与分组等技巧。
- 益处:深化数据探索能力,有利于后续分析。
- 下一步:尝试其他感兴趣数据集,进行数据整理练习。
- 社区互动:分享作品,或为同学作品提供建议/反馈,共同进步。
描述统计学介绍
Section titled “描述统计学介绍”- 统计学本质:对数据进行描述(特征概述)和推断。
- 本节重点:描述统计学,后续涉及推断统计。
- 数据分类:
- 分类数据:有限类别,如性别(二元)、狗品种(多种但有限)。
- 数值数据:具体测量值。
数值数据的数学意义
Section titled “数值数据的数学意义”- 数值数据(Numerical Data)不仅表示数值,还可以进行数学运算和统计分析(如求和、平均值)。
- 示例:班级人数、身高、工资。
- 注意:对分类数据(如性别、金牌/银牌/铜牌)进行数学运算往往没有实际意义。
分类数据与数值数据的进一步细分
Section titled “分类数据与数值数据的进一步细分”| 数据类型 | 细分类别 | 特点 |
|---|---|---|
| 分类数据 | 定序数据 (Ordinal) | 有明确的顺序(如:金 > 银 > 铜) |
| 分类数据 | 定类数据 (Nominal) | 无顺序之分(如:狗的品种) |
| 数值数据 | 连续数据 (Continuous) | 没有最小表示单位,两数值间可取无限值(如:头发长度) |
| 数值数据 | 离散数据 (Discrete) | 只能以整数或自然数为单位(如:台数、人数) |
统计学分析维度
Section titled “统计学分析维度”分析的三大核心维度
Section titled “分析的三大核心维度”- 集中趋势 (Central Tendency):观察数据集中在何处,即数据的“中心”位置。
- 离散趋势 (Dispersion/Spread):与集中趋势相反,衡量数据偏离中心的散布情况。
- 分布形状 (Distribution Shape):描述数据分布的对称性、峰值高低等形态特征。
正态分布特性
Section titled “正态分布特性”- 钟型分布:中间高、两头低,左右对称。
- 应用示例:高考分数人数分布,通常呈现中间集中、两端稀少的钟型曲线。
统计分析流程
Section titled “统计分析流程”- 确定分析维度(集中、离散、分布)。
- 计算对应的统计学指标(如平均值、标准差等)。
- 通过可视化图表(如直方图)直观判断分布形态。
集中趋势 (Central Tendency)
Section titled “集中趋势 (Central Tendency)”- 定义:衡量数据集中在何处,即数据的“中心”位置。
- 分析指标:
- 平均数 (Mean):所有数值之和除以数值个数,代表数据的中心位置。容易受极端值(如姚明身高)影响。
- 中位数 (Median):将数据按大小排序后处于中间的数值。若数据个数为偶数,则取中间两个数的平均值。不易受极端值干扰。
- 众数 (Mode):数据中出现次数最多的数值。
中位数的特性
Section titled “中位数的特性”- 位置意义:正好将数据分为两半,一半大于它,一半小于它。
- 鲁棒性:相比平均数,中位数对极端值不敏感,在统计分析中常与平均数结合使用。
离散趋势 (Dispersion/Spread)
Section titled “离散趋势 (Dispersion/Spread)”- 定义:衡量数据偏离中心位置的散布情况,与集中趋势相对。
分布形状 (Distribution Shape)
Section titled “分布形状 (Distribution Shape)”- 定义:描述数据分布的形态特征,如对称性、峰值高低等。
离散趋势 (Dispersion/Spread)指标详解
Section titled “离散趋势 (Dispersion/Spread)指标详解”- 衡量数据偏离中心程度。
- 可用指标:
- 极差:
最大值 - 最小值,表示数据波动范围。 - 方差/标准差:可相互转换,公式更复杂。
- 方差符号:
σ²。 - 标准差符号:
σ。 - 方差 = 标准差的平方,标准差 = 方差的平方根。
- 方差符号:
- 四分位距
- 极差: