谷歌-Python-IT-自动化-一二课笔记-全-
谷歌 Python IT 自动化 一二课笔记(全)
001:专业化介绍 🚀

在本节课中,我们将要学习IT职业发展的重要性,以及学习Python编程和自动化技能如何为你的职业生涯打开新的大门。我们还会概述整个课程的结构,并认识你的讲师团队。
IT职业:不止是一份工作
从事IT工作不仅仅是一份职业。它是一条职业发展路径。
研究表明,IT支持领域是未来职业成长和获得更高薪酬的起点。事实上,哈佛商学院、埃森哲和Burning Glass最近联合进行了一项名为“跨越鸿沟”的研究。研究发现,在当今那些需要培训但不需要正式大学学位的中等技能工作中,IT支持提供了通往成功的清晰路径。
我们在谷歌的IT支持项目中亲眼目睹了这一现象。那些努力自学Python编程的人通常都看到了强劲的职业发展。他们培养了进入IT领域更高级职位的关键技能。通过努力工作和决心磨练这些技能后,他们晋升为更专业的技术支持专家、系统管理员、技术解决方案工程师,甚至是站点可靠性工程师。
所有这些角色的共同点在于,知道如何编写代码来解决问题和实现自动化。
扩展你的技能工具箱
通过将编程技能纳入你的工具箱,你打开了通往系统管理世界的一扇窗,这可以引导你走向更高级的技术岗位。
特别是Python,它正经历着巨大的发展。根据2019年Stack Overflow开发者调查,Python是大多数人最想学习的编程语言,在已掌握者中最受喜爱的语言中排名第二,总体受欢迎程度排名第四。
那么,为什么要通过这个项目来学习Python编程呢?
以下是几个关键原因:
- 面向IT从业者:该项目专为已经身处或渴望进入IT领域的人士设计。你可能正在思考如何提升当前的IT角色,希望朝着大规模管理运维的方向努力;或者你刚刚起步,希望进入IT行业。也许你已经完成了我们在Coursera上的IT支持专业证书课程,或者你已具备同等的IT支持知识,例如处理文件和目录、熟悉网络概念以及了解如何在计算机上安装软件等基本计算技能。无论如何,这个项目都是为你量身定制的。
- 三种实践教学方法:该项目提供了三种动手实践的教学方法来教授编程、Python和自动化:代码块、Jupyter笔记本和Qwiklabs。
- 优秀的讲师团队:我们汇集了一群出色的谷歌员工,他们将在每门课程中担任你的讲师。他们都从IT支持岗位开始职业生涯,然后学习了编程并转向了更技术性的角色,就像我一样。
认识你的讲师
我们迫不及待地想与你分享我们的故事,以及我们如何在日常工作中使用Python。
哦,对了,我可能应该自我介绍一下。我叫Christine Rahtila,是谷歌的一名系统管理员。我将担任本课程的讲师。这个项目完全由谷歌设计和开发,我们甚至在谷歌不同的酷炫空间里拍摄了每门课程。

它将向你介绍Python编程语言,特别关注这门语言如何应用于IT系统支持和行政管理中的任务自动化。
能在这里与你们一起学习,我感到非常兴奋。在我年轻的时候,我甚至不知道IT职业的存在。我参与这个证书项目有很多原因,但我最大的动机之一是希望看到更多女性在这个行业中得到代表。
我记得曾参加过一个系统管理员峰会,那里有数百名男性,而女性系统管理员大约只有三位。自那时以来,情况已经发生了很大变化,但我们仍然可以做很多事情,为IT领域带来新的想法和多样性。这就是为什么我想与尽可能多的人分享我的知识。
我热爱我的工作,也热爱与我共事的人,因为他们让我很容易寻求帮助并获得指导。这种支持网络让我们的团队,乃至整个行业,能够取得更大的成功。
根据我的经验,我理解学习一门编程语言可能会让人感到相当畏惧,甚至有点害怕。请记住,每个人都曾站在你现在的位置,从第一个命令、第一个脚本开始,当然,还有众多错误中的第一个。当我开始我的职业生涯时,我力求第一次尝试就把每件事都做得完美无缺,但这实际上减慢了我的进步速度。所以,不要害怕犯错。这会让你占据优势。
课程内容概览


那么,让我们开始吧。接下来会有什么内容?
以下是整个项目的课程路线图:
- Python速成课:项目从Python速成课开始,你将学习编写简单程序,并理解它们在自动化中的作用。
- Python与操作系统交互:接下来,我们将更深入地动手实践,重点学习Python如何与操作系统交互。
- 使用Git和GitHub:之后,我们将介绍如何使用Git和GitHub来管理你的代码版本。
- 故障排除与调试:然后,我们将重点学习故障排除和调试技术,以发现和解决IT基础设施问题的根本原因。
- 大规模自动化:下一门课程涵盖大规模自动化,你将学习在云中运行的一批物理或虚拟机上部署配置管理。
- 期末项目:最后,我们将把所有知识融会贯通,完成一个旨在解决现实IT环境中可能遇到的任务的期末项目。作为奖励,你可以将项目发布到GitHub上,向雇主、朋友或两者展示你炫酷的新技能。

哇,一口气说了这么多。你感到兴奋吗?
现在,我想快速向你介绍一路上将会遇到的讲师同事们。
- Roger Martinez:嗨,我叫Roger Martinez。我是一名Linux系统管理员,我将在关于使用Python与操作系统交互的课程中担任你的讲师。
- Kenny Suleman:嗨,我是Kenny Suleman。我将在关于使用Git和GitHub管理代码版本的课程中担任你的向导。
- Amanda Belllis:大家好,我是Amanda Belllis,我将教你关于故障排除和调试的知识。
- Phlin Vandeville:嘿,我是Phlin Vandeville,在我的课程中,我们将学习使用配置管理和云技术进行大规模自动化。
感谢大家。这个全明星团队聚集在一起,是为了指导你在编程世界中的冒险。你得到了非常好的指导。
好了,我想这就是全部了。让我们准备好学习一些新技能,或许还能在此过程中收获一些欢笑。我们下一个视频见。
002:Python编程与IT自动化 🚀

在本节课中,我们将要学习Python编程的基础知识,以及如何利用编程技能实现IT自动化。通过掌握这些技能,你可以在IT领域获得更多机会,提升工作效率,并推动职业发展。
为什么学习编程? 💡
如果你在IT领域工作,掌握计算机编程技能将为你打开大量机会。能够编写脚本和程序,让计算机执行任务,是一项极其宝贵的工具。这不仅使你的工作更轻松、更高效,还能帮助你在IT职业生涯中更快成长、更进一步。
但如何开始学习像Python这样的编程语言?如何识别何时需要让计算机执行任务?又如何编写程序,让计算机完成你想要它做的事情?学习用Python编写程序可能会让你产生各种情绪:兴奋、期待,以及想要立即投入学习的冲动,同时也可能伴随着恐惧。
你可能会问自己:我真的能学会编程吗?我有这个能力吗?我要告诉你:是的,你绝对可以做到。学习编程可能令人畏惧,但同时也非常有趣和令人兴奋。编程就像生活一样,最有回报的工作通常都带有一些挑战,但最终绝对值得付出努力。
讲师介绍 👩💻
我的名字是克里斯汀·拉菲尔,我是谷歌的一名系统管理员,我将担任本课程的讲师和向导。
系统管理员的角色在不同公司,甚至在同一公司的不同团队中,差异很大。我恰好就职于企业身份与访问管理运营团队,简单来说,我们的职责是确保每个人都能被正确识别,并且在需要时能够访问特定资源。
我最喜欢系统管理员这个角色的地方在于,它的职能非常多样化。我们需要处理大量独特的问题和边缘情况,从调整不同系统到与其他团队协作,我总是在学习新东西,所以很难感到无聊。
自动化的力量 ⚙️
这一切都始于知道如何实现自动化。如果你是一名IT支持专家、系统管理员,或者介于两者之间的角色,掌握如何让计算机为你完成繁重工作,将使你在类似的IT角色中脱颖而出,并让你的工作生活轻松得多。
想一想:你是愿意手动部署100台计算机,还是告诉你的计算机一次性为你完成所有工作?答案显而易见,对吧?拥有编码技能可以帮助你成长为更专业的角色,例如:
- 系统管理员
- 云解决方案工程师
- DevOps专家
- 站点可靠性工程师
- 或者,谁知道呢,甚至可能是Web开发人员或数据分析师。
关键在于,能够编写程序是你IT工具箱中的一项基本工具,越来越多的雇主在招聘时都在寻找具备这些技能的人才。
学习新技能的旅程 🧗
如果你曾经学习过一项新技能,比如演奏乐器、说一门外语、编织或滑板,你就会知道,要精通新事物需要大量的练习。
对我而言,我喜欢学习新语言。我很自豪地说,我会说西班牙语、阿拉伯语、法语,我甚至还会10个俄语单词。我们的世界是由我们所说的词语和语言塑造的。虽然有些词语可能是某种语言所独有的,但你总能找到有助于学习和理解的相似之处。能够连接不同文化之间的点,让我能看到别人可能看不到的东西。
我想说的是,无论是学习法语还是Python,这从来都不容易。你必须从小处着手,学习基础知识,并不断练习直到掌握它们。只有这样,你才能转向更复杂、更令人印象深刻的内容。我将在这里帮助你走完这段旅程,你在后续课程中还会遇到我的同事们。
课程环境与目标 🎯
你可能会好奇,为什么我们在加拿大湖边的小木屋里录制这门课程?事实上,我们是在加利福尼亚州桑尼维尔市谷歌办公室的一个游戏室里。我们为这个项目的每门课程选择了不同主题的办公空间,只是为了增添变化。我觉得我这次选得不错。我应该提醒我的经理,课程结束后我也会经常待在这里,因为它超级舒适。
到本课程结束时,你将能够:
- 理解编程在IT角色中的好处。
- 使用Python编写简单的程序。
- 理解编程的基本构建模块是如何组合在一起的。
- 综合运用所有这些知识来解决一个复杂的编程问题。
没错,在本课程结束时,你将编写一个用Python设计的程序,用于解决一个现实世界的IT问题。这非常令人兴奋,对吧?
学习方法与承诺 📚
我们将从编写计算机程序的基础知识开始。你将通过互动练习和真实世界的例子,获得编程概念的实践经验。你将很快看到计算机如何执行多种任务——你只需要编写代码告诉它们该做什么。
在此过程中,我们将讨论自动化,即让计算机自动完成通常需要我们人类手动完成的任务的过程。
现在,有些内容可能会有点复杂和令人困惑。我承诺会尽我所能让这些课程清晰易懂。但是,如果你在任何时候遇到困难,请随时重新观看视频,尽情练习,并花时间真正理解这些主题。
本课程的目标不是教你关于软件工程的一切知识——天哪,那将是一门非常长的课程。相反,我们将向你介绍一些编程和脚本编写的关键概念,这些概念将使你能够在现实生活中发现自动化的机会。



总结 ✨
在本节课中,我们一起学习了学习Python编程和IT自动化的重要性。我们了解了编程如何为IT职业打开大门,认识了课程的讲师,探讨了自动化的价值,并预览了课程的学习路径和最终目标。
你即将学习一项可以帮助你将职业生涯提升到全新水平的技能。你感到兴奋吗?我很兴奋。那么,让我们开始吧!
003:🚀 开始编程之旅

在本节课中,我们将要学习编程的基本概念,了解什么是编程语言和脚本,并动手编写你的第一个Python脚本。我们会循序渐进地介绍每个知识点,确保你能完全理解。

正如中国古语所说:“千里之行,始于足下。”
今天是一个重要的日子。你迈出了学习用Python编写脚本的第一步。
这个过程有时会有些挑战,但真的,它并不可怕。
我们会放慢节奏,在进入下一个视频之前,确保你充分掌握每一个概念。
什么是编程?
上一节我们开启了学习之旅,本节中我们来看看编程究竟是什么。
在接下来的几个视频中,我们将探索计算机编程的基本概念。
你将了解什么是编程语言,什么是脚本。
除了Python之外,还有哪些其他语言,以及这一切与Python有何关联。
我们还会在你不知不觉中让你开始编码,通过我们准备的一些小型编码练习,让你亲手实践Python。
这包括编写你的第一个Python脚本。
给初学者的建议
在深入学习之前,这里有一些重要的建议。
请始终记住,如果在学习过程中的任何时候感到困惑或迷失,不要惊慌。
你可以根据需要多次观看视频,让概念慢慢消化。此外,你可以在讨论区提问,这是获取额外信息并与其他学习者联系的最佳方式之一。
当我被邀请参与这个项目时,它让我想起了自己刚开始编码的时候。
如果我能给年轻时的自己一条建议,我会告诉她:
代码第一次永远不会成功运行。
说真的,作为一个新手,我曾期望一切都能像魔法一样运行。我以为第一次就遵循规则并做对,就能证明我作为程序员的价值。
但事实并非如此。即使是最顶尖的程序员也不例外。
如果你期望第一次就写出完美的代码,你将会感到失望。
听到了吗,年轻的自己。
尽量不要被细节淹没。
融会贯通只能通过经验获得。所以,最好的学习方法就是直接开始实践。
按自己的节奏学习
每个人都有自己的学习节奏。
如果你已经了解其中一些概念,可以自由跳过,直接进入你最感兴趣的部分。
如果你是从零开始,请为每个概念留出足够的时间。评估测试会在你完成后等着你。
如果在任何时候你开始怀疑自己,请记住,即使是最资深的程序员也曾经想过:“Python?Python是什么?”
好了,我们即将全面了解它,让我们开始吧。
本节总结
本节课中,我们一起学习了编程之旅的起点,了解了编程的基本概念,并获得了开始实践的重要心态建议。记住,实践和耐心是学习编程的关键。
接下来,我们将详细梳理编程到底是什么。
004:什么是编程?🧑💻


在本节课中,我们将要学习编程的基本概念。我们将了解什么是计算机程序,以及编程语言如何像人类语言一样工作。我们还会区分“程序”和“脚本”,并介绍我们将要使用的编程语言——Python。
概述
从根本上说,计算机程序是一份指令清单,它告诉你的计算机要做什么。当你编写程序时,你创建了一份需要逐步执行的“食谱”来完成一项任务。当你的计算机执行程序时,它会读取你写的内容并一字不差地遵循你的指令。
编程语言:语法与语义
上一节我们介绍了程序是指令的集合,本节中我们来看看这些指令是如何被书写的。这份“食谱”是用一种称为编程语言的代码编写的。编程语言实际上与人类口语相似,因为它们也有语法和语义。


如果你已经很久没有上过语法课了,这里快速回顾一下语法和语义的概念。
在人类语言中:
- 语法是句子构成的规则。
- 语义则指的是语句的实际含义。

在英语中,句子通常既有主语(一个人、地方或事物),也有谓语(通常是一个动词,用于说明主语在做什么)。

让我们以句子“Paula loves to program in Python”为例。
- 在这个句子中,“Paula”是主语。
- “loves to program in Python”是谓语。
为了形成一个别人能理解的句子,你需要同时知道构建句子的语法和赋予其意义的语义。
这同样适用于编程语言。在像Python这样的编程语言中:
- 语法是每条指令的书写规则。
- 语义是这些指令产生的效果。

多种编程语言
与口语类似,可供选择的编程语言有很多。每种语言都有自己的历史、特点和应用场景,但它们都共享相同的基本理念。因此,一旦你理解了一种编程语言的基本概念,学习另一种就会容易得多。
最后,计算机总是完全按照被告知的内容执行。所以,当你编写程序时,非常清晰地表达你希望计算机做什么至关重要。学习你所选编程语言的语法和语义将使你能够做到这一点。
程序与脚本
在继续之前,让我们花点时间讨论一下术语。在接下来的视频中,你会多次听到“脚本”这个词。那么,脚本和程序有什么区别呢?
两者之间的界限可能有些模糊。在本课程中,我们将互换使用这两个术语。一般来说,你可以将脚本视为开发周期短、可以快速创建和部署的程序。换句话说,脚本是一种简短、简单且可以非常快速编写的程序。
本课程的重点:Python
在本课程中,我们将专注于一种特定的脚本语言——Python,我们将用它来学习编程的基础知识。我们将学习Python的语法(编写Python程序的规则)以及相关不同部分的语义(或含义)。

在我们开始学习如何编码并让你编写第一个Python脚本之前,让我们更多地谈谈什么是自动化以及它为什么有用。
总结
本节课中我们一起学习了:
- 计算机程序是指导计算机完成任务的指令集合。
- 编程语言像人类语言一样,拥有语法(书写规则)和语义(含义)。
- 存在多种编程语言,但核心概念相通。
- “脚本”通常指简短、开发快速的小型程序。
- 本课程将使用Python语言来学习编程基础和自动化。
005:什么是自动化?🤖
在本节课中,我们将要学习自动化的核心概念。我们将探讨自动化的定义、它的优势与局限性,以及如何判断一个任务是否适合自动化。
概述
自动化是信息技术和现代工作流程中的一个基础概念。它指的是用自动发生的步骤来取代手动操作的过程。虽然我们可能没有意识到,但在日常生活中,我们时刻都在享受自动化带来的便利。
什么是自动化?
自动化是将一个手动步骤替换为自动发生步骤的过程。
例如,交通信号灯能持续调节十字路口的车流。它只在需要维修或维护时才需要人工干预。交通的自动调节意味着人们不必站在十字路口手动指挥车辆停止或通行。相反,人们可以专注于更复杂、更具创造性或更困难的任务,比如专注于你的驾驶方向。
自动化的优势
以下是自动化的几个关键优势:
- 节省时间:自动化的系统可以持续工作,无需休息。
- 减少错误:机器执行重复任务的一致性远高于人类。人类执行同一任务数百次,其一致性永远无法与做同样事情的机器相比。
- 提高一致性:交通灯不会疲倦、无聊,也不会在应该显示红灯时意外显示绿灯。这凸显了自动化的另一个好处:一致性。
- 集中化解决方案与错误:自动化使得解决方案和错误更容易被集中管理和修复。
自动化的局限性
然而,尽管有诸多优势,自动化并非适用于所有情况。
有些任务根本不适合自动化。例如,它们可能需要自动化系统无法提供的创造力或灵活性。或者,对于更复杂或执行频率较低的任务,自动化的投入或成本可能实际上超过其价值。

以理发为例。要用机器自动化剪发的动作需要什么?在设计自动化系统时,需要考虑客户的身高、头型、当前发长和期望发型。我们需要复制训练有素的专业人士的创造力和技能,并进行大量测试以确保客户的安全和理发质量。在这种情况下,自动化的成本和精力并不值得自动理发所能带来的好处,这就是为什么我们没有机器人理发师。
总结

本节课中,我们一起学习了自动化的定义。我们了解到,自动化是一个强大的工具,在正确的时间、正确的地点使用,可以节省时间、减少错误、提高一致性。同时,我们也认识到自动化有其局限性,并非万能解决方案。在本课程及后续课程中,我们将讨论何时应用自动化是合理的,以及具体如何实施。最终,判断何时何地使用自动化,对你而言也将变得“自动化”。
006:让计算机为您工作 🖥️

在本节课中,我们将要学习自动化在IT工作中的重要性,以及如何通过编程让计算机代替我们执行重复性任务。我们将探讨自动化的优势,并通过具体例子理解其实际应用。
在IT领域,我们的很多工作最终都归结为使用计算机执行特定任务。在工作中,您可能需要创建用户账户、配置网络、安装软件、备份现有数据,或者每天执行一系列其他基于计算机的任务。
在我第一份IT工作中,我意识到每天上班时,我都要输入相同的三条命令来验证系统身份。出于安全考虑,这些凭据每天都会按设计超时。因此,我创建了一个脚本,让它每天早上自动为我运行这些命令,从而避免了自己手动输入。
有趣的是,监控异常活动的团队发现了我的这个小发明,并联系我将其删除。
为什么需要自动化?🤔
由计算机执行、需要多次重复且变化不大的任务,非常适合进行自动化。因为当您自动化一项任务时,可以避免人为错误的可能性,并减少执行任务所需的时间。
想象以下场景:您的公司在最近的一次会议上设有一个展位,并收集了大量对了解产品感兴趣的人的电子邮件列表。


您希望向这些人发送每月的电子邮件通讯,但列表中有些人已经订阅了该通讯。那么,如何确保每个人都能收到您的通讯,而不会意外地两次发送给同一个人呢?
您可以手动逐一检查每个电子邮件地址,以确保只将新地址添加到列表中。这听起来既无聊又低效,对吧?确实如此。而且它也更容易出错。您可能会意外地遗漏新邮件,或添加已经存在的邮件,或者因为过程太无聊而在办公桌前睡着。
自动化的解决方案 💡
那么,您可以怎么做呢?您可以让计算机为您完成这项工作。



您可以编写一个程序来检查重复项,然后将每个新电子邮件添加到列表中。无论列表中有多少电子邮件,您的计算机都会严格按照指示执行。因此,它不会感到疲倦,也不会犯任何错误。


更好的是,一旦您编写了程序,将来在类似情况下就可以使用相同的代码,从而节省更多时间。这很酷,对吧?
自动化的进阶优势 🚀
事情还可以变得更好。想想您何时发送这些电子邮件。如果您手动发送,您必须向每个人发送相同的电子邮件。个性化电子邮件将需要大量的手动工作。
相反,如果您使用自动化来发送,您可以让每个人的姓名和公司自动添加到电子邮件中。结果是,电子邮件更有效,而您无需花费数小时在文本中插入姓名。

自动化任务可以让您专注于更能有效利用时间的项目,让计算机为您处理枯燥的工作。学习如何编程是实现这一目标的第一步。如果您想让计算机为您工作,那么您来对地方了。
一个自动化实例分享 📂
在本视频开头,我告诉您我自动化的第一个任务。现在,我想告诉您我自动化过的最酷的事情。
那是一个脚本,它更改了大量Google内部服务的访问权限。该脚本遍历了一个包含大量不同文件的大型目录树,检查文件内容,然后根据我在脚本中设定的条件更新服务的权限。
好吧,我承认,我是个书呆子,但我仍然认为这真的很酷。
分享您的想法 💬
接下来,是时候分享您的想法了。您希望使用编程自动化哪些事情?
虽然这些讨论提示是可选的,但它们真的很有趣。说真的,它们让您能稍微了解其他学习者,并在想法和见解上进行协作。请务必阅读其他人的发言,他们可能会给您带来您从未想过的点子。

在那之后,您就可以准备参加本课程的第一次测验了。别担心,这只是练习。

本节总结 📝
本节课中,我们一起学习了自动化在IT工作中的核心价值。我们了解到,自动化能够高效、准确地处理重复性任务,避免人为错误,并释放我们的时间以专注于更有价值的项目。通过编程,我们可以教会计算机执行这些任务,从简单的命令脚本到复杂的文件处理系统。现在,您已经准备好思考如何将自动化应用到自己的工作中了。
007:什么是Python?🐍

在本节课中,我们将要学习Python编程语言的基本概念,了解为什么选择它作为本课程的教学语言,并初步体验如何运行Python代码。
欢迎回来。你在第一次测验中表现如何?如果答对了大部分问题,做得很好。如果没有,不用担心。这是学习过程的一部分。我们会通过这类定期测验来帮助你真正理解这些概念。
如果你觉得某个问题棘手,可以返回复习视频,然后重新尝试测验。在进入下一课之前,你需要对所学内容感到非常熟悉。记住,慢慢来。当你准备好继续时,我随时在这里。
感觉不错?很好,让我们开始吧。
在本课程中,我们将使用Python编程语言来演示基本的编程概念,以及如何将它们应用于编写脚本。我们之前提到过,市面上有很多编程语言。那么为什么选择Python呢?
我们选择Python有几个原因。首先,用Python编程的感觉通常类似于使用人类语言。这是因为Python让我们能够用易于阅读和书写的语法,轻松地表达我们想做的事情。
请看这个例子:
friends = ['Taylor', 'Alex', 'Pat', 'Eli']
for friend in friends:
print("Hi " + friend)
这里有很多内容需要理解。所以,如果你不能立刻明白,请不要担心。我们将在课程后面深入细节。但即使你以前从未见过一行代码,你或许也能猜出这段代码的作用。它定义了一个包含朋友名字的列表,然后为列表中的每个名字创建一句问候。

现在,轮到你与Python交朋友了。尝试运行它,看看会发生什么。
在整个课程中,你将使用网页浏览器来执行Python代码。我们将从使用代码块进行一些小型的编码练习开始,就像你刚才实验的那个一样。之后,随着你技能的发展,你将使用其他工具来处理更大、更复杂的编码练习。
精通某事需要大量的练习,编程和Python也不例外。我们建议你亲自练习本课程中分享的每一个例子。
如果你的电脑上没有安装Python,不用担心。你仍然可以使用在线的Python解释器进行练习。请查看下一份阅读材料,获取最流行的在线Python解释器的链接。
现在,我确信你很好奇,到底什么是Python解释器?在编程中,解释器是读取和执行代码的程序。还记得我们把计算机程序比作包含分步说明的食谱吗?那么,如果你的食谱是用Python写的,Python解释器就是那个读取食谱内容并将其翻译成你的计算机可以遵循的指令的程序。

最终,你会希望在电脑上安装Python,以便在本地运行它并随心所欲地进行实验。我们将在接下来的课程中指导你如何安装Python,但你不必为了初次体验Python而安装它。
你可以通过我们提供的测验以及下一份阅读材料中给出的在线解释器和代码编辑器链接进行练习。我们会为你提供大量练习,但也欢迎你提出自己的想法,并在讨论论坛中分享。尽情发挥创意吧,这是你展示新技能的机会。
总结
本节课中,我们一起学习了选择Python作为学习语言的原因,包括其语法接近人类语言、易于读写。我们初步接触了Python代码的结构,并了解了解释器(如python命令)是执行代码的关键程序。我们还明确了本课程将通过浏览器和在线工具提供实践机会,鼓励大家积极练习和创造。
008:Python与IT的相关性 🐍


在本节课中,我们将探讨Python编程语言为何在当今IT行业中如此重要。我们将了解Python的特点、其发展历程,以及它如何成为自动化、系统管理乃至新兴技术领域的关键工具。
Python的简洁性与可读性
上一节我们提到了Python的广泛应用,本节中我们来看看它为何如此受欢迎。Python的语法简单易读,这使得表达编程的基本概念(如数据结构和算法)变得非常直观。
示例代码:
# 一个简单的Python列表和循环示例
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
这种可读性使Python成为学习编程的理想语言。
Python的发展历程与版本
Python并非一门新语言。它由Guido van Rossum创建,并于1991年首次发布。自那时起,其开发社区不断壮大,语言本身也取得了长足进步。
每当语言语义或语法发生重大变化时,就会发布新的主要版本。
- 2000年:发布了Python 2。
- 2008年:发布了Python 3。
本课程将使用2018年发布的Python 3.7。多年来,Python曾被视为初学者语言,主要用于教学概念或编写小型简单脚本。但近年来,Python的采用率急剧上升。
Python在IT行业的广泛应用
Python日益普及的原因之一是语言本身变得更加强大,另一个原因是Python为不断增长的应用领域提供了更多工具。
以下是Python的一些常见用途:
- 执行统计分析。
- 运行动态网站。
- 处理图像。
- 与Web服务交互。
Python非常适合自动化。它允许您编写易于理解和维护的简单脚本来自动执行日常任务。这就是为什么Python成为许多从事IT支持、系统管理和Web开发人员的首选语言。
不仅如此,Python还应用于IT快速发展的领域,如机器学习和数据分析。最后,Python可以在多种操作系统上使用,例如Windows、Linux和macOS。
学习编程:寻求帮助与利用资源
编程学习很大程度上是通过试错和提问来完成的。因此,如果您在任何时候遇到困难,请不要气馁。犯错可以帮助您进步。
您越是将失败或错误的代码视为学习的机会,您掌握编程的速度就越快。请记住,即使是有经验的程序员有时也需要向同事请教或在互联网上查找资料。
最好的程序员通过寻求帮助或利用其他资源来克服挑战。完成本课程后,您将能够自信地使用Python进行基础编程。
持续学习的可用资源
网络上有大量信息可以帮助您持续提升编程技能。以下是一些有用的资源:
- 官方Python文档:可以找到Python编码问题的答案。
- Stack Overflow等网站:可以与其他开发者讨论和分享。
- 课程讨论区:可以在此提问。
- Python邮件列表:可以订阅以了解语言的最新动态。
您正在打开通往整个编程世界的大门。加入开发社区是一件非常令人兴奋的事情。最重要的是要记住,您永远不会孤单。在职业生涯中的任何时候遇到任何问题,都有资源可以帮助您找到所需的答案。
本节课中我们一起学习了Python在IT领域的重要性、其发展历史以及广泛的应用场景。我们还强调了在学习过程中勇于试错和积极利用社区资源的重要性。现在,您已经为开始实际编写Python脚本奠定了坚实的基础。
009:编程语言概览 🌐

在本节课中,我们将要学习编程语言的基本概念,了解Python在众多语言中的位置,并初步探索不同语言之间的异同。
虽然我们为本课程选择了Python,但必须指出,它只是众多编程语言中的一种。
你可以将一门特定的编程语言视为你IT工具箱中众多强大工具之一。
每种语言都有其独特的优缺点。有些语言运行速度更快。有些语言更适合企业级应用。另一些则在处理数字计算方面特别出色。
以下是几种不同类型的编程语言:
- 平台特定脚本语言:例如在Windows上使用的PowerShell和在Linux上使用的Bash。这两种语言在各自平台上被系统管理员广泛使用。
- 通用脚本语言:与Python类似的语言,例如Perl或Ruby。它们也广泛用于脚本编写和自动化。
- JavaScript:最初是作为一种Web客户端脚本语言开发的,现在越来越多地被用作服务器端语言,以完成更广泛的任务。
- 传统语言:除此之外,还有大量传统的编程语言可供探索,如C、C++、Java或Go。
随着你在IT领域的职业发展,你可能会遇到许多不同的语言,并学会在何时使用它们。但让我们不要操之过急。首先,我们需要掌握Python。
上一节我们介绍了编程语言的多样性,本节中我们来看看学习一门语言带来的好处。
学习一门语言编程基础的一个优点是,你通常可以将学到的相同概念应用到其他语言中。这意味着一旦你熟悉了Python,你会发现学习新的编程语言会更容易,因为你将能识别和理解它们之间的相似性与差异性。
毕竟,每种语言都需要做一些共同的事情,例如创建变量、控制程序流程、读取输入和显示输出。即使它们使用不同的方法来完成这些任务。
正如我们之前提到的,学习编程语言有点类似于学习一门外语。你需要掌握该语言的语法。幸运的是,一旦你掌握了编程的基础知识,学习另一门语言比学习第二门外语要容易得多。编程语言之间的相似性远多于差异性。
为了探索各种脚本语言之间的一些相似性和差异性,让我们来看一个简单的程序,它用三种不同的语言(Python、Bash和PowerShell)打印“hello world”十次。
# Python 示例
for i in range(10):
print("hello world")
# Bash 示例
for i in {1..10}; do
echo "hello world"
done
# PowerShell 示例
for ($i=1; $i -le 10; $i++) {
Write-Host "hello world"
}
如你所见,每种语言都使用不同的方法来打印“hello world”。但仔细观察,你也会发现相似之处。
每种语言都必须以某种方式将文本输出到屏幕。Python的命令是print,Bash是echo,而PowerShell是Write-Host。
同时注意,每种语言都必须以某种方式计数到10。Python通过指定range(10)来实现,Bash使用序列符号从1计数到10。PowerShell在这个例子中语法最复杂,但它本质上也是从1开始计数到10。

所以,正如我们刚刚看到的,世界上有非常多的编程语言,但不要被此吓倒。在本课程中,你只需要专注于学习Python。一旦你掌握了Python,你就可以继续学习任何其他你想学的语言。
本节课中我们一起学习了编程语言的多样性、学习第一门语言的价值,以及通过一个简单的“hello world”示例对比了不同脚本语言的异同。接下来,我们将通过一个小测验来帮助你巩固刚刚学到的知识。
010:你好,世界!👋

在本节课中,我们将学习如何编写并运行你的第一行Python代码,并理解其背后的基本概念。
现在你已经对Python代码有了初步印象,让我们来查看一个最基础的例子,并深入探究其背后的原理。我们将使用Python解释器,让我们的计算机向世界问好。
打印“Hello World” ✨
当我们运行以下代码时,无论是在本地计算机上还是在网页解释器中,屏幕上都会出现“Hello World”的字样。
print("Hello World")
这看似神奇,实则不然。这是因为 print 是一个Python函数,它的作用是将我们告诉它的内容输出到屏幕上。例如,语句“Hello World”。print 函数是Python基础语言的一部分。

理解语法:函数与关键字 🔑

每当我们使用属于该语言的关键字或函数时,我们就是在使用编程语言的语法来告诉计算机该做什么。
那么,什么是函数和关键字呢?
以下是关于它们的基本解释:
- 函数:是执行一个单元工作的代码片段。我们将在后续课程中详细讨论函数,你甚至会学习如何编写自己的函数。
- 关键字:是用于构建指令的保留字。这些词是语言的核心部分,只能以特定的方式使用。一些例子包括
if、while和for。我们将在课程后面解释这些以及更多关键字。
正如我们提到的,Python中使用的关键字和函数构成了该语言的语法。一旦我们理解了它们的工作原理,就可以用它们来构建更复杂的表达式,让计算机执行我们想要的操作。
字符串的概念 📝
最后,请注意“Hello World”是如何写在双引号之间的。用引号包裹文本表示该文本被视为一个字符串,这意味着它是将被我们脚本处理的文本。在编程中,任何不在引号内的文本都被视为代码的一部分。
历史趣闻与总结 📚
现在,分享一个有趣的小知识。你知道为什么在我们的例子中要向整个世界问好吗?打印“Hello World”自20世纪70年代以来一直是学习编程语言的传统起点,当时它被用作著名编程书籍《C程序设计语言》的第一个例子。那个例子看起来像这样:
#include <stdio.h>
main() {
printf("hello, world\n");
}
在Python中,“Hello World”示例只有一行。在C语言中,它是三行。在其他语言中,可能更多。虽然学习编写“Hello World”不会教会你整个语言,但它能让你对函数的使用方式以及用该语言编写的程序的外观有一个初步印象。
好了,既然我们已经编写了第一段Python代码,我认为你已经准备好迎接比“Hello World”更具挑战性的内容了。让我们继续前进吧!😊

本节课总结:我们一起学习了如何用 print 函数输出“Hello World”,理解了函数和关键字是构成Python语法的基本元素,并认识了用引号定义的字符串。这是你Python编程之旅的第一步。
011:从用户获取信息 📥

在本节课中,我们将要学习如何让Python程序从用户那里获取信息,从而使程序能够执行更具体、更有用的操作,而不仅仅是输出固定的内容。
概述
一个有用的程序通常需要从用户那里获取至少一些信息。利用这些数据,程序可以执行与用户相关的操作,而不是像打印“Hello world”这样的通用操作。数据可以通过多种方式提供给计算机。
上一节我们介绍了程序的基本结构,本节中我们来看看如何让程序接收外部输入。
数据输入的方式
数据可以通过多种不同的平台和方式输入。
以下是几种常见的数据输入方式:
- 在网站上,您可以通过在文本字段中输入文本或点击链接来输入数据。
- 如果您使用移动应用程序,可能会点击按钮或从下拉菜单中选择偏好设置。
- 在命令行程序中,您可以通过将字符串作为参数传递给程序来提供额外数据,或者让程序以交互方式向您请求数据。
所有这些不同的平台、程序和应用程序处理数据的方式各不相同。有些程序可能将文件内容作为要处理的数据,而另一些程序则从其他来源收集数据并在后台进行处理。
课程中的数据处理方式
在本课程最初的示例中,我们将直接在代码块中把数据写成单独的一行。这种方式虽然有限,但简单直接。在本课程后期以及后续课程中,我们将向您介绍更好的方法将数据输入到代码中。

现在,让我们通过一个非常简单的例子来看看这个想法是如何实现的。
一个简单的示例
假设我们想向一个名叫“小明”的人问好。我们可以这样写代码:
name = "小明"
print("你好," + name)
通过将姓名与调用print函数的代码分开,我们使得调用print函数的那行代码变得通用,同时仍然能个性化问候语。如果我们想向不同的人问好,只需要更改name变量的值,而调用print函数的代码保持不变。
这很简单,对吧?
总结

本节课中我们一起学习了程序获取用户信息的重要性,并了解了数据输入的多种方式。我们通过一个简单的Python示例,看到了如何通过变量将数据与程序逻辑分离,从而使代码更加灵活和可重用。
接下来,我们将学习其他一些可以让Python为您完成的简单任务。
012:用Python作为计算器 🧮

在本节课中,我们将学习如何使用Python执行基础数学运算。Python不仅可以处理复杂任务,还能作为一个强大的计算器,帮助我们快速准确地进行各种计算。
概述
Python具备强大的数学运算能力。在深入学习复杂主题前,我们先通过一个简单任务来熟悉它:将Python当作计算器使用。这有助于我们理解Python处理数字和运算的基本方式。
基础运算
让我们从简单的数学运算开始。Python可以执行加、减、乘、除等基础运算。
以下是几个基础运算示例:
4 + 5的结果是9。9 * 7的结果是63。-1 / 4的结果是-0.25。
处理小数和循环小数
在进行除法时,Python会精确地显示结果,包括小数。对于无限循环小数,Python会以包含多位小数的格式进行表示。
例如,计算 1 / 3:
在数学中,1除以3的结果是小数点后3无限循环。Python无法显示无限长的数字,因此它会展示一个包含许多小数位的近似值。
复杂表达式与运算顺序
上一节我们介绍了基础运算,本节中我们来看看如何计算更复杂的表达式。要计算复合算式,我们需要像在普通数学中一样使用括号 () 来明确运算顺序。

例如,计算 (2050 / 5 - 32) / 9:
我们需要先用括号确保先进行除法和减法,再进行第二次除法。
乘方运算
除了四则运算,Python还能轻松计算乘方(幂运算),例如平方、立方或任意次方。
要计算一个数的乘方,我们使用双星号 ** 运算符。
以下是乘方运算示例:
- 计算2的10次方,代码为
2 ** 10。
为何使用Python计算?
如果你开始疑惑,为何要用Python而不是普通计算器?这是一个合理的问题。通过这种方式进行实验,你能熟悉语言的数学能力。在IT工作中,许多任务都需要数学计算。
你可能需要统计某个词在文本中出现的次数、计算操作完成的平均时间,或者计算需要将图像压缩多少才能符合特定大小限制。无论你需要计算什么,编写脚本都能帮助你更快、更准确地完成。因此,你需要了解有哪些数学运算可供使用。
进阶能力简介
Python实际上拥有更多用于数据分析、统计学、机器学习和其他科学应用的高级数值计算能力。本课程不会深入这些内容,但如果你想自行了解更多,网上有丰富的资源可供查阅。
总结
本节课中我们一起学习了如何将Python用作计算器。我们涵盖了基础运算、处理小数、使用括号控制复杂表达式的运算顺序,以及使用 ** 运算符进行乘方计算。掌握这些基础数学运算是利用Python自动化处理任务的重要第一步。
接下来,将有一份速查表来帮助你回顾刚学到的编程概念。之后,是另一个小测验,这次包含一些简单的编码练习。记住,如果有任何不清楚的地方,你可以根据需要多次回看视频。
准备好了吗?你可以的。
013:代码编辑器与IDE概览 🛠️

在本节课中,我们将要学习代码编辑器和集成开发环境(IDE)的基础知识。它们是帮助您更高效地编写、调试和运行Python代码的重要工具。
上一节我们介绍了一些Python编码基础,本节中我们来看看能辅助您进行开发的编码工具。
什么是代码编辑器?
代码编辑器是用于编写代码的工具。使用代码编辑器,您可以编写、调试和执行Python程序。
代码编辑器提供多种功能,包括:
- 语法高亮:用不同颜色显示代码的不同部分,使其更易读。
- 自动缩进:自动调整代码的缩进,这对Python这类依赖缩进的语言至关重要。
- 错误检查:实时提示代码中的潜在错误。
- 自动补全:在您输入时,智能地建议和补全代码。
总体而言,代码编辑器帮助定义代码的结构和功能,让您能更高效地编写代码。它们也使理解变量、命令、函数和循环变得更加容易。
以下是几个我们将在后续视频中介绍的代码编辑器示例:
- VS Code
- Jupyter Notebook
- Colab
什么是集成开发环境(IDE)?
IDE的功能比代码编辑器更丰富。代码编辑器与IDE的区别在于,代码编辑器更像一个文本编辑器,而IDE则能指导您编写代码,并允许您查看代码的执行过程。
您可以这样理解:代码编辑器就像一部固定电话,您可以拨号、打电话。而IDE更像一部智能手机,您仍然可以打电话,但它还拥有额外的功能,允许您进行视频通话、发送短信、浏览互联网和使用许多其他应用程序。
IDE是一个软件工具,它简化了创建新软件应用程序的过程。它是一个提供软件开发综合设施的软件应用程序。

代码编辑器与IDE的关系
IDE始终包含一个代码编辑器。IDE通过将多种工具集成到一个环境中,让您能更高效地开发代码。您将能够在一个应用程序中完成编辑、构建、测试和打包所有工作。它们还允许您更快地编程应用程序,而无需进行手动集成和配置。
接下来,我们将介绍IDLE。IDLE是一个随Python自动安装的IDE。它是一个优秀的初学者级IDE,因为它非常易于使用。对于大型项目它可能不太理想,但对于了解如何使用IDE来说,它非常出色。
现在,让我们深入了解一些您可以在Python学习之旅中使用的代码编辑器和IDE。
本节课中我们一起学习了代码编辑器和集成开发环境(IDE)的基本概念。我们了解到,代码编辑器是专注于编写和调试代码的工具,而IDE则是一个功能更全面的开发环境,集成了编码、测试、调试等多种功能。选择合适的工具将极大地提升您的编程效率和体验。
014:🚀 使用命令行与IDLE编写Python脚本

在本节课中,我们将学习如何通过命令行和Python自带的IDLE工具来编写和运行Python脚本。这是开始Python编程的第一步。
概述
命令行是直接与计算机操作系统交互的强大工具。通过它,我们可以执行各种任务,例如访问服务器、移动文件、切换目录,以及运行脚本。本节将重点介绍如何在Linux操作系统上使用命令行和IDLE来编写Python代码。如果你使用其他操作系统,原理是相似的,可以参考相关文档进行调整。
使用命令行
上一节我们介绍了命令行的重要性,本节中我们来看看如何在Linux上实际操作。
首先,你需要打开Linux终端。可以通过点击应用程序图标或使用快捷键 Ctrl + Alt + T 来实现。
打开终端后,你可以检查系统是否已安装Python。在终端中输入以下命令:
python3 --version
大多数Linux系统都预装了Python。如果系统提示命令未找到,则表示需要安装。你可以使用以下命令进行安装:
sudo apt install python3
系统会提示你输入密码。输入密码并按回车后,Python 3将开始安装。
安装完成后,你就可以在终端中直接进入Python的交互模式了。只需输入:
python3
以下是交互模式的一个简单示例。输入以下代码并按回车:
print("Hello, world!")
你将看到终端输出:Hello, world!。
要退出Python交互模式,请输入:
exit()
使用IDLE编写脚本
除了命令行交互模式,我们还可以使用IDLE来编写更复杂的Python脚本文件。IDLE是Python官方提供的集成开发与学习环境,特别适合初学者。
IDLE提供了语法高亮、代码自动补全和自动缩进等功能,能帮助你更轻松地编写代码。
在Linux上,如果尚未安装IDLE,可以使用以下命令安装:

sudo apt install idle3
安装完成后,在终端中输入 idle3 即可启动IDLE。

启动IDLE后,你会看到一个交互式解释器窗口。要创建新的脚本文件,请点击菜单栏的 File -> New File。
在新打开的编辑器窗口中,你可以编写Python代码。例如,编写一个简单的加法程序:
# 这是一个简单的加法脚本
num1 = 5
num2 = 3
sum = num1 + num2
print(f"两数之和为: {sum}")
代码编写完成后,需要保存文件。点击 File -> Save As...,为文件命名,例如 sum.py,然后点击保存。

要运行这个脚本,你有两种选择:
- 在编辑器窗口中,点击
Run->Run Module。 - 或者直接按键盘上的
F5键。
运行后,你将在IDLE的交互式窗口或终端中看到脚本的输出结果。
总结
本节课中我们一起学习了Python编程的起点工具。我们掌握了如何在Linux命令行中检查、安装Python,并使用 python3 命令进入交互模式执行简单的代码。接着,我们介绍了功能更强大的IDLE工具,学习了如何安装、启动IDLE,并完成了一个从编写、保存到运行完整Python脚本的流程。
记住,无论你使用哪种操作系统,都可以通过命令行来运行Python。对于执行和调试单个脚本或 .py 文件,使用IDLE这类文本编辑器并从命令行运行是非常有效的方法。
接下来,让我们探索一些其他代码编辑器和集成开发环境(IDE)。我们下个视频再见。
015:使用 JupyterLab 与 Jupyter Notebooks 📓

在本节课中,我们将学习如何使用 JupyterLab 和 Jupyter Notebooks 来编写、运行和调试 Python 代码。这是一种非常流行的交互式编程环境,尤其适合数据分析和学习。
概述:什么是 JupyterLab 与 Jupyter Notebooks?
JupyterLab 和 Jupyter Notebooks 是一个名为 Project Jupyter 的开源项目的一部分,可以免费使用。你可以在 jupyter.org 了解更多信息。
JupyterLab 是一个基于网页的界面,允许你使用 Jupyter Notebooks 来编写、运行和调试 Python 代码。它提供了一个在线环境,让你可以在云端运行代码。
Jupyter Notebook 则是一种可以创建包含实时代码块的文本文档的工具。你可以在一个地方编写 Python 程序并查看其执行结果,这对于理解和创建代码非常有帮助。
如何使用基于云的 JupyterLab 环境?
最流行的使用方式之一是通过基于云的环境。以下是具体步骤:
- 访问 jupyter.org。
- 点击 “Try” 按钮。
- 在弹出的选项中选择 “JupyterLab”。
进入 JupyterLab 环境后,你可以创建一个新的 Notebook:
- 点击 “+” 号添加新标签页。
- 在 “Notebook” 分类下选择 “Python”。
- 一个新的 Notebook 就会打开,你可以开始编写和运行 Python 代码了。
在 Notebook 中编写并运行代码
你将在带有蓝色边框的 单元格 中编写代码。让我们尝试一个简单的例子。
以下是一个打印语句的示例:
print("Hello world")
要运行单元格中的代码,请使用工具栏顶部的 “运行” 按钮。点击后,你的单元格就会执行,输出结果会显示在单元格下方。对于上面的代码,输出应该是:
Hello world
保存与下载你的 Notebook
你可以使用工具栏顶部的 “保存” 按钮来保存你的 Jupyter Notebook。点击保存并为你的文件命名,例如 hello.ipynb。

如果你想下载你的 Notebook 文件,可以使用左上角的 “文件” 菜单,然后选择 “下载” 选项。


在本地机器上安装和使用 Jupyter
你也可以在自己的电脑上安装和使用 JupyterLab 和 Jupyter Notebooks。这需要通过命令行使用 pip 命令。
以下是安装和启动 JupyterLab 的步骤:
- 在命令行中输入:
pip install jupyterlab - 安装完成后,输入:
jupyter-lab来启动它。
以下是安装和启动 Jupyter Notebook 的步骤:
- 在命令行中输入:
pip install notebook - 安装完成后,输入:
jupyter notebook来启动它。

总结与更多资源
本节课中,我们一起学习了 JupyterLab 和 Jupyter Notebooks 的基本用法。它们是编写 Python 代码的强大工具。Notebook 文件可以轻松地通过电子邮件、GitHub 或 Jupyter Notebook Viewer 进行分享和保存。
网络上还有大量关于 Jupyter Notebooks 的资源。如果你需要更多支持,Jupyter 官方网站是一个深入学习的绝佳资源。
在下一个视频中,我们将介绍 Colab,这是一个与 Jupyter Notebooks 非常相似的编码工具。请继续观看以了解更多。
016:使用Google Colab 📓

在本节课中,我们将学习如何使用Google Colab。Colab是一个基于网页的平台,允许你在Google Drive中快速编写和运行Python代码。我们将介绍如何开始使用Colab、其核心功能以及如何管理你的项目。
概述
上一节我们介绍了Jupyter Notebooks。本节中,我们来看看Google Colab Notebooks。Colab Notebooks是由Google的Collaboratory托管的Jupyter Notebooks。在Colab中,你可以编写和运行Python代码。本视频将详细介绍如何使用Colab及其功能。
Colab是一个基于网页的平台,允许你在Google Drive中快速编写和运行Python代码。它是免费的,无需任何配置即可使用。你可以直接访问 collab.sandbox.google.com 或搜索“Google Colab”来开始使用。
Colab提供了Python的所有功能。Colab中的单元格可以包含代码、文本和图像。代码单元格包含可执行代码和富文本,这使得编写和运行代码变得非常容易。
Colab还使得在Notebook中包含Markdown变得简单。这是一个分享Notebook的绝佳功能,因为你可以添加标题、段落、列表、数学公式等。
你可以在代码单元格中使用 pip 命令安装Python包。Colab Notebooks也可以轻松地与其他协作者共享。
如何使用Colab
现在,让我们来看看如何使用Colab。
首先,再次打开Google Colab。你可以通过访问 colab.sandbox.google.com 来完成此操作。
转到“文件”菜单,点击“新建笔记本”。现在,你可以开始编写Python代码了。
在代码单元格中,让我们编写一个输出你名字的打印语句。
print("你的名字")
要运行你的代码并查看其执行结果,请使用代码单元格左侧的“运行”按钮。
你也可以给你的编码项目起一个名字。在顶部,你可以将 untitled.ipynb 更改为类似 name.ipynb 的名称。这将使你将来更容易找到你的代码。

Colab的一个优点是它会自动将你的Notebook存储在Google Drive中。
要找到你的Notebook,你可以直接访问你的Google Drive,在搜索栏中输入“Colab notebooks”,然后打开名为“Colab Notebooks”的文件夹。在这里,你将看到你创建的所有Notebook。

总结
本节课中,我们一起学习了如何使用Google Colab。我们了解到Colab是一个便捷的在线Python编程环境,能够自动保存项目到Google Drive,并支持代码执行、Markdown文档编写以及包安装。现在你已经掌握了使用这些代码编辑器的窍门。接下来,让我们进入最后一个编辑器——VS Code的学习。我们下个视频见。
017:使用 VS Code 进行 Python 开发 🛠️

在本节课中,我们将学习如何安装和配置 Visual Studio Code(简称 VS Code),这是一个功能强大的开源代码编辑器,并利用它来编写和运行 Python 代码。
认识 VS Code
上一节我们介绍了几种不同的编码工具,本节中我们来看看 VS Code。
VS Code 是一个包含开发者工具的开源代码编辑器。它类似于 Jupyter Notebooks 和 Colab,但提供了更多功能。VS Code 提供了内置支持,包括智能代码补全、交互式调试器以及其他构建和脚本工具。
VS Code 的布局简洁,易于学习和使用。其直观的特性使其成为 Python 编码的绝佳选择。
安装准备:Python 3
要使用 VS Code 进行 Python 开发,你需要安装 Python 3、VS Code 以及 VS Code 的 Python 扩展。本视频将展示如何完成这些步骤。
VS Code 可以在 Windows、Mac 和 Linux 操作系统上使用。本视频将以 Linux 操作系统为例。如果你使用其他操作系统,我们提供了相关阅读材料供你后续参考。
现在,让我们开始吧。

首先,打开一个终端窗口,输入以下命令来检查 Python 3 是否已安装:
python3 --version

如果 Python 3 已安装,输出将显示你计算机上安装的 Python 版本,例如:
Python 3.10.12
如果未安装,输出将返回 command not found。这意味着你需要先安装 Python 3。
以下是安装步骤:

- 在终端命令行中,输入
sudo apt install python3并按回车。 - 系统会提示你输入密码。输入密码后,安装将开始。
- 在安装过程中,系统可能会询问
Do you want to continue? [Y/n]。选择Y并按回车。
现在,Python 3 已安装完毕并准备就绪。

下载并安装 VS Code
接下来,我们安装 VS Code。

你可以访问 code.visualstudio.com/download 下载 VS Code。我们将下载与 Linux 兼容的版本。
选择 .deb 版本的 VS Code 进行下载。等待下载完成。
然后,回到终端。我们需要导航到下载文件夹并安装软件包。

以下是具体步骤:


- 输入
cd Downloads/进入下载目录。 - 使用
ls命令,这会列出我们刚刚下载的 Debian 文件。你将看到已下载文件的名称。 - 输入
sudo dpkg -i加上列出的文件名,然后按回车执行安装命令。
一旦该命令执行完毕,Visual Studio Code 就安装成功了。
要打开 Visual Studio Code,在命令行输入 code。VS Code 就会为我们打开。

配置 Python 扩展
最后一步是在 VS Code 中设置 Python 环境。
我们需要浏览并安装扩展。在 VS Code 中,按 Ctrl+Shift+X 可以查看扩展。
这会显示 VS Code 市场上最流行的扩展列表。你可以使用搜索栏搜索 “Python”,然后点击 “安装”。
安装完成后,它会提供开始 Python 开发的选项。我们直接选择 “创建 Python 文件”,这将打开代码编辑器。

让我们用一个简单的语句来测试一下。在新的工作区中输入:
print("Hello world")

接下来,点击 “运行” 来执行代码。系统会提示你命名并保存文件。为你的 Python 文件取一个名字,然后点击 “保存”。在这个例子中,我们将文件命名为 helloworld.py。

你的代码将运行,并在此处看到它的输出。
总结与回顾
干得漂亮!现在来总结一下。
VS Code 是一个极其强大的源代码编辑器。它使用智能感知技术,为编码提供语法高亮和自动补全。VS Code 允许你通过其交互式控制台直接在编辑器中进行调试。
总的来说,VS Code 极具交互性和可定制性。它还有一个庞大的扩展库,可以轻松集成。
本节课我们共同学习了如何安装 Python 3、下载并安装 VS Code,以及如何配置 Python 扩展来运行你的第一个程序。内容很多,你可以根据需要多次复习这些视频。

请记住,找出最适合你的工具的最佳方法之一,就是探索它们提供的所有功能并多加练习使用。
018:Python入门与自动化基础 - 初步总结 🎉

在本节课中,我们将回顾并总结第一模块所学的核心概念,涵盖Python编程基础、脚本编写、语法语义以及自动化入门知识。
恭喜你完成了第一模块的学习。你已迈出了学习新编程语言、提升IT技能的第一步。这展现了你的决心与学习意愿。
我们涵盖了许多主题,如果你之前从未接触过编程,其中很多内容可能是全新的。你了解了什么是脚本、编程语言的语法和语义,以及它们如何与自动化相关联。
上一节我们介绍了Python的基础代码块,本节中我们来看看本模块的核心收获总结。
以下是本模块涵盖的主要内容:
- 脚本的概念:理解了脚本作为一系列可执行指令的本质。
- 编程语言的语法与语义:学习了代码的结构规则(语法)和代码的含义(语义)。
- Python与自动化的关联:探讨了Python为何是IT自动化的强大工具。
- 其他编程语言:简要了解了除Python外还有哪些可用的编程语言。
- 数据输入与脚本编写:初次尝试了如何接收输入数据并编写利用这些数据的脚本。
- 数学计算:学习了如何使用Python执行典型的数学运算。
对于Python入门的第一步而言,这些内容相当丰富。这只是学习编程这一激动人心旅程的开始,希望你渴望学习更多知识。

接下来,请准备好迎接你的第一次分级评估。这些评估有助于你检查是否理解了所有概念,并确认已准备好进入下一阶段。
现在,请不要担心。如果在任何时刻你对问题不确定,你随时可以回顾视频和阅读材料来回忆答案。
记住,每个人的学习速度不同。请按照自己的节奏,真正熟悉这些概念。一旦你感觉准备就绪,评估就在那里等着你。等你完成评估后,我们再见。
本节课中我们一起学习了Python编程与自动化的基础,包括脚本、语法语义、数据操作和基础计算。这是你自动化之旅的坚实起点。
019:课程介绍与开发者访谈 🎬

在本节课中,我们将了解《用Python进行IT自动化办公》课程背后的开发者之一,玛格丽塔·莫诺拉。她将分享自己参与课程开发的初衷、过程以及对学习者的期望。
开发者介绍 👩💻
我的名字是玛格丽塔·莫诺拉。我是谷歌Linux团队的一名站点可靠性工程师。
我非常热衷于向所有人教授编程。我认为让每个人都能学会如何告诉计算机该做什么,这一点非常重要。
参与课程的初衷 💡
最初让我对这门课程产生兴趣的一点是,它的目标人群并非来自计算机科学背景。
由于我自己也并非计算机科学背景出身,我对此深感认同。我希望帮助所有这样的人持续成长、持续学习、持续获取越来越多的技能。这就是为什么我也希望这个项目能够成功。
开发过程与合作 🤝
我很早就参与了本课程的开发工作,因为我对能够触及成千上万的学习者、并帮助他们提升技能感到非常兴奋。
与他人合作对这个项目至关重要。我与许多不同的人进行了协作,包括谷歌内部和外部的同事。我收到了来自多方的审阅意见,也获得了新的想法。
我认为这非常重要,因为它让课程脚本变得更好。审阅者们提出了应该添加的新内容,或者指出了不合理之处。我持续将这些想法整合到脚本中,以确保交付的内容尽可能达到最佳。如果只有我一个人,这是不可能完成的。整合多种不同的观点至关重要。
总结与展望 🌟
开发工作虽然繁重,但我非常享受这个过程。看到课程最终成型,令人无比兴奋。
我希望这门课程能帮助人们持续成长,不断拓展视野,从而充分发挥他们的潜力。
在本节课中,我们一起了解了课程开发者玛格丽塔的背景、她参与课程开发的动机,以及团队合作在打造优质学习内容中的重要性。她的经历也鼓励着所有非科班出身的学习者,勇敢地踏上编程与自动化之路。
020:Python基本语法介绍 🐍


在本节课中,我们将要学习Python编程语言的基本语法。我们将探讨变量、表达式、函数和条件语句等核心构建块。理解这些基础概念是编写有效Python代码的关键。
欢迎回来。恭喜你完成了第一次分级评估。
到目前为止,你做得非常出色。我们已涵盖的一些主题有时可能有点棘手,尤其是如果你完全是编程新手。
如果某些内容没有立刻理解,请不要担心。我们介绍了很多新概念,可能需要反复学习几次才能熟练掌握。这完全正常。我们每个人在学习编码时都经历过这个过程。
在之前的模块中,我们探讨了一些基本概念,如编程和自动化。我们提到每种编程语言都有特定的语法,我们需要学习这些语法才能告诉计算机该做什么。
我们随后预览了可以用Python完成的一些事情。
接下来,我们将更深入地探讨Python语法的一些基本构建块,例如变量、表达式、函数和条件语句块。乍一看,这些部分可能看起来相当简单。但当我们开始组合它们时,它们会变得更加强大。
理解编程语言的语法与学习口语没有太大不同。例如,学习西班牙语的最佳方法是访问一个说西班牙语的国家,沉浸在该文化中,倾听人们说话,然后弄清楚如何排列单词以形成另一个说话者能理解的句子。编程也是如此。
当你沉浸在Python编程中时,你将学习如何制定计算机能理解的代码语句。这被称为语法。
好的,在接下来的几个视频中,请记住我们的主要目标是学习语言的语法。因此,我们将专注于如何告诉计算机做什么,而不是如何让它执行复杂的任务。
像之前一样,我们将进行一些简单的练习,帮助你看到这些概念的实际应用。
随着你掌握新技能并熟悉不同的工具,我们将开始编写更高级的脚本来解决更具挑战性的问题。
再次强调,如果在任何时候你感到困惑或觉得某些内容不清楚,请记住,你可以根据需要多次观看视频和进行练习测验。精通编程的关键在于练习、练习、再练习。你必须不断锻炼你的编程“肌肉”才能变得强大,就像在健身房锻炼肌肉一样。努力训练,定期训练,你很快就能处理更复杂的编码问题。
好的,准备好继续学习了吗?在下一个视频中,我们将全面学习数据类型。
让我们开始吧。
本节课中,我们一起学习了Python语法的重要性及其与学习口语的相似之处。我们回顾了之前模块的内容,并预告了接下来将深入学习的核心构建块:变量、表达式、函数和条件语句。掌握这些基础是迈向编写强大Python脚本的第一步。
021:Python数据类型 🧱


在本节课中,我们将要学习Python编程中的核心概念之一:数据类型。我们将了解什么是数据类型,为什么它们很重要,以及如何识别和使用几种最常见的数据类型。
概述
在之前的视频中,我们提到在引号之间书写的文本在Python中被称为字符串。在编程术语中,字符串被称为一种数据类型。
无论是手机游戏还是用于自动创建用户帐户的脚本,大多数程序都需要处理某种数据,而这些数据可以有许多不同的形式,我们称之为数据类型。
什么是数据类型?
字符串只是Python中的一种数据类型。还有很多其他类型,例如:
- 整数:表示没有小数部分的整数,如
1。 - 浮点数:表示实数,即带有小数部分的数字,如
2.5。
通常,你的计算机不知道如何混合不同的数据类型。例如,将两个整数相加对计算机来说完全合理,就像这样:
7 + 8
将两个字符串相加也有意义。我们最终会得到一个包含这两个字符串的更长字符串,就像这样:
"Hello" + "World"
但是你的计算机不知道如何将一个整数和一个字符串相加。如果你让它混合这两种不同的数据类型,你的计算机将不知道该怎么办,并会“引发一个错误”。
处理类型错误
让我们看看会发生什么:
7 + "8"
哦不,我们的第一个错误。但不要惊慌。错误是编程中常见的一部分,你可能需要经常处理它们。诀窍是把错误看作是计算机给你的小提示,帮助你提高编程技能。
仔细阅读错误信息,理解它们告诉你的内容,然后利用这些新知识来帮助你修复错误。在这个例子中,错误信息的最后一行显示我们遇到了一个叫做类型错误的东西。我们得到了一些解释性文本,告诉我们不能在int类型和str类型之间使用加号,int和str分别是整数和字符串的简称。
根据我们已经学到的关于字符串、整数和混合数据类型的知识,你能猜出这个错误试图告诉我们什么吗?
“unsupported operand type”这条信息告诉我们,不能将整数7和字符串"8"相加,因为它们是不同的数据类型。
但如果你没有老师来指出这一点,你怎么会知道呢?你需要运用你的研究技能和我们在课程前面提到的资源来进行一些调查。例如,你可以通过将类型错误信息粘贴到你最喜欢的搜索引擎的搜索栏中来查找有关该错误的信息。这是几乎所有学习编码的人,甚至是有经验的开发人员常用的技巧。你通常会发现互联网上的其他人也报告过类似的错误并解决了它们。
回到我们的例子,也许你在想,我们这里不是在加两个数字吗?看起来有点像,对吧?那么,仔细看,记住在Python中,任何用引号包裹的东西都被视为字符串。所以"8"在这里是一个字符串,而7对计算机来说是一个整数。7加"8"对我们来说就像7加"a"一样奇怪,而7加"a"完全没有意义。
识别数据类型
从它们能代表的信息角度来思考数据类型可能会有所帮助。例如,文件名可以表示为字符串数据类型,而该文件的大小可能是一个整数数据类型。

如果你不能100%确定某个值是什么数据类型,Python提供了一种方便的方法来找出答案。你可以使用type()函数让计算机告诉你类型。在处理别人编写的代码,并且你不确定它使用什么数据类型时,这可能会派上用场。例如:
type("a")
type(2)
type(2.5)
这告诉我们"a"属于str类,正如我们之前所说,它是string的缩写。数字2属于int类,它是integer的缩写。2.5属于float类。我们将在课程后面更多地讨论“类”的含义。现在,你可以直接把它当作数据类型的同义词。
总结
本节课中我们一起学习了Python中三种非常常见的数据类型:字符串、整数和浮点数。很快你还会用到许多其他数据类型,但目前不必担心。随着课程的继续,我们会遇到更多的数据类型,并学习如何与它们中的每一个进行交互。目前,只需记住混合数据类型会让你的计算机……嗯,完全混乱。所以,让你的字符串和字符串在一起,整数和整数在一起,浮点数和浮点数在一起,这样你就不会陷入太多麻烦。
022:表达式、数字与类型转换 🧮

在本节课中,我们将学习Python中不同类型数据之间的运算规则,特别是数字类型(整数和浮点数)的隐式转换,以及如何通过显式转换将数字与字符串结合使用。我们还会回顾字符串拼接的基本操作。
在之前的视频中,我们了解到不能在整数和字符串之间使用加号运算符,因为它们是不同的数据类型。

但如果尝试用整数和浮点数进行运算,会发生什么?让我们来探索一下。
Python可以毫无问题地执行这个操作。
但这是怎么回事?整数和浮点数不是两种不同的数据类型吗?确实是。
但幕后发生了很多事情。在后台,计算机正忙着自动将我们的整数7转换为浮点数7.0。
这使得Python能够将两个值相加,返回一个同样是浮点数的结果。我们称这个过程为隐式转换。解释器自动将一种数据类型转换为另一种。

我们之前提到过这一点,但值得再次强调:Python的运算不仅限于数字。
你也可以使用加号运算符来拼接字符串。这让你能够将单个单词组合成句子。
只是别忘了在每个单词之间添加空格。否则,计算机会将它们全部连在一起。
那么,如果你真的想将一个字符串和一个数字结合起来,可能吗?当然可能。
但这需要通过显式转换来实现。在Python中,要在不同数据类型之间转换,我们需要调用一个以目标类型命名的函数。让我们看看这是如何工作的。
现在,事情变得稍微复杂一些。让我们花点时间来解析一下,确保一切都清晰明了。
在这个脚本中,我们首先计算一个三角形的面积。在打印时,我们将其添加到一个字符串中。为此,我们需要调用str()函数来将数字转换为字符串。
让我们执行它,看看会发生什么。
我们的数字被转换成了字符串,并与消息一起打印了出来。

我们学习了一些关于变量、值、表达式和转换的知识。接下来,有一个练习测验来帮助你巩固所学知识。
像往常一样,如果需要,请花时间复习内容。你完全可以做到。
完成后,我们下一个视频再见。
023:Python函数定义 🧱

在本节课中,我们将要学习Python编程中的一个核心概念:函数。函数是组织代码、实现特定任务的重要工具。我们将从定义函数的基本语法开始,逐步理解其结构和用法。
概述
到目前为止,我们已经学习了变量、表达式和操作,它们是脚本中最小的组成部分。接下来,我们将学习函数,这是另一个关键的编程构建块。
在我们的示例中,我们已经遇到过一些Python内置函数,例如用于在屏幕上输出文本的print函数、用于确定值类型的type函数,以及将数字转换为字符串的str函数。这些函数是语言的一部分。在本课程中,我们将探索更多Python内置函数。
现在,我们将学习如何定义自己的函数,以指示计算机执行语言内置函数所不具备的功能。
定义第一个函数
让我们从一个简单的例子开始。
def greeting(name):
print("Welcome, " + name)
在这段代码中,我们定义了一个函数。该函数接收一个参数name,并为该名字打印一条问候语。
这个代码片段虽然简短,但已经展示了在Python中定义函数的许多重要要点。让我们逐步分析。
要定义一个函数,我们使用def关键字。函数名是关键字之后的部分。在这个例子中,函数名是greeting。因此,在脚本后面调用该函数时,我们将使用greeting这个词。
在函数名之后,我们列出函数的参数,它们写在括号内。在这个例子中,我们只有一个参数name,行末有一个冒号。
冒号之后是函数体,这是我们声明希望函数执行什么操作的地方。请注意函数体是如何向右缩进的。这是Python的一个关键特性,我们会经常遇到。目前,只需记住函数体必须在定义的右侧。
在这个例子中,函数体只包含一行代码,即调用print函数。看起来很简单,对吧?
但创建函数实际上可以非常强大。函数体可以包含任意多行代码,并执行各种有趣的操作。我们将在后续视频中详细探讨。现在,让我们执行我们的函数,看看会发生什么。
greeting("Kay")
输出:
Welcome, Kay
增强函数功能
这很好,但还不够有趣。让我们让它做更多事情。
上一节我们介绍了如何定义一个简单的单参数函数。本节中我们来看看如何定义接收多个参数、执行更复杂操作的函数。
以下是增强版的greeting函数:
def greeting(name, department):
print("Welcome, " + name)
print("You are part of " + department)
我们的函数现在接收两个参数,而不是一个:name和department。它输出两条独立的消息。再次注意缩进。我们可以在函数体中添加任意多行代码,但每一行必须向右缩进相同数量的空格。在这个例子中,我们使用了四个空格。我们也可以使用两个、八个或任何其他数量的空格,只要它们都保持一致。
让我们尝试调用我们新的、增强版的greeting函数。
greeting("Blake", "IT Support")
输出:
Welcome, Blake
You are part of IT Support
这更有用了。我们只是刚刚触及了使用函数所能实现功能的表面。

函数的能力与回顾
请记住,这些只是简单的例子。函数能做的远不止打印消息。在本课程以及接下来的课程中,我们将探索使用Python可以完成的一系列其他任务,并且通常我们会将它们写在函数内部。
到目前为止,你感觉如何?这些新概念来得又快又多。现在,你是否开始掌握这一切了?如果是,那太好了!如果有些内容仍然有些模糊,现在是一个回顾我们迄今为止所涵盖的所有内容的好时机。
一旦你感觉良好,请在下一个视频中与我见面。
总结
本节课中我们一起学习了Python函数的基础知识。我们了解了使用def关键字定义函数的基本语法,包括函数名、参数和函数体。我们看到了如何通过缩进来组织函数体内的代码,并实践了定义和调用接收不同数量参数的函数。函数是封装代码逻辑、提高代码可重用性的强大工具,是我们后续学习的重要基础。
024:Python 函数返回值详解 📤

在本节课中,我们将要学习函数中一个至关重要的概念:返回值。我们将了解如何从函数中获取计算结果,以及如何利用这些值进行更复杂的操作。
概述
我们已经了解了如何通过参数将值传递给函数。但是,如何从函数中获取值呢?这就是返回值发挥作用的地方。函数执行的工作可以产生新的结果。我们可以将这些结果打印到屏幕上,但如果我们想在脚本的后续部分使用这些结果,或者根本不想打印它们,该怎么办呢?我们可以通过从自定义的函数中返回值来实现这一点。
从函数中返回值
让我们回到计算三角形面积的例子。你是否还记得我们之前练习中的三角形示例?三角形的面积计算公式是:面积 = 底 * 高 / 2。想象一下,如果我们需要在代码中多次计算这个值,那么拥有一个能为我们完成此功能的函数将会非常有用。
以下是这个函数的样子:
def area_triangle(base, height):
return base * height / 2
我们使用关键字 return 来告诉 Python,这是函数的返回值。当我们调用函数时,可以将该值存储在一个变量中。
假设我们有两个三角形,并且想计算它们面积的总和。以下是我们的做法:
首先,我们分别计算两个面积。然后,将两个面积相加。最后,打印结果,并将其转换为字符串。
area_a = area_triangle(5, 4)
area_b = area_triangle(7, 3)
sum = area_a + area_b
print("The sum of both areas is: " + str(sum))
在这个例子中,area_triangle 函数返回一个值,即三角形的面积。我们为每次函数调用将该值存储在不同的变量中(本例中是 area_a 和 area_b)。然后,我们使用这些值进行操作,将它们相加到名为 sum 的变量中,并且只打印这个最终结果。
这展示了 return 语句的强大之处。它允许我们将函数调用组合成更复杂的操作,从而使你的代码更具可重用性。
返回多个值
Python 中的返回语句更有趣,因为我们可以用它来返回多个值。假设你有一个以秒为单位的时间长度,你想将其转换为等效的小时、分钟和秒数。
以下是如何在 Python 中实现:
def convert_seconds(seconds):
hours = seconds // 3600
minutes = (seconds - hours * 3600) // 60
remaining_seconds = seconds - hours * 3600 - minutes * 60
return hours, minutes, remaining_seconds
你发现这个函数中的新运算符了吗?那个双斜杠运算符叫做 地板除法。
地板除法将一个数除以另一个数,并取除法结果的整数部分。例如,5 // 2 的结果是 2,而不是 2.5。
在我们的例子中,第一个操作是计算给定秒数中有多少小时。第二个操作则是在减去小时数后,计算剩余多少分钟,以及在减去分钟数后,还剩下多少秒。
我们最终得到三个数字作为结果,因此函数返回所有这三个值。
让我们看看调用这个函数时的样子:
hours, minutes, seconds = convert_seconds(5000)
print(hours, minutes, seconds)
因为我们知道函数返回三个值,所以我们将函数的结果分配给三个不同的变量。
返回“空”值(None)
关于返回值,还有最后一点需要说明:函数可以什么都不返回,这是完全可以的。让我们看一个之前视频中的例子:
def greeting(name):
print("Welcome, " + name)
这个函数只是打印了一条消息,没有返回任何内容。如果我们尝试将这个函数的“值”赋给一个变量,你认为会发生什么?让我们试试看:

result = greeting("Alice")
print(result)

这里,当我们调用函数时,它如预期一样打印了一条消息。我们将返回值存储在 result 变量中,但函数中没有 return 语句。所以 result 的值是 None。
None 是 Python 中一种非常特殊的数据类型,用于表示事物是空的或者它们没有返回任何内容。
总结
本节课中,我们一起学习了关于函数和返回值的丰富知识。我们了解了如何使用 return 语句从函数中获取单个或多个结果,以及如何处理不返回任何内容的函数(其结果为 None)。记住,掌握这些概念的关键是尽可能多地练习编写你刚刚学到的代码。函数和返回值可能是需要掌握的比较棘手的概念,但它们让我们能够做很多很酷的事情。所以,投入时间和精力去学习它,你会获得非常有价值的回报。😊
025:代码重用原则 🧩

在本节课中,我们将要学习如何通过函数来组织和重用代码,从而让脚本更加清晰、高效。
函数的力量
上一节我们介绍了函数的基本概念,本节中我们来看看函数如何帮助我们重用代码。
函数之所以强大,是因为你可以创建自己的函数。你可以使用函数将脚本中的代码组织成逻辑块,这使得你编写的代码更容易使用和重用。
请看以下示例:
name = "Kay"
number = len(name) * 9
print("Hello " + name + ". Your lucky number is " + str(number))
name = "Cameron"
number = len(name) * 9
print("Hello " + name + ". Your lucky number is " + str(number))
这段脚本使用了 len 函数,该函数返回其字符串的长度。在示例中,脚本随后使用该长度计算一个数字,我们称之为幸运数字。最后,它打印一条包含姓名和数字的消息。
每次我们想要执行计算时,都需要更改变量的值、编写公式,然后打印问候语和幸运数字。
注意代码的第一部分和第二部分中有两行完全相同。
识别并消除重复代码
当你在脚本中发现代码重复时,最好检查是否可以通过使用函数来简化代码。
以下是重写后的代码,我们创建了一个函数,将所有重复的代码合并到一行中:
def lucky_number(name):
number = len(name) * 9
print("Hello " + name + ". Your lucky number is " + str(number))
lucky_number("Kay")
lucky_number("Cameron")
更新后的脚本与原始脚本的结果完全相同,但看起来更加简洁。首先,我们定义了一个名为 lucky_number 的函数,该函数执行计算并为我们打印结果。然后我们调用该函数两次,每次使用一个不同的姓名。
由于我们将计算和打印语句分组到一个函数中,我们的代码不仅更易于阅读,而且现在可以重用。我们只需使用不同的姓名调用它,就可以根据需要多次执行 lucky_number 函数中的代码。

因此,我们不必为每个新姓名反复编写相同的代码。
函数的输入与输出
希望这些示例有助于解释函数的使用和定义方式,并展示它们的有用性。
你是否注意到我们通过参数向函数输入信息?这是我们可以向代码输入数据的多种方式之一。这些参数的值可能来自不同的地方,例如计算机上的文件或网站上的表单。但这不会影响我们的代码。无论参数来自何处,函数的结果仍然相同。
函数是你的朋友。它们可以帮助清理你的代码并执行计算,这样你就不必手动操作。在本课程和你的编程生涯中,你将会频繁使用函数。
所以,准备好与函数建立真正的友好关系吧。😊
总结
本节课中我们一起学习了如何通过创建函数来组织和重用代码。我们看到了识别重复代码、将其封装进函数,以及通过参数向函数传递信息的方法。掌握函数的使用将使你的代码更加模块化、易于维护和扩展。
026:Python代码风格指南 🎨

在本节课中,我们将要学习如何编写清晰、易读的Python代码。良好的代码风格不仅能让你的代码更易于理解和维护,还能减少错误,并让你在团队协作中更受欢迎。
概述
到目前为止,我们已经学习了Python语法在变量、表达式以及定义和使用函数方面的应用。虽然还有更多语法知识等待探索,但在深入之前,让我们先谈谈编程的另一个重要方面——代码风格。
从整体上看,代码风格的好坏通常不会直接影响脚本能否成功运行或崩溃。然而,它对于使用和修改代码的人来说,却可能产生巨大的影响。
为什么代码风格很重要?🤔
上一节我们介绍了代码风格的概念,本节中我们来看看它为何如此重要。
糟糕的编程风格会给IT专家或系统管理员带来困难,他们可能需要在脚本编写后阅读它或对其进行修改,以适应新的系统。即使对于脚本的作者本人,如果时隔很久再回头看自己写的代码,糟糕的风格也可能让人头疼。想象一下,因为代码过于混乱而无法理解,不得不重写自己的代码,这无疑是一种糟糕的体验。
相反,良好的风格可以让脚本看起来几乎像自然的人类语言。它能使脚本的意图和结构对读者一目了然。😊
良好的风格让维护代码的人生活更轻松,帮助他们理解代码的功能和实现方式。它还可以减少错误,因为更新代码变得更加容易和直接。最重要的是,良好的风格让你看起来很酷,对吧?所以我们都同意,我们的代码应该是有风格的。
什么是好的代码风格?✨
那么,是什么决定了一段代码风格的好坏呢?虽然没有适用于所有编程语言和情况的硬性规定,但牢记几个原则将大大有助于创建良好、有风格的代码。
以下是几个核心原则:
1. 代码应尽可能自文档化

自文档化代码的编写方式是可读的,并且不隐藏其意图。😊
这个原则可以应用于编写代码的所有方面,从选择变量名到编写清晰、简洁的表达式。以下是一个代码片段示例:
a = 10
b = 5
c = a * b
仅通过查看这段代码,很难确定其目的。变量的名称没有给读者提供太多信息。虽然你可能可以计算出结果,但没有任何线索表明这个结果可能用于什么。
在编程术语中,当我们重写代码使其更具自文档化时,我们称这个过程为重构。
那么,如果我们重构这段代码,它会是什么样子呢?
hours_worked = 10
hourly_rate = 5
total_pay = hours_worked * hourly_rate
通过这段重构后的代码,其意图现在应该更加清晰。变量和函数的名称反映了它们的用途,这有助于读者更快地理解代码。
你应该始终致力于让你的代码自文档化。
2. 适时使用注释
然而,即使如此,有时你可能需要在脚本中使用一段特别复杂的代码。当良好的命名和清晰的组织无法使代码变得清晰时,你可以向代码中添加一些解释性文本。这是通过添加我们称之为注释的内容来实现的。
在Python中,注释由井号(#)字符表示。当你的计算机看到一个井号时,它会理解应该忽略该行中该字符之后的所有内容。

看看这是如何实现的:
# 计算员工总薪酬
hours_worked = 10 # 员工本周工作的小时数
hourly_rate = 5 # 员工的小时工资率
total_pay = hours_worked * hourly_rate # 总薪酬 = 工时 * 时薪
使用注释可以让你解释为什么某个函数以某种特定方式工作。它还允许你给自己或其他程序员留下笔记,提醒你需要改进什么以及为什么。
显然,阅读自己的代码比阅读别人的代码要容易得多。但在我的工作中,我需要处理由许多不同人编写的代码,每个人的设计方式都略有不同。这就是为什么注释和记录你的代码如此重要。
总结与过渡
在本节课中,我们一起学习了良好代码风格的重要性、自文档化代码的原则以及如何使用注释来增强代码的可读性。
更重要的是,你的代码最终很可能会被除你之外的其他人使用。所以,做一个好邻居,使用风格指南来构建你的代码,使其在六个月后当你忘记当初为什么写那段代码时,仍然能被他人或你自己读懂。
在本课程接下来的练习中,我们将使用注释来告诉你需要对代码做什么。你总是可以根据需要编写任意多的额外注释。
现在,来一个小测验,巩固你新获得的关于函数和代码风格的知识。别担心,你能做到的。😊
027:Python中的比较与逻辑运算 🧮

在本节课中,我们将要学习Python中如何比较数值,以及如何使用逻辑运算符连接多个比较条件。这些知识是编写能够做出判断的自动化脚本的基础。
我们已经见过一些算术表达式,例如加法、减法和除法。还记得我们将Python当作计算器使用的时候吗?实际上,Python还可以比较数值。这让我们能够检查一个值是否小于、等于或大于另一个值。通过比较运算,我们可以利用表达式的结果来做出决策。

请看以下三个例子。

以下是三个基本的比较运算示例:
- 在第一个例子中,
10 > 1,因此打印出的结果是True。 - 在第二个例子中,我们使用了由两个等号组成的相等运算符
==,用于测试两个事物是否相等。这里,字符串"cat"不等于"dog",因此打印出布尔值False。 - 在第三个例子中,我们通过组合感叹号和等号
!=进行相反的比较,这是不相等运算符。在这行特定代码中,运算符检查1是否不等于2。
True 是一种属于另一种名为布尔型的数据类型的值。布尔型代表两种可能的状态之一:True(真)或 False(假)。每次在Python中进行比较,结果都是一个相应值的布尔值。
之前我们提到过,加号运算符不能在整数和字符串之间使用。那么,如果我们尝试比较一个整数和一个字符串会发生什么呢?让我们通过检查数字 1 是否小于字符串 "1" 来找出答案。
1 < "1"
我们会得到一个 TypeError(类型错误)。这是因为Python不知道如何检查一个数字是否小于一个字符串。
那么相等运算符呢?在这种情况下,解释器可以毫无问题地告诉我们整数 1 和字符串 "1" 不相同。为什么会这样?本质上,尽管它们在我们看来可能相似,因为它们都包含相同的数字,但对计算机而言,一个数字和一个字符串是清晰不同的。对计算机来说,它们显然是两个完全不同的实体。
除了比较和相等运算符,Python还有一组逻辑运算符。这些运算符允许你连接多个语句,并执行更复杂的比较。
在Python中,逻辑运算符是单词 and、or 和 not。让我们看一些例子。
要评估 and 运算符的结果是否为真,需要两个表达式同时为真。
(1 < 2) and (2 < 3) # 结果为 True

这里,我们比较字符串,> 和 < 运算符指的是字母顺序。"Yellow" 在 "Cyan" 之后,但 "Brown" 不在 "Magenta" 之后。这意味着第一个语句为真,但第二个不是,从而导致整个表达式的结果为 False。

("Yellow" > "Cyan") and ("Brown" > "Magenta") # 结果为 False
如果我们使用 or 运算符,那么只要有一个表达式为真,整个表达式就为真;只有当两个表达式都为假时,结果才为假。

(25 > 50) or (1 != 2) # 结果为 True

让我们试一下。25 绝对不大于 50。但是 1 不等于 2。所以最终,整个表达式为 True。

最后,not 运算符会反转其前面表达式的值。如果表达式为真,它就变为假;如果为假,则变为真。

not (1 == 1) # 结果为 False
逻辑运算符非常重要,因为它们帮助我们编写更复杂的表达式。我们将在接下来的几个视频中看到它们的实际应用。如果这是你第一次接触这些运算符,可能会觉得有很多东西要记。但别担心,通过练习,你会很快掌握大部分内容。在下一篇阅读材料中,我们有一个速查表,列出了所有可用的运算符及其功能。这是一个方便的资源,在你编写自己的脚本时肯定会发现它很有用。

本节课中,我们一起学习了Python中的比较运算符(如 >、<、==、!=)和逻辑运算符(and、or、not)。我们了解到比较运算的结果是布尔值(True 或 False),并且不同类型(如整数和字符串)之间通常不能直接比较。掌握这些运算符是让程序能够根据条件做出判断的关键一步。
028:使用if语句进行分支 🧭

概述
在本节课中,我们将要学习如何使用Python的if语句来实现程序的分支执行。分支是程序根据条件判断选择不同执行路径的能力,它是编写实用脚本的关键组成部分。我们将通过一个IT相关的具体例子,讲解如何编写条件判断,并理解其语法结构。
掌握了Python表达式、比较运算符和变量的知识后,我们现在可以深入探讨如何在脚本中使用它们,根据不同的值执行不同的操作。程序改变其执行顺序的能力被称为分支。

分支是使你的脚本变得有用的关键组成部分。你可能在日常生活中经常使用分支的概念。例如,如果是在中午之前,你可能会用“早上好”来问候某人,而不是“下午好”或“晚上好”。如果外面在下雨,你可能会选择带伞。如果天气冷,你可能会穿外套。
在你的脚本中,你也可以指示计算机根据输入做出决策。
让我们来看一个以IT为重点的例子。在许多公司,新员工可以选择他们用于访问公司系统的用户名,通常所选用户名需要符合一套给定的准则。公司可以为有效用户名的外观设置不同的标准。目前,我们假设在你的公司,一个有效的用户名必须至少有三个字符。
你被指派编写一个程序,告诉用户他们的选择是否有效。为此,你可以编写一个像下面这样的函数。
以下是定义该函数的代码:
def validate_username(username):
if len(username) < 3:
print("Invalid username. Must be at least 3 characters long.")
这个函数检查用户名的长度是否小于3。如果是,函数会打印一条消息,说明用户名无效。
仔细观察if语句是如何编写的。我们写下关键字if,后跟我们想要检查的条件,然后是一个冒号。之后是if代码块的主体,它进一步向右缩进。
你可能会注意到if代码块和函数的定义方式有一些相似之处。关键字(无论是def还是if)表示一个特殊代码块的开始。在第一行的末尾,我们使用冒号,然后函数体或if代码块的主体向右缩进。
但if代码块和函数的定义方式也有一个重要区别。if代码块的主体只有在条件评估为真时才会执行。否则,它将被跳过。

当然,在if代码块的主体内部,你可以做的事情远不止打印信息。随着我们编程能力的扩展,我们将学习如何执行诸如缩短过长的文本、删除存在的文件、启动未运行的服务等更多操作。

如果你的代码在一个函数内部,你也可以选择根据是否满足某个条件来返回一个值。你能想象那会是什么样子吗?
总结
本节课中我们一起学习了Python中if语句的基本用法。我们了解了分支的概念,即程序根据条件判断执行不同代码路径的能力。我们通过一个验证用户名的具体例子,学习了if语句的语法结构:if关键字、条件表达式、冒号以及缩进的代码块。我们还比较了if语句与函数定义的异同,并认识到if代码块仅在条件为真时执行。
现在你已经知道如何定义函数,并且可以在这些函数中,让你的程序仅在满足特定条件时才执行某些操作。
准备好进一步扩展分支功能,用else语句让我们的分支更有趣了吗?那么请继续观看下一个视频,否则你可能会错过精彩内容。😊
029:else语句 🚦

在本节课中,我们将要学习如何扩展if语句的功能,通过引入else语句来创建更强大的条件分支逻辑。我们将通过具体的例子,理解else语句的语法、作用以及如何在实际编程中应用它。
if语句的扩展:else语句
上一节我们介绍了if语句的基本用法,它允许我们根据条件是否为真来执行特定的代码块。本节中我们来看看如何通过else语句,为条件为假的情况也提供一个执行路径。
if语句本身已经是一个非常有用的结构,但我们可以扩展它,使其功能更加强大。回想一下上一视频中的用户名验证例子。如果我们不仅想在用户名无效时打印消息,还想在用户名有效时也打印一条确认消息,该怎么办?
这里,我们引入了一个else语句来实现这个目标。现在,程序可以根据用户名的长度,在两个方向中选择一个执行。
username = input("请输入用户名:")
if len(username) < 3:
print("用户名无效,长度至少需要3个字符。")
else:
print("用户名有效!")
如果用户名长度不够,我们会收到一条指示用户名无效的消息。但如果程序验证用户名长度足够,它将打印一条消息说明用户名有效。
请注意else语句的写法。它使用else关键字,后跟一个冒号,表示else代码块的开始。同样,代码块的主体需要进一步向右缩进。
else代码块的细节
正如我们之前提到的,这些代码块可以包含多行代码,并且不仅仅是打印消息。它们可以进行计算、修改变量值、返回值等等。
以下是关于缩进的重要规则:
- 你可以选择任意数量的空格进行缩进。
- 但你必须进行缩进。
- 在同一个代码块中,你必须使用相同数量的空格。
何时可以省略else语句
else语句非常有用,但我们并不总是需要它。假设我们想编写一个函数来检查一个值是偶数还是奇数。
我们可能会写出下面这样的代码:
def is_even(number):
if number % 2 == 0:
return True
else:
return False
这里我们使用了一个新的运算符,让我们先解释一下。取模运算符由百分号 % 表示,它返回两个数整数除法的余数。
整数除法是一种在整数之间进行的运算,它产生两个结果(都是整数):商和余数。
5除以2,商是2,余数是1。11除以3,商是3,余数是2。
偶数是 2 的倍数,这意味着一个偶数与 2 进行整数除法时,余数总是 0。在这个函数中,我们正是利用这个原理来判断一个数是否为偶数。
一种更简洁的写法


那么,为什么我们可以在没有else语句的情况下,写出下面这样两个return语句一上一下的代码呢?
def is_even(number):
if number % 2 == 0:
return True
return False
关键在于:当return语句被执行时,函数会立即退出,其后的代码不会被执行。
这意味着如果数字是偶数,计算机将执行return True语句并退出函数。只有在if语句中的条件为假时,其后的任何代码才会被执行。

换句话说,一旦函数执行到return False这一行,我们就可以确定if条件为假,这意味着数字是奇数。
总结与建议
起初,你可能会觉得即使不需要,也加上else语句会更舒服。这完全没问题。重要的是要知道,这两种写法都是正确的。
请记住,这种省略else的技巧只能在if语句内部返回值时使用。
让我们来回顾一下:
if语句允许我们根据特定条件是否为真来分支执行。else语句让我们可以设置一段代码,仅在if语句的条件为假时运行。- 如果你在
if代码块中返回一个值,那么该代码块之后的代码将只在条件为假时执行。
如果这些if和else开始让你感到有点困惑,没关系。这里有很多内容需要消化。最好的方法就是,是的,你猜对了——练习。
所以,请复习这些内容,并根据需要尽可能多地自己动手练习。完成后,我们下一个视频再见。
本节课中我们一起学习了else语句如何与if语句配合,为程序提供完整的条件分支逻辑。我们探讨了其基本语法、缩进规则,并学习了在特定情况下(如在if块中返回值)如何省略else语句以写出更简洁的代码。理解并熟练运用条件控制是编程的基础,请务必通过实践来巩固这些概念。
030:Python条件分支进阶 - elif语句详解 🧩

在本节课中,我们将要学习Python中elif语句的使用。elif是“else if”的缩写,它允许我们在程序中处理多个条件分支,从而使代码更加清晰和灵活。
概述
if和else语句允许我们根据条件的真假来分支执行代码。但是,当需要考虑更多条件时,elif语句就派上用场了。在开始学习如何使用它之前,我们先来看看为什么需要它。
为什么需要elif语句?
让我们回到之前用户名验证的例子。现在,假设你的公司还有一条规则:用户名不能超过15个字符。我们如何告知用户他们选择的用户名太长呢?可以这样做:
if len(username) < 3:
print("Invalid username. Must be at least 3 characters long.")
else:
if len(username) > 15:
print("Invalid username. Must be at most 15 characters long.")
else:
print("Valid username!")
这种方法虽然可行,但代码的嵌套结构使其难以阅读。为了避免不必要的嵌套并使代码更清晰,Python提供了elif关键字。
如何使用elif语句?
elif语句看起来与if语句非常相似。它后面跟着一个条件和一个冒号,然后是一个向右缩进的代码块,构成其主体。只有当条件为真时,elif块的主体才会执行。
elif和if语句的主要区别在于,elif块只能作为if块的伴侣出现。这是因为只有在if语句的条件不成立时,才会检查elif语句的条件。
以下是使用elif的示例:

if len(username) < 3:
print("Invalid username. Must be at least 3 characters long.")
elif len(username) > 15:
print("Invalid username. Must be at most 15 characters long.")
else:
print("Valid username!")
在这个例子中,程序首先检查用户名是否少于3个字符,如果是,则打印一条消息。如果用户名至少有3个字符,程序接着检查它是否超过15个字符,如果是,则打印相应的消息。最后,如果以上条件都不满足,程序打印用户名有效的消息。
添加更多条件
我们可以添加的条件数量没有限制,并且很容易包含新的条件。例如,假设公司决定用户名不应包含数字。我们可以轻松地添加一个额外的elif条件来检查这一点:
if len(username) < 3:
print("Invalid username. Must be at least 3 characters long.")
elif len(username) > 15:
print("Invalid username. Must be at most 15 characters long.")
elif any(char.isdigit() for char in username):
print("Invalid username. Must not contain numbers.")
else:
print("Valid username!")
总结
本节课中我们一起学习了如何使用elif语句来处理多个条件分支。你现在已经知道如何比较事物,并在if、elif和else语句中使用这些比较。通过在函数中使用所有这些语句,利用分支来确定程序的流程,你的脚本将开启全新的可能性。
你可以使用比较来选择执行不同的代码片段,这使得你的脚本非常灵活。分支还可以帮助你完成各种实际任务,例如仅备份特定扩展名的文件,或仅在一天中的特定时间允许登录服务器访问。每当你的程序需要做出决定时,都可以使用分支语句来指定其行为。
你是否开始注意到日常工作中可以通过脚本变得更高效的任务?编程能帮助你做的事情有很多可能性,而我们才刚刚开始探索所有酷炫的东西。
在接下来的阅读材料中,我们为你整理了一份速查表。你会在那里找到一个方便的资源,列出了所有这些运算符和分支块。当你需要快速复习时,它会非常有用。所以不要跳过阅读。
031:面向对象编程介绍(可选) 🐍

在本节课中,我们将学习面向对象编程(OOP)的基本概念。我们将了解如何创建自己的对象,并探索Python中一些有趣的功能。课程还会介绍许多新的术语。
概述
到目前为止,我们已经学习了Python的所有基础语法,并检查了最常见的数据结构,如字符串、列表和字典。这些脚本能够执行许多有趣的操作,例如处理文本、遍历元素以对每个元素执行操作、找出元素出现的频率等等。
在接下来的视频中,我们将重点学习一系列新概念。我们将深入探讨面向对象编程,这是一种思考和实现代码的方式。
面向对象编程简介
上一节我们回顾了Python的基础知识,本节中我们来看看面向对象编程(OOP)。面向对象编程是一种编程范式,它使用“对象”来设计应用程序和软件。对象可以包含数据(属性)和代码(方法)。

以下是面向对象编程的核心概念:
- 类 (Class): 类是创建对象的蓝图或模板。它定义了一组属性和方法,这些属性和方法将由该类的所有对象共享。
class Dog: def __init__(self, name, age): self.name = name # 属性 self.age = age # 属性 def bark(self): # 方法 return "Woof!" - 对象 (Object): 对象是类的实例。它是根据类定义创建的具体实体。
my_dog = Dog("Buddy", 5) # 创建一个Dog类的对象 - 属性 (Attribute): 属性是与对象关联的变量,用于存储对象的数据。
print(my_dog.name) # 输出: Buddy - 方法 (Method): 方法是与对象关联的函数,用于定义对象的行为。
print(my_dog.bark()) # 输出: Woof!
课程总结
本节课中,我们一起学习了面向对象编程的基本介绍。我们了解了类、对象、属性和方法这些核心概念,并看到了如何使用简单的代码来定义类和创建对象。面向对象编程帮助我们以更模块化和可重用的方式组织代码,是Python中一个非常强大的功能。
032:Python面向对象编程 - 实例方法详解 🐷

在本节课中,我们将要学习Python中面向对象编程的一个核心概念:实例方法。我们将通过创建一个可爱的小猪类来理解方法如何操作对象的属性,以及如何让不同的对象实例表现出不同的行为。
什么是实例方法? 🤔
上一节我们介绍了类和对象的基本概念,本节中我们来看看如何让对象“动起来”。
实例方法是属于类的函数,它操作特定类实例的属性。当我们对列表调用append方法时,我们是在向那个特定列表的末尾添加元素,而不是其他列表。当我们对字符串调用lower方法时,我们是将那个特定字符串的内容转换为小写。

理解方法的关键在于:方法是作用于某个类特定实例属性上的函数。
创建第一个方法 🛠️
首先,我们需要定义一个类并创建它的一个实例。
class Piglet:
pass
我们创建了一个Piglet类。虽然我们的小猪可能很可爱,但它现在还做不了什么。如果我们想给它一个“声音”,对象就需要方法来执行动作。
以下是定义一个方法的步骤:
- 在类内部,使用
def关键字定义函数。 - 该函数的第一个参数必须是
self,它代表正在执行该方法的实例本身。 - 函数体需要缩进,以表明它是类的一部分。
让我们给类添加一个speak方法:
class Piglet:
def speak(self):
print("Oink Oink!")
现在,让我们创建一个实例并调用这个方法:
hamlet = Piglet()
hamlet.speak()
# 输出:Oink Oink!
小猪会叫了!但所有Piglet类的实例都会说同样的话,这有点无聊。
让方法依赖实例属性 🎭
为了让方法根据实例的不同属性产生不同的行为,我们需要使用实例变量。
实例变量是那些对于同一个类的不同实例可以拥有不同值的变量。我们可以在类中初始化它们,并在方法中通过self.变量名来访问。
让我们改进Piglet类,为每只小猪起个名字:
class Piglet:
name = "piglet" # 初始化一个实例变量,默认值为"piglet"
def speak(self):
print(f"Oink! I'm {self.name}! Oink!")
在这个新的speak方法中,它使用self.name的值来知道要打印什么名字。这意味着它从当前的小猪实例中访问name属性。
让我们来试试:
hamlet = Piglet()
hamlet.name = "Hamlet" # 设置实例的name属性
hamlet.speak()
# 输出:Oink! I'm Hamlet! Oink!
我们创建了会说话的Python小猪!如果我们用不同的名字创建另一个实例呢?
petunia = Piglet()
petunia.name = "Petunia"
petunia.speak()
# 输出:Oink! I'm Petunia! Oink!
我们创建了两个Piglet类的实例,每个都有自己的名字。当调用speak方法时,每个实例都打印自己的名字,而不是另一个的。这就是实例变量的作用。

带参数和返回值的方法 🔄
既然方法就是属于特定类的函数,它们就可以像其他函数一样工作:可以接收更多参数,也可以返回值。
让我们看一个返回值的例子。我们将创建一个方法,将小猪的人类年龄转换为“猪年”。
class Piglet:
years = 0
def pig_years(self):
return self.years * 18

在这个例子中,pig_years方法根据实例的years属性计算并返回一个值。
让我们创建一个实例并看看这个方法如何工作:
piggy = Piglet()
print(piggy.pig_years())
# 输出:0
piggy.years = 2
print(piggy.pig_years())
# 输出:36
随着years属性值的改变,pig_years方法的返回值也随之改变。
总结 📚
本节课中我们一起学习了Python中的实例方法。

我们了解到:
- 实例方法是定义在类内部的函数,用于操作特定实例的数据。
- 方法的第一个参数总是
self,它指向调用该方法的对象本身。 - 通过
self.属性名,方法可以访问和修改对象的实例变量,从而实现每个对象独特的行为。 - 方法可以接收额外参数,也可以返回值,就像普通函数一样。
通过创建Piglet类并为其添加speak和pig_years方法,我们实践了如何让对象拥有自己的行为和状态。接下来,我们将学习一些特殊类型的方法,特别是被称为构造函数的方法。
033:为什么我喜欢 Python 🐍

在本节课中,我们将通过一位谷歌工程师的视角,了解 Python 在实际 IT 自动化工作中的优势与特点。我们将学习 Python 的可读性、丰富的模块生态,以及它作为脚本语言的适用场景和需要注意的地方。
Python 在 IT 自动化中的应用
上一节我们了解了课程背景,本节中我们来看看 Python 在谷歌内部的具体应用场景。
我的团队负责维护谷歌内部大量计算机的操作系统,我们完成的许多工作都通过 Python 脚本实现。
以下是几个具体的应用实例:
- 系统维护脚本:我们有一个脚本,用于确保计算机软件每日更新,该脚本由 Python 编写。
- 问题检查与告警脚本:我们还有一个脚本,用于检查计算机是否存在特定问题。如果发现问题,它会向用户发出警报以便采取行动,这个脚本同样由 Python 编写。
- 其他自动化脚本:我们拥有许多类似的脚本,运行在用户的计算机上,它们全部由 Python 编写。
Python 的核心优势
了解了 Python 的实际应用后,本节我们深入探讨其备受青睐的两个核心优势。
1. 卓越的代码可读性
我最喜欢 Python 的一点在于其代码极具可读性。你可以将一段 Python 代码交给一个完全不懂编程的人,大多数情况下,他们至少能对代码在做什么有个大致的概念。
2. 丰富的内置与第三方模块
Python 的另一个优点是它自带大量模块,并且拥有庞大的生态系统,这些模块已经实现了我们想做的许多事情。Python 语言历史悠久,有众多贡献者开发了这些模块。
因此,你想实现的功能很可能已经存在于某个模块中,你只需要导入并使用它即可。例如,使用 os 模块与操作系统交互,或使用 requests 模块处理网络请求。
# 示例:导入并使用模块
import os
import requests
# 使用 os 模块检查当前目录
current_dir = os.getcwd()
print(f"当前工作目录是:{current_dir}")
# 使用 requests 模块获取网页内容(示例)
# response = requests.get('https://www.example.com')
Python 的注意事项与最佳实践
没有一种计算机语言是完美的。每种语言都有其优点和缺点。对于 Python 而言,我觉得最令人困扰的一点是,因为它不是编译型语言,代码中的某些错误可能要到开发过程的后期才会被发现。
虽然代码中可能存在这些隐藏的错误不是好事,但可以通过编写良好的测试来缓解这个问题。如果你编写了测试用例,并且这些测试能够覆盖所有代码(即使某些代码路径不常被执行),你就能确信你的代码运行正常。
总结与适用场景
本节课中,我们一起学习了 Python 在 IT 自动化中的强大作用。
综上所述,这就是我认为 Python 非常适合编写自包含的小型脚本,而不太适合需要大量基础设施支撑的大型软件项目的原因。它的简洁、易读和强大的生态,使其成为自动化日常任务的绝佳选择。
034:Python基础语法总结 🎉
在本节课中,我们将总结Python基础语法的核心概念。我们已经学习了如何操作不同的数据类型、创建变量和表达式、定义函数,以及如何在脚本中创建分支结构。这些知识是编写有效Python代码的基石。

模块完成与回顾
恭喜你完成了第二个模块的学习,掌握了大量Python语法知识。
我们学习了如何操作不同的数据类型,并创建了自己的变量和表达式。
我们定义了第一个函数,并学习了如何让函数返回值,以提高代码的可重用性。
条件分支结构
上一节我们介绍了函数,本节中我们来看看如何创建脚本中的分支结构。这使我们的脚本能够根据变量的值采取不同的行动。
我们学习了许多新的、非常强大的内容。了解如何组织代码和函数,以及如何根据不同的值让代码采取不同的行动,是让我们能够告诉计算机该做什么的关键。
知识的应用与巩固
我们将在整个课程中持续使用这些工具,逐步过渡到更复杂和有趣的内容。
接下来,你可以通过下一个分级评估来测试你所学的全部知识。
如果你觉得还没有完全准备好,不必担心。请记住,你可以根据需要多次回看视频并完成练习测验,以确保你完全理解我们涵盖的所有内容。
当你准备好进行测试时,请从容应对。祝你一切顺利。
在你完成测试后,我们将在下一个模块再见。在那里,我们将全面学习循环结构。
总结
本节课中我们一起学习了Python的基础语法,包括变量、数据类型、函数和条件分支。这些是构建更复杂程序的必要基础。我们将在后续课程中不断应用和深化这些概念。

我们下个模块见。
035:Python基础语法总结 🎯

在本节课中,我们将对Python基础语法模块进行总结,回顾已学习的关键概念,并为后续学习做好准备。
概述
上一节我们介绍了条件分支,本节中我们将对整个基础语法模块进行回顾与总结。我们已经学习了Python编程的多个核心组成部分。
核心概念回顾
以下是我们在本模块中掌握的关键技能:
- 变量与表达式:我们学会了如何创建变量来存储数据,并使用表达式进行计算。例如,
total = price * quantity。 - 数据类型操作:我们掌握了如何操作字符串、整数、浮点数等不同数据类型。
- 函数定义与返回值:我们定义了第一个函数,并学会了使用
return语句使其返回值,从而提高代码的可重用性。例如:def calculate_area(length, width): return length * width - 条件分支:我们深入学习了如何在脚本中创建分支,使代码能够根据变量的值执行不同的操作。这通过
if、elif、else语句实现。
学习成果的意义
理解如何组织代码和函数,以及如何让代码根据不同的值采取不同的行动,是我们能够指挥计算机完成任务的基础。这些强大的工具将在整个课程中持续使用,帮助我们处理更复杂、更有趣的项目。
下一步:测验与展望
接下来,你可以在即将到来的分级评估中检验所学的一切。如果你觉得尚未完全准备好,无需担心。请记住,你可以随时回看视频并多次完成练习测验,以确保完全理解我们涵盖的所有内容。
当你准备好参加测试时,请从容应对。祝你一切顺利!
完成测试后,我们将在下一个模块再见。在那里,我们将全面学习循环的相关知识。
总结
本节课中我们一起回顾了Python基础语法模块的核心内容,包括变量、表达式、函数和条件分支。这些是构建更复杂程序的基石。我们即将通过测验巩固知识,并迈向关于循环的新篇章。

期待下次相见! 👋
036:循环介绍 🔄

在本节课中,我们将要学习编程中的一个核心概念——循环。循环允许计算机自动、准确地执行重复性任务,这是实现自动化办公的关键技能。
概述
上一节我们介绍了如何通过函数组织代码,以及如何根据条件让代码分支执行。本节中,我们来看看如何让计算机执行重复性任务。
计算机非常擅长重复执行相同的任务。它们不会感到无聊,也不会出错。你可以让计算机进行一千次相同的计算,第一次的结果会和最后一次一样准确,这是人类难以做到的。这种准确执行重复任务且永不疲倦的能力,正是计算机在自动化领域如此强大的原因。
自动化任务可以是多种多样的,例如:将文件复制到网络上的多台计算机、向用户列表发送个性化邮件,或者验证某个进程是否仍在运行。无论任务多么复杂,计算机都会按照你的指令执行任意多次,从而让你有时间去处理更有趣的事情,比如规划未来的硬件需求或管理软件部署。
在接下来的视频中,我们将探索三种实现重复任务自动化的技术:while循环、for循环和递归。这些技术都用于指示计算机重复执行任务,但各自采用了略有不同的方法。我们将学习如何为每种技术编写代码,以及如何判断在何种情况下应使用哪一种技术。

三种循环技术


以下是三种主要的循环技术:
-
while循环- 当特定条件为真时,重复执行一段代码块。
- 代码示例:
while condition_is_true: # 执行任务
-
for循环- 对序列(如列表、字符串)中的每个元素,重复执行一段代码块。
- 代码示例:
for item in sequence: # 对每个item执行任务
-
递归
- 函数调用自身来解决问题,通常用于将复杂任务分解为更小的同类子任务。
- 代码示例:
def recursive_function(parameters): if base_case_condition: # 基线条件,用于停止递归 return base_case_value else: # 处理并递归调用自身 return recursive_function(modified_parameters)
总结
本节课中我们一起学习了循环在编程中的重要性。我们了解到,循环是让计算机自动化处理重复性任务的基础,它解放了人力,使我们能专注于更复杂的规划和管理工作。我们简要介绍了三种实现循环的技术:while循环、for循环和递归,并将在后续课程中详细学习每一种的具体用法和应用场景。
037:什么是while循环?🔄

在本节课中,我们将要学习Python编程中的一个核心概念——while循环。循环是让计算机重复执行某段代码的强大工具,它能帮助我们自动化重复性任务,是IT自动化办公中不可或缺的一部分。
概述

首先,我们来谈谈while循环。while循环指令你的计算机根据一个条件的值来持续执行你的代码。
这与我们之前学过的分支结构(if语句) 工作原理相似。关键区别在于,循环体中的代码块可以被执行多次,而不仅仅是一次。
一个简单的while循环示例
让我们来看下面这段程序。在运行它之前,你能猜出它会做什么吗?
我们将一起逐行分析它。
x = 0
while x < 5:
print("还没到呢,x的值是:", x)
x = x + 1
print("循环结束,x的最终值是:", x)
代码解析
- 初始化变量:在第一行,我们将值
0赋给变量x。这个操作称为初始化,即给变量一个初始值。 - 启动循环:在下一行,我们开始了
while循环。我们为这个循环设置了一个条件:x需要小于5。目前,我们知道x是0,所以这个条件当前为真。 - 循环体:接下来的两行代码向右缩进,根据我们学过的函数和条件语句知识,可以识别出这是
while循环的主体。
以下是循环体内的两个操作:
- 第一行:打印一条消息,后面跟着
x的当前值。 - 第二行:递增
x的值。我们通过将其当前值加1,然后重新赋值给x来实现。
所以,在第一次执行循环体之后,x将从0变为1。


循环是如何工作的?
因为这是一个循环,计算机不会直接继续执行脚本中的下一行。相反,它会循环回去,重新评估while循环的条件。
由于此时x(值为1)仍然小于5,它会再次执行循环体。它再次打印消息,并再次将x增加1。现在x变成了2。
计算机会持续这个过程,直到条件不再为真。在这个例子中,当x不再小于5(即x >= 5)时,条件将变为假。
一旦条件为假,循环结束,程序继续执行循环之后的下一行代码。最后,我们代码的最后一行打印出x的最终值。
执行结果
现在这段代码的逻辑更清晰了,你认为当我们执行它时会发生什么?
让我们运行代码看看结果。
还没到呢,x的值是: 0
还没到呢,x的值是: 1
还没到呢,x的值是: 2
还没到呢,x的值是: 3
还没到呢,x的值是: 4
循环结束,x的最终值是: 5
我们得到了五行“还没到呢”的消息。在脚本的最后,x的值是5。
while循环的应用场景
这是一个展示while循环行为的简单例子。正如我们之前所说,我们正在学习编程的基础构建模块。一旦你掌握了这些模块,就可以将它们组合起来创建更复杂的表达式。
对于IT专家来说,循环非常有用。以下是几个应用场景:
- 你可以用它来持续请求用户名,直到提供的用户名有效为止。
- 或者重复尝试一个操作,直到它成功为止。
了解如何构建这些表达式,可以帮助你用很少的代码让计算机完成大量工作,这非常强大。
另一个例子
现在你已经了解了while循环的基本工作原理,让我们用另一个例子来加深理解。
假设我们需要一个程序,让用户重复输入密码,直到输入正确为止(这里我们假设正确密码是"secret")。
password = ""
while password != "secret":
password = input("请输入密码:")
print("密码正确,欢迎进入!")
在这个例子中:
- 我们首先将
password变量初始化为空字符串。 while循环的条件是password != "secret",意思是“当密码不等于‘secret’时”。- 只要用户输入的不是
"secret",循环就会一直要求输入。 - 一旦用户输入了
"secret",条件变为假,循环结束,打印欢迎信息。
总结
在本节课中,我们一起学习了while循环。我们了解到:
- while循环用于在条件为真时重复执行一段代码块。
- 它与if语句的关键区别在于执行次数:循环可以执行多次,而if语句的代码块只执行一次(如果条件为真)。
- 循环通常包含三个关键部分:变量初始化、循环条件和在循环体内改变条件变量的值(以避免无限循环)。
- while循环是自动化重复任务、验证用户输入和处理不确定次数操作的基础工具。

掌握循环是迈向有效编程和IT自动化的重要一步。在接下来的课程中,我们将探索更多类型的循环和它们的实际应用。
038:更多while循环示例 🌀

在本节课中,我们将深入学习while循环的更多应用示例。我们将探讨如何在函数内部使用while循环,以及如何通过调用其他函数和逻辑运算符来构建更复杂的循环条件。通过具体示例,帮助初学者理解while循环的灵活性和强大功能。
回顾简单while循环
上一节我们介绍了while循环的基本语法和工作原理。现在,我们将应用这些知识来解析一个类似的示例,但这次while循环位于函数内部。
函数内的while循环示例
以下是一个包含while循环的函数示例,请尝试分析其功能:
def example_function(n):
x = 1
while x <= n:
print(f"当前尝试次数:{x}")
x += 1
在这个示例中,我们首先初始化一个名为x的变量,并将其值设为1。然后进入while循环,检查x的值是否小于或等于函数接收的参数n。如果比较结果为真,则执行循环体内的代码。
假设我们向该函数传递参数值5。在第一次循环中,x等于1,因此比较1 <= 5为真,进入循环体。
在循环体内,我们首先打印一条消息,显示当前尝试次数,然后将x的值增加1。这里使用了x += 1的简写形式,它等同于x = x + 1。两种表达式含义相同,可互换使用。
这个过程持续进行,直到比较结果不再为真,即当x大于n时。在当前示例中,当x的值变为6时,循环结束。
使用函数调用的循环条件
在上述示例中,我们使用了简单的数值比较条件。这些是常见条件,但并非while循环中唯一可用的条件类型。
例如,常见的做法是调用一个单独的函数来评估条件,如下所示:
username = get_username()
while not valid_username(username):
print("无效用户名,请重新输入。")
username = get_username()
在这种情况下,大量代码隐藏在函数背后,执行我们看不到的操作。get_username函数用于向用户请求用户名,valid_username函数用于验证该用户名。所有这些操作仅通过少量字符完成。
如您所见,短短一行代码可以包含强大的功能。在此示例中,while循环体将一直执行,直到用户输入有效的用户名。
需要记住的重要一点是,while循环使用的条件必须评估为True或False。无论是通过比较运算符还是调用其他函数来实现,这一点都至关重要。
使用逻辑运算符的复杂条件
while循环中使用的条件也可以通过逻辑运算符(如and、or、not)变得更加复杂。这些运算符允许我们组合多个表达式的值,以获得所需的结果。
例如:

while (x > 0) and (x < 10):
# 循环体代码
常见陷阱与注意事项
我们已经介绍了while循环是什么,学习了其语法和基本行为。虽然其中一些内容可能有些棘手,但您做得很好,请继续保持。
接下来,我们将概述在编写自己的循环时可能遇到的一些最常见陷阱。请继续学习下一节内容以深入了解。
总结
在本节课中,我们一起学习了while循环的更多应用示例。我们探讨了如何在函数内部使用while循环,如何通过调用其他函数来构建循环条件,以及如何使用逻辑运算符创建更复杂的条件。理解这些概念将帮助您更灵活地使用while循环,编写出更高效、更强大的Python代码。
039:Python循环中的变量初始化 🎯
课程编号:P39

在本节课中,我们将要学习为什么在编写循环时正确初始化变量至关重要。我们将探讨忘记初始化变量可能导致的两种常见问题,并通过具体示例来理解如何避免这些错误。
在之前的课程中,我们介绍了循环如何让计算机为我们执行重复性工作。由于编写脚本和进行IT自动化的主要好处之一是通过自动化重复任务来节省时间,因此循环非常有用。本节中我们来看看编写循环时人们常犯的一些错误,并学习如何避免它们。
最常见的错误之一是忘记用正确的值初始化变量。我们刚开始学习编码时都犯过这个错误。还记得在之前的例子中,我们在一种情况下将变量x初始化为0,在另一种情况下初始化为1吗?
当我们忘记初始化变量时,可能会发生两种不同的事情。
以下是第一种可能的结果,也是最容易发现的:
- Python可能会引发一个错误,告诉我们正在使用一个未定义的变量。错误信息如下所示:
正如我们处理遇到的其他错误一样,我们可以查看最后一行来了解发生了什么。这个错误类型是NameError,后面的信息说明我们使用了未定义的变量。NameError: name 'variable_name' is not defined
修复这个问题很简单。我们只需要在使用变量之前初始化它,像这样:
variable_name = 0 # 或其他合适的初始值
# 现在可以使用 variable_name 了
上一节我们介绍了因变量未定义而导致的错误,本节中我们来看看第二种更隐蔽的问题。
如果我们忘记用正确的值初始化变量,可能会遇到的第二个问题是:变量可能已经在程序的其他地方被使用过了。在这种情况下,如果我们没有从一开始就为变量设置正确的值,它将仍然保留之前的值。这可能导致一些非常意外的行为。
请看这个脚本:
# 第一部分:计算1到10的和
x = 1
sum = 0
while x <= 10:
sum += x
x += 1
print(f"Sum from 1 to 10 is: {sum}")
# 第二部分:计算1到10的乘积
product = 1
while x <= 10:
product *= x
x += 1
print(f"Product from 1 to 10 is: {product}")
你能发现问题吗?
在第一部分代码中,我们正确地将x初始化为1,sum初始化为0,然后迭代直到x等于10,累加中间的所有值。因此,在该部分代码结束时,sum等于从1到10所有数字相加的结果,而x的值是10。
在代码的第二部分,本意是获取从1到10所有数字的乘积。但如果你仔细观察,会发现我们初始化了product,却忘记了重新初始化x。所以x仍然是10。这意味着当检查while循环条件时,在迭代开始前x就已经是10了。while条件在开始前就为假,循环体永远不会执行。

在这种情况下,可能更难发现问题,因为Python不会引发错误。这里的问题是我们的product变量得到了错误的值。如果你的循环行为异常或不符合预期,最好检查一下是否所有变量都已正确初始化。在这个例子中,我们需要在开始第二个循环之前将x重置为1。

学习的最佳方式永远是亲自实践。如果你在某个地方感到困惑或不确定,可以随时在讨论区寻求帮助。这些论坛就是为了让你在需要时获得所需的帮助,所以别忘了使用它们。
本节课中我们一起学习了编写循环时初始化变量的重要性。总结如下:
- 每当编写循环时,请检查你是否在使用所有变量之前对它们进行了初始化。
- 如果第一次没有做对,请不要担心。我们学习编码时都经历过这个阶段。正如之前强调的,掌握编程的方法就是练习、练习、再练习。不断练习直到你感到得心应手,即便如此,犯错也是可以的。所以,不要觉得你不能回过头去复习和练习我们目前所涵盖的所有内容。
040:Python中的无限循环与中断方法 🔄

在本节课中,我们将要学习无限循环的概念、它可能带来的问题,以及如何避免或中断无限循环。理解这些内容对于编写稳定、高效的Python程序至关重要。

什么是无限循环?
上一节我们介绍了while循环的基本用法,它通过检查一个条件来决定是否继续执行。本节中我们来看看,如果这个条件永远不会变为False,会发生什么。
无限循环是指循环条件始终为真,导致循环体永不停止执行的情况。这通常是由于循环体内的逻辑未能改变循环条件所导致的。
例如,考虑以下代码:
x = 0
while x % 2 == 0:
x = x / 2
在这个例子中,如果x的初始值为0,那么0 % 2的结果是0,条件为真。循环体内x = 0 / 2的结果仍然是0,因此x的值永远不会改变,循环将永远执行下去。
如何避免无限循环?
为了避免程序陷入无限循环,我们需要在编写循环时仔细考虑变量的所有可能取值。
以下是两种常见的预防策略:
-
使用条件语句包裹循环:在执行循环之前,先检查条件是否安全。
if x != 0: while x % 2 == 0: x = x / 2 -
在循环条件中增加逻辑判断:将安全条件直接整合到
while语句中。while x != 0 and x % 2 == 0: x = x / 2
这两种方法都确保了只有当x不为零时,才会进入可能修改x值的循环体,从而避免了除零和值不变的情况。
如何主动中断循环?
虽然我们需要警惕意外的无限循环,但有时我们也会故意创建无限循环,让程序持续运行直到某个外部条件被触发。
例如,网络工具ping会持续发送数据包,直到用户手动中断(通常通过按下Ctrl+C)。在Python中,我们使用break关键字来主动跳出循环。
break语句的作用是立即终止当前所在的最内层循环。它不仅可以用于跳出无限循环,也可以在循环任务提前完成时,用于提前结束循环。
以下是一个使用break的无限循环示例:
while True:
# 执行一些持续性的任务,例如监控网络
if some_external_condition_met:
break # 条件满足时,跳出循环
在这个模式中,while True:创建了一个条件永远为真的循环。循环的退出完全依赖于内部的if语句和break。
核心要点总结
本节课中我们一起学习了关于循环控制的重要知识:

- 无限循环是条件永不终止的循环,通常由编程逻辑错误引起。
- 避免无限循环的关键是:确保循环体内的操作能影响循环条件,并仔细考虑变量的边界值。
break语句是控制循环流程的强大工具,可以用于设计受控的无限循环或在满足条件时提前退出。
记住,编写循环时,花点时间思考“这个循环在什么情况下会停止”,是写出健壮代码的好习惯。
所有关于循环的讨论可能让人有点“晕眩”了。在你进行接下来的练习测验之前,我需要去躺一会儿休息一下。祝你好运,完成后我们下一个视频再见。😊
041:Python中的for循环 🔄

在本节课中,我们将要学习Python编程中的一种重要结构——for循环。for循环允许我们遍历一个序列中的每个元素,并对每个元素执行相同的操作。这在自动化任务中非常有用,比如处理文件列表、分析数据或批量操作。
什么是for循环?
上一节我们介绍了循环的基本概念,本节中我们来看看for循环的具体结构和工作原理。
for循环用于遍历一个序列中的值。一个非常简单的for循环示例如下,它遍历一个由数字组成的序列:
for x in range(5):
print(x)
请注意,这个结构与我们之前见过的结构有些相似。第一行以关键字for开始,并以冒号结束。循环体向右缩进,就像我们在while循环、if语句块和函数定义中看到的那样。
不同之处在于,这里我们使用了关键字in。此外,在for关键字和in关键字之间,我们有一个变量名。这个变量将依次取序列中的每个值。
在这个例子中,它遍历由range函数生成的一个数字序列。
关于range函数的重要说明

关于range函数,有两个重要事项需要说明:
首先,在Python以及许多其他编程语言中,默认情况下,数字范围从0开始。
其次,生成的数字列表将比给定的值少一个。
在刚才的简单示例中,变量x将依次取值0、1、2、3和4。让我们验证一下:

for x in range(5):
print(x)
这样我们就得到了一个非常基础的for循环,它遍历由range函数生成的数字序列。
for循环的工作原理
使用for循环时,我们将定义在for和in之间的变量(在这个例子中是x)指向序列中的每个元素。这意味着在第一次迭代中,x指向0;在第二次迭代中,它指向1,依此类推。
无论我们在循环体中放入什么代码,都会在每个值上执行,一次处理一个值。
正如我们之前所说,循环体可以用它遍历的值做很多事情。例如,你可以有一个计算数字平方的函数,然后使用for循环来求一个范围内数字的平方和。
遍历不同类型的序列
遍历数字看起来与之前展示的while循环示例非常相似。你可能会想,为什么要有两个看起来做同样事情的循环呢?
for循环的强大之处在于,我们可以用它来遍历任何类型的值的序列,而不仅仅是数字范围。回想一下本课程中我们最初的Python示例,还记得我们可靠的“hello friends”脚本吗?在里面,我们看到了一个遍历字符串列表的for循环,它看起来像这样:
for name in ["Alice", "Bob", "Charlie"]:
print("Hello, " + name + "!")
我们将在后面更多地讨论列表。但现在,你只需要知道我们可以使用方括号构造列表,并用逗号分隔其中的元素。
在这个例子中,我们遍历一个字符串列表,并为列表中的每个字符串打印一条问候语。
for循环遍历的序列可以包含任何类型的元素,不仅仅是字符串。例如,我们可以遍历一个数字列表来计算总和与平均值。以下是其中一种实现方式:
values = [1, 2, 3, 4, 5]
sum = 0
length = 0
for value in values:
sum = sum + value
length = length + 1
print("Sum:", sum)
print("Average:", sum / length)
这里,我们定义了一个值列表。之后,我们初始化两个变量sum和length,它们将在for循环体中更新。
在for循环中,我们遍历列表中的每个值,将当前值加到总和上,同时将length加1,以计算列表中有多少个元素。遍历完整个列表后,我们打印出总和与平均值。
for循环在IT自动化中的应用

我们将在示例中继续使用for循环,每当我们想要遍历任何序列的元素并对它们进行操作时。
以下是一些我们可以遍历的序列示例:
- 目录中的文件
- 文件中的行
- 机器上运行的进程
还有很多其他例子。因此,作为一名IT专家,你将使用for循环来自动化大量任务。例如:
- 将文件复制到多台机器
- 处理文件内容
- 自动安装软件
- 以及更多其他任务
几周前,我不得不根据内容用不同的值更新大量文件。于是我写了一个脚本,使用for循环遍历所有文件。然后,我的脚本根据if条件采取不同的操作,并为我更新了所有这些文件。如果我手动逐个文件操作,那将花费我大量的时间。
for循环与while循环的选择
如果你想知道何时应该使用for循环,何时应该使用while循环,这里有一个判断方法:
- 当存在一个你想要遍历的元素序列时,使用for循环。
- 当你想要重复一个动作直到某个条件改变时,使用while循环。
如果你尝试做的事情既可以用for循环也可以用while循环完成,那就用你最喜欢的那一个。我个人更喜欢while循环,但这完全取决于你的选择。

总结
本节课中我们一起学习了Python中的for循环。我们了解了它的基本语法,如何使用range函数生成数字序列,以及如何遍历不同类型的序列(如列表)。我们还探讨了for循环在IT自动化中的实际应用,并学习了如何根据任务需求在for循环和while循环之间做出选择。
掌握for循环是编写高效、自动化Python脚本的关键一步。接下来,我们将通过更多示例来帮助你练习使用for循环,并发现一些可以用它们实现的酷炫功能。
042:更多for循环示例 🔄

在本节课中,我们将深入学习Python中range函数的更多用法,特别是如何通过传递不同数量的参数来控制序列的起始值、结束值和步长。我们将通过具体的代码示例来演示这些概念,帮助你更好地理解和应用for循环。
起始值不为零的序列
上一节我们介绍了range函数的基本用法,它默认生成从0开始的序列。本节中我们来看看,当我们需要序列从非零值开始时该如何操作。
range函数允许我们通过传递两个参数来指定生成序列的起始元素。第一个参数是起始值,第二个参数是结束值(不包含)。
以下是计算1到9所有数字乘积的示例:
product = 1
for n in range(1, 10):
product = product * n
print(product)
在这个例子中,我们计算从1到9所有数字的乘积。这个操作必须从1开始,如果从0开始,整个乘积结果将为零。
控制序列的步长
除了起始值,我们还可以通过传递第三个参数来改变序列中每个元素之间的步长。这意味着元素之间的差值可以大于1。
以下是一个实际应用的例子,我们将创建一个华氏温度到摄氏温度的转换表:
def to_celsius(x):
return (x-32) * 5/9
for x in range(0, 101, 10):
print(x, to_celsius(x))
我们定义了一个将华氏温度转换为摄氏温度的函数to_celsius,它使用了转换公式(x-32) * 5/9。
for循环从0开始,到100结束,步长为10。注意,我们使用101作为上限而不是100,因为range函数不包含最后一个元素,而我们希望100被包含在序列中。
循环体打印出华氏温度值及其对应的摄氏温度值,从而生成一个转换表。
range函数参数总结
前面的例子可能包含了许多信息,但请不要担心。正如我们之前所说,你不需要死记硬背,多加练习自然会熟练掌握。
以下是range函数接收不同数量参数时的行为总结:

- 如果接收一个参数,它会创建一个从0开始,到(参数值-1)结束,步长为1的序列。
- 公式:
range(stop)-> 生成[0, 1, 2, ..., stop-1]
- 公式:
- 如果接收两个参数,它会创建一个从第一个参数开始,到(第二个参数-1)结束,步长为1的序列。
- 公式:
range(start, stop)-> 生成[start, start+1, ..., stop-1]
- 公式:
- 如果接收三个参数,它会创建一个从第一个参数开始,向第二个参数移动,步长为第三个参数的序列。同样,它在到达第二个参数前停止。
- 公式:
range(start, stop, step)-> 生成[start, start+step, start+2*step, ...](最后一个值 < stop)
- 公式:
本节课中我们一起学习了range函数更高级的用法,包括如何指定序列的起始值、结束值和步长。我们通过计算乘积和创建温度转换表两个实例,演示了这些参数在实际编程中的应用。记住,理解这些概念的关键在于实践,多写代码,你就能轻松掌握。
043:嵌套的 for 循环 🔄

在本节课中,我们将要学习嵌套的 for 循环。这是一种在循环内部再放置另一个循环的编程技巧,常用于处理需要组合或配对数据的情况。我们将通过两个具体的例子来理解其工作原理和实际应用。
概述
嵌套循环是指一个循环结构内部包含另一个完整的循环结构。这种结构特别适用于需要遍历多维数据或生成组合的场景。理解嵌套循环是掌握复杂数据处理的关键一步。
多米诺骨牌的例子 🎲
上一节我们介绍了循环的基本概念,本节中我们来看看如何用嵌套循环解决一个实际问题:打印一套多米诺骨牌的所有组合。
一套标准的多米诺骨牌,每张牌有两个数字(从0到6),且组合(如2-3和3-2)被视为同一张牌,只出现一次。我们的目标是编写程序打印出所有唯一的骨牌组合。
以下是实现此目标的思路:
- 首先处理所有左边数字为0的骨牌,右边数字可以从0打印到6。
- 接着处理左边数字为1的骨牌,但需要跳过0-1组合,因为它已经作为1-0打印过了。因此,右边数字从1打印到6。
- 以此类推,对于左边数字为
n的骨牌,右边数字从n开始打印到6。
将上述思路转化为代码,就需要使用两个for循环,一个套在另一个里面,即嵌套循环。
for left in range(7):
for right in range(left, 7):
print("[" + str(left) + "|" + str(right) + "]", end=" ")
print()
在这段代码中,我们使用了一个传递给 print 函数的新参数:end。默认情况下,print 函数在输出内容后会添加一个换行符。通过设置 end=" ",我们让它在输出每个骨牌后添加一个空格而不是换行,从而使一行的输出更紧凑。注意,内部的 for 循环每次迭代的元素数量会随着外部循环变量 left 的值变化而变化。
篮球联赛配对的例子 🏀
嵌套循环的另一个典型应用是生成配对或组合。假设你管理一个由四支队伍组成的本地女子篮球联赛,每支队伍都需要与其他队伍进行主客场两场比赛。
我们有一个存储队伍名称的列表:
teams = [‘Dragons‘, ‘Wolves‘, ‘Pandas‘, ‘Unicorns‘]
我们希望编写脚本输出所有可能的比赛配对。配对中名字的顺序很重要,因为第一个名字代表主队,第二个名字代表客队。当然,我们不需要一支队伍与自己比赛。
以下是生成所有有效比赛配对的步骤:
- 我们需要使用一个条件判断来确保只在两支队伍名称不同时才打印配对。
for home_team in teams:
for away_team in teams:
if home_team != away_team:
print(home_team + " vs " + away_team)
如你所见,嵌套循环是解决像队伍配对这类问题的超级有用的工具。
关于性能的注意事项 ⚠️
虽然嵌套循环是一个方便的工具,但我们不能盲目地将其应用于所有问题。主要原因是性能考虑:代码需要遍历的列表越长,计算机完成任务所需的时间就越长。
假设你的经理要求你对一个包含10,000个元素的列表进行操作。如果每个元素的操作耗时1毫秒,那么整个单层循环将耗时 10秒(10000 * 0.001秒)。
现在,想象我们添加一个嵌套循环,它也必须遍历同样的10,000个元素。这意味着外部循环的每一次迭代,都会完整地执行一次内部循环(耗时10秒)。因此,整个嵌套迭代将耗时 100,000秒(10000 * 10秒),这超过了27小时。

这并不意味着我们不应该使用嵌套循环。它们是解决特定问题的有用工具,但我们需要谨慎考虑在何处以及如何使用它们。在本课程及后续课程中,我们将学习许多技巧,帮助我们为不同类型的问题选择合适的工具。
总结
本节课中我们一起学习了嵌套的 for 循环。我们通过打印多米诺骨牌组合和生成篮球联赛赛程两个例子,理解了嵌套循环的结构和应用场景。同时,我们也认识到需要关注嵌套循环可能带来的性能影响,并学会在合适的场景下使用它。接下来,我们将探讨在编写 for 循环时可能遇到的一些常见错误及其解决方法。
044:Python for循环中的常见错误 🐍

在本节课中,我们将学习在使用Python的for循环时可能遇到的一些常见错误。理解这些错误及其解决方法,能帮助你更顺畅地编写自动化脚本。
上一节我们介绍了如何编写for循环并将其与函数、嵌套循环及条件语句结合使用。本节中,我们来看看在尝试自己编写循环时可能遇到的一些典型问题。
错误类型一:尝试迭代不可迭代对象
for循环用于迭代序列。解释器会拒绝迭代单个非序列元素。
例如,以下代码会引发错误:
for x in 25:
print(x)
Python会抛出一个TypeError,提示整数(integers)是不可迭代的。
解决方法取决于你的意图:
以下是两种常见场景的解决方案:
-
如果想从0迭代到25:应使用
range()函数。for x in range(25): print(x) -
如果想迭代一个仅包含数字25的列表:则需要将其放入列表中。
for x in [25]: print(x)
你可能会疑惑,为什么要迭代只有一个元素的列表?这通常发生在函数内部。例如,一个用于修复文件权限的函数,其参数预期接收一个文件列表。当你只想修复一个特定文件时,也需要将这个文件作为单元素列表传入。
错误类型二:意外迭代字符串的字符
让我们通过一个熟悉的例子来探讨这个问题。我们将修改“问候朋友”的代码,将问候语放在一个函数内。
我们定义了一个greet_friends函数,它接收一个列表作为参数,并遍历该列表来问候每个朋友。
def greet_friends(friends):
for friend in friends:
print("Hi " + friend + "!")
greet_friends(["Alice", "Bob", "Charlie", "Diana"])
但如果只想问候一位朋友(例如“Mary”),直接传入字符串会如何?
greet_friends("Mary")
输出并非预期。这是因为字符串本身是可迭代的。for循环会遍历字符串的每一个字母并执行操作(本例中是打印问候语),导致为每个字母都打印了一条问候信息。
在某些情况下,你确实需要遍历字符串的每个字符。但在此例中,我们并不需要。
正确的做法是,即使只有一个朋友,也应将其作为列表的元素传入:
greet_friends(["Mary"])

本节总结
本节课我们一起学习了for循环中的两个常见错误:
- 尝试迭代不可迭代的单个对象(如整数)。解决方法是确保循环作用于一个序列,使用
range()或将其放入列表。 - 本想迭代包含字符串的列表,却意外地迭代了字符串本身的字符。解决方法是将单个字符串放入列表中再传递。
简而言之,若遇到“某类型不可迭代”的错误,需确保for循环使用的是元素序列而非单个元素。若发现代码在遍历字符串的字母而你本意是处理整个字符串,则很可能需要将该字符串作为列表的一部分。
我们已经学会了编写while循环和for循环。记住,当需要遍历已知元素序列时,for循环是最佳选择;而当需要在某个条件为真时持续操作,则应使用while循环。
接下来,我们将提供一份超级实用的速查表,将所有循环知识汇总。之后,请前往练习测验来检验你的学习成果。😊
045:什么是递归(可选)🔁

在本节课中,我们将要学习一种新的编程技术——递归。我们将了解递归的基本概念、工作原理,并通过具体例子来理解它如何解决复杂问题。
欢迎回来。完成上一个测验后感觉如何?
我们开始学习一些可以在代码中实现的非常酷的技巧。谁能想到循环可以如此迷人?😊 目前我们已经发现了两种可以在Python中使用的循环技术:while循环和for循环。当某个条件为真时,我们使用while循环来重复执行操作。当我们想要遍历序列中的元素时,则使用for循环。
现在,我们将探讨第三种技术——递归。但在深入之前,你可能已经注意到本视频标记为“可选”。这是因为,虽然递归是软件工程中一种非常常见的技术,但在自动化领域中使用得并不多。尽管如此,我们认为了解递归并知道如何使用它对你来说仍然很有价值。你可能会在他人编写的代码中看到它,或者遇到一个用递归解决是最佳方案的问题。因此,虽然接下来的几个视频标记为可选,且其内容不计入评分,但它们仍然非常有价值。当然,如果你更愿意专注于需要评分的概念,可以自由跳过它们。
让我们开始吧。递归是将相同的过程重复应用于一个更小的问题。😊
递归的直观理解
你玩过俄罗斯套娃吗?它们是递归的一个绝佳视觉示例。每个套娃内部都有一个更小的套娃。当你打开一个套娃找到里面更小的那个时,你会一直继续,直到到达最小的那个无法再打开的套娃。
递归让我们通过将问题简化为一个更简单的问题来处理复杂问题。😊
以我们的俄罗斯套娃为例,它们都嵌套在彼此内部。想象一下,我们想知道总共有多少个套娃。我们需要一个一个地打开每个套娃,直到最后一个,然后数一数我们打开了多少个。这就是递归在起作用。
以下是另一个更复杂问题的例子。想象你排在一个队伍中,想知道你前面有多少人。我得说,我受不了排长队。无论如何,如果队伍很长,在不离开队伍并失去位置的情况下,可能很难数清人数。因此,你可以问你前面的人,他们前面有多少人。由于这个人处于和你相同的情况,他们必须问他们前面的人同样的问题,以此类推,直到问题传到队伍的第一个人。这个人可以自信地回答,他前面没有人。然后,队伍中的第二个人可以回答“1”。他后面的人回答“2”,以此类推,直到答案传回给你。
好吧,我知道让所有人都配合你,只为了让你知道自己在队伍中的位置,这种可能性很小,但这是可视化递归工作原理的一个有用方法。
编程中的递归
那么,这在编程中如何体现呢?在编程中,递归是一种通过让函数调用自身来执行重复任务的方式。😊
一个递归函数会调用自身,通常使用一个修改过的参数,直到达到一个特定条件。这个条件被称为基线条件。在我们之前的例子中,基线条件就是最小的俄罗斯套娃或队伍最前面的人。
让我们看一个递归函数的例子,以理解我们在这里讨论的内容。
递归函数示例:阶乘

我们定义一个名为factorial的函数。在函数的开头,我们有一个条件块,定义了基线条件,即当n小于2时,它直接返回值1。😊
在基线条件之后,我们有一行代码,factorial函数用n-1作为参数调用自身。这被称为递归情况。这创建了一个循环:每次函数执行时,它都会用一个更小的数字调用自身,直到达到基线条件。一旦达到基线条件,它返回值1,然后之前调用的函数将其乘以2,再之前调用的函数将其乘以3,依此类推。这个循环会一直持续,直到第一个被调用的factorial函数返回期望的结果。
这有点复杂,对吧?让我们添加一些print语句来确切地看看它是如何工作的。😊
def factorial(n):
print(f"计算 {n} 的阶乘")
if n < 2:
print(f"达到基线条件,n={n},返回 1")
return 1
else:
result = n * factorial(n-1)
print(f"计算 {n} 的阶乘完成,结果是 {result}")
return result
# 调用函数
print(factorial(5))
在这里,我们可以看到函数不断调用自身,直到达到基线条件。之后,每个函数返回前一个函数的值乘以n,直到原始函数返回结果。
很酷,😊
总结与前瞻
本节课中,我们一起学习了递归的概念。我们了解到递归是一种通过函数调用自身来解决问题的方法,它包含一个关键的基线条件来终止循环。我们通过俄罗斯套娃和排队的例子直观地理解了递归,并通过阶乘函数的代码示例看到了它的具体实现。

下一节,我们将探讨更多关于何时使用递归以及何时最好避免使用它的例子。
046:在IT背景下的递归实践 🧠

在本节课中,我们将学习递归函数在IT自动化任务中的实际应用。我们将探讨为什么在某些场景下,递归比循环更合适,并通过具体的IT示例来理解其工作原理。
什么是递归函数?
上一节我们介绍了递归函数的基本概念,包括如何编写基线条件和递归条件。现在,我们来看看为什么在特定情况下,递归函数比for或while循环更有效。
某些特定问题的解决方案,在使用递归函数时更易于编写和理解。许多数学函数,如阶乘或前所有数字之和,就是很好的例子。如果一个数学函数已经用递归术语定义,那么将其代码编写为递归函数就非常直接。
递归在IT自动化中的应用
递归不仅限于数学函数。让我们通过几个例子,看看它如何帮助IT专家自动化任务。
示例一:统计目录中的文件数量
假设你需要编写一个工具,遍历计算机中的一系列目录,并计算每个目录中包含的文件数量。在列出目录中的文件时,你可能会发现其中包含子目录,并且你希望同时统计这些子目录中的文件。
这时使用递归非常合适。基线条件是一个没有子目录的目录。对于这种情况,函数只需返回文件数量。
递归条件则是为每个包含的子目录调用递归函数。给定函数调用的返回值将是该目录中的所有文件数量,加上所有包含的子目录中的文件数量。
一个可以包含其他目录的文件目录是递归结构的一个例子,因为目录可以包含子目录,子目录又可以包含更多子目录,依此类推。
当对递归结构进行操作时,通常使用递归函数比for或while循环更容易。

以下是该逻辑的简化代码描述:
def count_files(directory):
total = 0
# 统计当前目录的直接文件
total += len(list_files_in_current_dir(directory))
# 遍历所有子目录并递归调用
for subdirectory in list_subdirectories(directory):
total += count_files(subdirectory) # 递归调用
return total
示例二:管理嵌套用户组
另一个IT领域的递归结构示例是处理可以包含其他组的用户组。在使用Active Directory或LDAP等管理工具时,我们经常遇到这种情况。
假设你的组管理软件允许你创建同时包含用户和其他组作为成员的组,并且你想要列出属于给定组的所有真实用户。
在这里,你可以使用递归函数来遍历这些组。基线条件是一个只包含用户的组,列出所有用户。
递归条件意味着遍历所有包含的组,列出其中的所有用户,然后列出当前组中包含的任何用户。
以下是该逻辑的简化代码描述:
def list_all_users(group):
users = []
# 添加当前组的直接用户
users.extend(get_direct_users(group))
# 遍历所有子组并递归调用
for subgroup in get_subgroups(group):
users.extend(list_all_users(subgroup)) # 递归调用
return users
递归的限制与注意事项
需要指出的是,在某些语言中,递归调用的次数是有限制的。在Python中,默认情况下,你可以递归调用一个函数1000次,直到达到限制。
这对于像子目录或用户组这样嵌套深度不会达到数千层的情况来说是可以的,但对于我们在上一个视频中看到的数学函数来说,可能就不够了。
让我们回到上一个视频中的阶乘例子,尝试用n=1000来调用它。
factorial(1000)

你会看到一个错误,它告诉我们已经达到了递归调用的最大限制。因此,虽然你可以在许多不同场景中使用递归,但我们只建议在你需要遍历一个不会达到1000层嵌套的递归结构时使用它。
总结
本节课中,我们一起学习了递归在IT自动化中的实际应用。我们探讨了递归为何适合处理像目录树和嵌套用户组这样的递归结构,并通过具体示例理解了其实现方式。同时,我们也了解了Python中递归深度的默认限制,明确了其适用的场景。现在,递归已成为你不断增长的脚本工具箱中的一员,在需要时可以随时使用。
047:Python循环总结 🎯
在本节课中,我们将要学习Python中用于执行重复任务的三种主要方法:while循环、for循环和递归。我们将回顾每种方法的核心概念、适用场景,并帮助你理解如何在实际编程中选择合适的工具。

我们已经走过了很长的学习路程,你已经掌握了很多知识。
现在是一个很好的时机,停下来给自己一个大大的鼓励。在这个模块中,我们研究了可以用来告诉计算机重复执行操作的方法。
Python为我们提供了三种不同的方式来执行重复任务:while循环、for循环和递归。
while循环 🔄
上一节我们介绍了循环的概念,本节中我们来看看第一种循环方式。
当希望在某个条件为真时持续执行一个操作,或者直到该条件变为假时停止,我们使用while循环。
以下是while循环的基本语法结构:
while condition:
# 要重复执行的代码块
for循环 📊
接下来,我们看看第二种循环方式。
当我们想要遍历一个序列(如列表、字符串)的元素或一个数字范围时,我们使用for循环。
以下是for循环的基本语法结构:

for element in sequence:
# 对每个元素执行的代码块
递归 🧩
最后,我们探讨第三种实现重复操作的方法:递归。
当一个问题最适合通过分解为更小的步骤来解决,然后将这些步骤组合起来形成更大的解决方案时,我们使用递归。
递归的核心是一个函数调用自身。以下是递归函数的基本结构:
def recursive_function(parameters):
if base_case_condition: # 基线条件
return base_case_value
else: # 递归条件
return recursive_function(modified_parameters)
如果你仍然不确定针对特定问题应该选择哪种最佳工具,请不要担心,这很正常。
随着你不断练习和提升自动化技能,在不同选项之间做出选择将变得自然而然。
因此,下次当你发现自己一遍又一遍地做相同或类似的事情时,那就是一个信号,提醒你看看是否可以使用循环来让计算机为你完成这项工作。
接下来,又是测试时间,我们将进行下一个分级评估。和往常一样,请记住,你可以在参加评估前花费任意多的时间。按照自己的节奏进行,复习我们涵盖的所有内容并练习示例。
这样,循环就绝不会让你感到困惑。
本节课中我们一起学习了Python中实现重复操作的三种核心方法:while循环、for循环和递归。我们了解了每种方法的适用场景和基本语法,并强调了通过练习来培养选择合适工具的能力。掌握这些循环结构是自动化任务和构建高效程序的关键一步。
048:个人经历分享与启示 🚀

在本节课中,我们将通过一位经验丰富的IT专业人士的个人经历,了解如何从零开始进入编程领域,并探索在IT行业中持续学习和成长的重要性。我们将重点分析其学习路径、职业转折点以及面对挑战的态度。
我是四个兄弟姐妹中最小的。我的家庭一直有互相分享热情的文化。因此,当我还是个孩子时,我的一个哥哥把一台电脑带回了家。他鼓励我摆弄电脑,参与在线网络。我开始编码并操作电脑,这让我非常兴奋。
小时候我用电脑做的一件事是让它运行一个简单的文本游戏,类似于那种“选择你自己的冒险”书籍,但是以电脑文本游戏的形式呈现。它非常简单,但这让我对能让电脑按照我的意愿行事感到非常兴奋。
我在阿根廷学习电子工程。我没有学习计算机科学。我在业余时间自学了编程。但我后来一直从事IT行业的工作,从未担任过电子工程师。
我的第一份工作是IT支持专家,但这纯属偶然。我得到这份工作只是因为一个朋友打电话给我,问我是否认识能为一家小公司提供支持的人,这家公司正在寻找能帮助其IT员工的人。
我说,是的,我可以做那个人。我唯一的背景就是为我的家庭和家用电脑提供过IT支持,比如我母亲的电脑。我没有接受过正规教育,也没有接受过IT支持的正式培训。但我觉得我能胜任这份工作,所以我接受了。我在那份工作中学到了很多。
之后我继续学习更多技能。我学习了如何真正地编程,而不仅仅是制作文本游戏。最终,我找到了另一份软件开发商的工作。我不断学习,学习新的编程语言、新技术、新框架。因此,我一直在不断拓展我的视野,因为总的来说,我对编程充满热情。
我已经在谷歌工作了七年。我来自阿根廷,但七年前搬到了德国。回顾我的IT职业生涯,我不会说我遇到了巨大的障碍。我更多地将它们视为成长的机会。
所以,如果我需要学习一门新的编程语言,或者需要学习新技术,它们都是我成长的机会。
上一节我们分享了进入编程领域的个人经历和初期探索。本节中,我们来看看从这段经历中可以提炼出的关键步骤和心态,这对于初学者规划自己的路径非常有帮助。
以下是基于个人经历总结出的进入IT领域的几个关键阶段:
- 兴趣启蒙与早期实践:通过家庭环境接触电脑,在鼓励下开始“摆弄”并尝试简单编程(如制作文本游戏)。核心在于动手尝试,即使项目很简单(例如一个基于文本的
choose-your-own-adventure游戏)。 - 非科班背景下的自学:专业是电子工程,但通过业余时间自学编程。这证明了正式计算机科学学位并非进入行业的唯一途径。
- 抓住偶然的入门机会:第一份IT支持工作来自偶然推荐。关键在于自信地抓住机会,即使只有非正式的经验(如解决家庭电脑问题)。
- 在实践中学习与转型:在IT支持工作中“学到了很多”,然后主动学习更高级的技能(“学习如何真正地编程”),从而实现向软件开发者角色的转型。
- 持续学习与拓展视野:职业生涯中不断学习新语言、技术和框架(例如学习
new programming languages, new techniques, new frameworks)。将学习新事物视为成长机会而非障碍。
本节课中我们一起学习了如何从个人兴趣出发,通过自学和实践进入编程世界,并抓住职业发展机会。我们了解到,即使没有相关专业背景,通过主动学习和勇于尝试,也能在IT领域找到自己的位置。最重要的是保持热情,并将每一个新挑战视为拓展技能和视野的成长机会。
049:Python基础数据结构介绍 🧱

在本节课中,我们将要学习Python中几种核心的数据结构:字符串、列表和字典。掌握这些结构是编写自动化脚本的关键,它们能帮助我们更高效地组织和处理数据。
欢迎回来。祝贺你坚持学习到这里。
我很高兴你没有在上一个模块关于循环的内容中掉队。
你做得很好,取得了巨大的进步。在之前的视频中,我们介绍了Python语法的基本要素。我们讨论了如何定义函数。

如何让计算机根据条件执行不同的操作?
以及如何使用while循环、for循环和递归让它重复执行操作。
既然我们已经掌握了语法基础,现在可以开始扩展我们的Python知识了,这将让我们能够执行越来越多有趣的操作。
请记住,本课程的主要目标之一是帮助你学会编写能自动执行操作的简短Python脚本。你已经朝着这个目标迈出了一大步。
在接下来的视频中,我们将学习一系列新的、超级有用的技能,以丰富你的编程工具箱。
我们将探索Python语言提供的一些数据类型,以帮助我们解决脚本中的常见问题。
具体来说,我们将深入探讨字符串、列表和字典。
虽然我们已经在脚本中使用过字符串,但我们仅仅触及了在Python中利用它们所能做的事情的表面。
我们也在一些例子中遇到过列表,但还有很多关于列表的内容我们尚未了解。
而字典对我们来说是一个全新的、值得深入钻研的数据类型。
这些都是超级灵活的数据类型或数据结构。
我们将使用它们来编写各种Python脚本。
因此,花些时间了解它们,学习何时使用它们以及如何最大限度地利用它们,是一个好主意。
我们有许多新的、令人兴奋的概念要去发现。那么,让我们直接开始吧。
050:Python字符串基础入门 🧵

概述
在本节课中,我们将要学习Python编程语言中的字符串数据类型。字符串是用于表示文本数据的基本类型,在IT自动化脚本中处理文件名、用户信息、配置内容等都离不开它。我们将从字符串的基本定义开始,逐步了解其特性和常见操作。
什么是字符串?🤔
到目前为止,我们已经在很多示例中使用过字符串,但尚未详细探讨它们。
在深入细节之前,我们先回顾一下目前所学的知识,并补充几点。
首先,快速回顾一下。字符串是Python中用于表示一段文本的数据类型。
它写在引号之间,可以是双引号,也可以是单引号,由你选择。
使用哪种引号并不重要,只要它们匹配即可。
如果我们混淆了双引号和单引号,Python会报错,返回一个语法错误,提示无法找到字符串的结尾。

字符串可以短至零个字符,通常称为空字符串。也可以非常长。
我们还学习了可以使用加号来组合字符串以构建更长的字符串,这个操作称为拼接。
一个不太常见的操作是将字符串乘以一个数字,这会将字符串的内容重复相应的次数,如下所示:
"Ha" * 3
# 结果是:'HaHaHa'
如果我们想知道一个字符串的长度,可以使用len()函数,我们在之前的视频中见过。len()函数会告诉我们字符串中包含的字符数。
字符串的用途 📝
我们可以用字符串来表示许多不同的事物。
它们可以保存用户名、机器名、电子邮件地址、文件名以及任何其他文本。
我们将要交互的很多数据都将以字符串形式存储。因此,了解如何使用它们非常重要。
在我们的脚本中,可以对字符串进行大量操作。
以下是几个具体的应用场景:
- 检查文件名:通过查看文件名,检查它们是否符合我们的命名规范。
- 创建电子邮件列表:通过检查系统用户并拼接上我们的域名来生成。
- 处理文件内容:文本文件的内容也是字符串。例如,将一批配置文件中的默认值从“true”替换为“false”。
你可以想到更多代码需要处理字符串的例子。但为了有效地使用字符串,我们需要了解Python中提供了哪些可用的操作。
在接下来的几节中,我们将介绍一些可以对字符串执行的操作,包括如何访问其部分内容以及如何修改它们。
总结
本节课中,我们一起学习了Python字符串的基础知识。我们明确了字符串是用于表示文本的数据类型,可以使用单引号或双引号定义。我们回顾了字符串拼接和重复乘法等基本操作,并了解了len()函数用于获取字符串长度。最后,我们探讨了字符串在IT自动化中的实际应用场景,例如处理文件名和文件内容,为后续深入学习字符串操作打下了基础。
051:字符串的组成部分 🧵

在本节课中,我们将要学习Python中字符串的基本组成部分,包括如何访问单个字符、使用切片获取子字符串,以及理解索引的工作原理。这些技能对于处理文本数据至关重要。
字符串索引:访问特定字符 🔍
上一节我们介绍了使用for循环遍历字符串。本节中我们来看看如何访问字符串中的特定字符。
例如,当文本过长需要截取部分显示,或需要提取短语中每个单词的首字母制作缩写时,我们可以使用字符串索引操作。该操作使用方括号和位置编号访问给定位置或索引的字符。
示例:string[0]
初次尝试可能会令人困惑。我们请求第一个字符,但得到的是第二个字符。这是因为Python从0开始计数索引,与range函数的行为一致。因此,要访问第一个字符,需要使用索引0。
了解索引从0开始后,字符串的最后一个索引始终是字符串长度减一。例如,一个长度为6的字符串,其最后一个索引是5。尝试访问超出范围的索引(如索引6)将引发“索引超出范围”错误。
若想打印字符串的最后一个字符但不知道其长度,可以使用负索引。负索引允许从字符串末尾开始访问位置。
示例:string[-1]
字符串切片:获取子字符串 ✂️

除了访问单个字符,我们还可以访问字符串的切片。切片是包含多个字符的字符串部分,有时也称为子字符串。

我们通过使用冒号作为分隔符创建范围来实现切片。
示例:string[1:4]
用于访问字符串切片的范围与range函数创建的范围类似:包含起始数字,但不包含结束数字(结束数字减一)。例如,string[1:4]从索引1(字符串的第二个字母)开始,到索引3(字符串的第四个字母)结束。
范围还可以只包含两个索引中的一个。在这种情况下,未指定的索引默认为0(起始值)或字符串长度(结束值)。
以下是切片操作的示例:
- 从起始到索引4:获取字符串的前四个字符(索引0到3)。
- 从索引4到结束:获取从索引4开始的所有字符。

总结与练习建议 📚
本节课中我们一起学习了字符串索引和切片的核心概念。所有索引操作起初可能令人困惑,但通过持续练习可以掌握。后续课程提供了大量练习来帮助巩固这些技能。
现在我们已经知道如何选择、切片和访问所需的字符串部分,接下来将学习如何修改它们。
052:Python字符串操作基础(第51课)🔤

在本节课中,我们将要学习Python中字符串的基本操作,包括如何访问和修改字符串中的字符,以及如何使用一些内置方法来处理字符串。我们还会通过一个实际的例子来巩固所学知识。
字符串的不可变性 🔒
上一节我们介绍了如何访问字符串中的特定字符。本节中我们来看看如何修改它们。
想象你有一个字符串,其中包含一个错误的字符,你想要修正它。考虑到你学过的字符串索引知识,你可能会尝试通过访问相应的索引来修改字符。
让我们看看如果尝试这样做会发生什么。
message = "Hello, World!"
message[7] = 'w'
输出:
TypeError: 'str' object does not support item assignment
在这种情况下,我们被告知字符串不支持项赋值。这意味着我们不能更改单个字符,因为Python中的字符串是不可变的。
“不可变”只是一个花哨的词汇,意味着它们不能被修改。
我们可以做的是基于旧字符串创建一个新字符串,像这样:
message = "Hello, World!"
new_message = message[:7] + 'w' + message[8:]
print(new_message)
输出:
Hello, world!
很好,我们修正了拼写错误。
但这意味着message变量永远不能改变吗?并非如此。我们可以为同一个变量分配一个新值。让我们这样做几次来看看它是如何工作的。
message = "Hello, World!"
message = "Hello, world!"
message = "Hello, Python!"
我们在这里做的是给message变量一个全新的值。我们并没有改变之前分配给它的底层字符串。我们分配了一个具有不同内容的全新字符串。
如果这看起来有点复杂,没关系。你现在不需要担心这个。每当我们编写的程序与此相关时,我们都会指出来。
查找字符位置 🔍
我们弄清楚了如何从旧消息创建新消息。但我们如何知道要更改哪个字符呢?让我们尝试一些不同的方法。
message = "Hello, World!"
index = message.index('W')
print(index)
输出:
7
在这种情况下,我们使用一个方法来获取某个字符的索引。
方法是一个与特定类关联的函数。我们稍后会更多地讨论类和方法。现在,你需要知道的是,这是一个应用于变量的函数,我们可以通过在变量后面加一个点来调用它。
让我们再试几次。
message = "Hello, World!"
print(message.index('o'))
print(message.index('World'))
输出:
4
7
index方法返回给定子字符串在字符串中的索引。我们传递的子字符串可以任意长或短。
如果子字符串不止一个呢?
message = "Mississippi"
print(message.index('s'))
输出:
2
这里我们知道有两个's'字符,但我们只得到一个值。这是因为index方法只返回第一个匹配的位置。
如果字符串中没有我们要找的子字符串会发生什么?
message = "Hello, World!"
print(message.index('z'))
输出:
ValueError: substring not found
index方法无法返回一个数字,因为子字符串不存在。所以我们得到一个值错误。
检查子字符串是否存在 ✅
我们说如果子字符串不存在,我们会得到一个错误。那么我们如何知道一个子字符串是否包含在字符串中以避免错误呢?让我们来看看。
我们可以使用关键字in来检查子字符串是否包含在字符串中。
我们在使用for循环时遇到过关键字in。在那种情况下,它用于迭代。在这里,它是一个条件,可以是真或假。
如果子字符串是字符串的一部分,则为真;如果不是,则为假。
message = "Hello, World!"
print('World' in message)
print('Python' in message)
输出:
True
False
所以在这里,'dragon'这个子字符串不是字符串的一部分。遗憾的是,我们不能养龙作为宠物。
实践:更新电子邮件域名 📧
我们刚刚涵盖了一堆新内容,你做得非常棒。让我们把所有这些东西放在一起来解决一个现实世界的问题。
想象一下,你的公司最近开始使用一个新域名,但公司很多电子邮件地址仍然在使用旧域名。你想编写一个程序,在任何过时的电子邮件地址中将旧域名替换为新域名。
替换域名的函数如下所示:
def replace_domain(email, old_domain, new_domain):
if "@" + old_domain in email:
index = email.index("@" + old_domain)
new_email = email[:index] + "@" + new_domain
return new_email
return email
这个函数比其他函数复杂一些。所以让我们逐行分析。
首先,我们定义replace_domain函数,它接受三个参数:要检查的电子邮件地址、旧域名和新域名。
将所有值作为参数而不是直接放在代码中,使我们的函数可重用。我们不仅仅是更改一个域名为另一个。我们有一个适用于所有域名的函数。非常棒。
在函数体的第一行,我们使用关键字in检查电子邮件地址中是否包含“@”符号和旧域名的连接。
我们检查这个是为了确保电子邮件在“@”符号后面的部分包含旧域名。
如果条件为真,则需要更新电子邮件地址。为此,我们首先找出旧域名(包括“@”符号)开始的索引。
我们知道这个索引将是一个有效的数字,因为我们已经检查了子字符串存在。

因此,使用这个索引,我们创建新的电子邮件。这是一个字符串,包含旧电子邮件直到我们计算出的索引的第一部分,然后是“@”符号和新域名。
最后,我们返回这个新电子邮件。
如果电子邮件不包含新域名,那么我们可以直接返回它,这就是我们在最后一行所做的。
总结 📝
本节课中我们一起学习了Python字符串的基本操作。我们了解到字符串是不可变的,这意味着不能直接修改其中的字符,但可以通过创建新字符串来实现修改。我们学习了如何使用index()方法查找子字符串的位置,以及如何使用in关键字检查子字符串是否存在。最后,我们通过一个更新电子邮件域名的实际例子,将所学知识综合应用,解决了实际问题。
这些概念是处理文本数据的基础,在后续的编程工作中会经常用到。如果你觉得某些部分有难度,可以重新观看视频或向学习社区寻求帮助。当你准备好继续前进时,我们将在下一个视频中学习更多方便的字符串方法。
053:Python字符串进阶操作 🧵

课程编号:P53
在本节课中,我们将要学习更多用于处理和转换字符串的Python方法。我们将探索如何改变字符串的大小写、清理用户输入、获取字符串信息,以及如何拆分和连接字符串。
我们之前提到过,有许多令人兴奋的新概念即将到来。现在,我们将通过一系列有趣的方法来结束关于字符串的课程,这些方法可以转换我们的字符串文本。
到目前为止,我们已经学习了使用索引技术访问字符串部分的方法,通过切片和连接创建新字符串,使用index方法查找字符串中的字符,甚至测试一个字符串是否包含另一个字符串。除了这些强大的字符串处理功能外,str类还提供了许多其他处理文本的方法。
现在,我们将展示如何使用其中一些方法。请记住,目标不是让你记住所有内容,而是让你了解在Python中可以用字符串做什么。
字符串转换与格式化方法
一些字符串方法允许你对字符串文本执行转换或格式化操作,例如upper()及其相反的方法lower()。
以下是几个关键方法及其用法:
str.upper(): 将字符串中的所有字符转换为大写。text = "Hello World" print(text.upper()) # 输出: HELLO WORLDstr.lower(): 将字符串中的所有字符转换为小写。text = "Hello World" print(text.lower()) # 输出: hello world
在处理用户输入时,这些方法非常有用。假设你想检查用户对某个问题的回答是否为“yes”,你无需关心用户输入的是大写还是小写,只需将答案转换为你想要的格式即可。
清理用户输入
另一个处理用户输入时非常有用的方法是strip()。此方法会去除字符串周围(开头和结尾)的空格。
如果我们向用户询问答案,通常不关心任何周围的空格。因此,使用strip()方法去除任何空白字符是一个好主意。
以下是相关方法:
str.strip(): 移除字符串开头和结尾的空白字符(包括空格、制表符\t、换行符\n)。user_input = " yes \n" print(user_input.strip()) # 输出: "yes"str.lstrip(): 仅移除字符串开头(左侧)的空白字符。str.rstrip(): 仅移除字符串结尾(右侧)的空白字符。
这意味着strip()不仅移除空格,还移除制表符和换行符,这些通常是我们不希望出现在用户提供的字符串中的字符。
获取字符串信息
其他方法可以为你提供关于字符串本身的信息。
以下是几个用于检查字符串内容的方法:
str.count(substring): 返回给定子字符串在字符串中出现的次数。sentence = "She sells seashells by the seashore." print(sentence.count("sea")) # 输出: 2str.endswith(substring): 返回字符串是否以某个子字符串结尾。filename = "document.pdf" print(filename.endswith(".pdf")) # 输出: Truestr.isnumeric(): 返回字符串是否仅由数字组成。num_str = "12345" print(num_str.isnumeric()) # 输出: True
补充一点,如果我们有一个由数字组成的字符串,可以使用int()函数将其转换为实际的整数。
字符串的拆分与连接
在之前的视频中,我们展示了可以使用加号+来连接字符串。
join()方法也可用于连接字符串。要使用join()方法,必须在将用于连接的字符串上调用它。该方法接收一个字符串列表,并返回一个字符串,其中列表中的每个字符串都由初始字符串连接起来。
让我们看一个例子:

words = ["Hello", "world", "from", "Python"]
separator = " "
result = separator.join(words)
print(result) # 输出: Hello world from Python
最后,我们也可以将一个字符串拆分成一个字符串列表。split()方法返回初始字符串中所有单词组成的列表,它会自动按任何空白字符进行拆分。它可以选择性地接受一个参数,按另一个字符(如逗号或点)来拆分字符串。
data = "apple,banana,cherry"
items = data.split(",")
print(items) # 输出: ['apple', 'banana', 'cherry']
你是否开始看到这些字符串方法在你的IT工作中可能很有用?好的,我们刚刚学习了一堆新方法,但还有更多可以用于字符串的方法。我们在下一份速查表中包含了我们讨论过的方法和一些新方法。
你还会在那里找到完整Python文档的链接,它提供了每个可用方法的所有信息。正如我们之前所说,不要担心试图记住所有内容。通过练习,你会掌握这些概念。文档总是在那里,如果你需要的话。
在本节课中,我们一起学习了多种处理字符串的Python方法。我们了解了如何转换字符串的大小写以规范化用户输入,如何使用strip()系列方法清理字符串两端的空白字符,以及如何使用count()、endswith()和isnumeric()等方法获取字符串的特定信息。最后,我们探索了如何使用join()方法连接字符串列表,以及如何使用split()方法将字符串拆分为列表。掌握这些方法将极大地增强你处理和操作文本数据的能力。
054:Python字符串格式化 📝

概述
在本节课中,我们将要学习Python中一种更优雅、更强大的字符串构建方法:使用format()方法进行字符串格式化。我们将逐步了解其基本用法、高级特性,以及如何利用它来美化程序输出和生成清晰的日志信息。
从拼接字符串到格式化字符串
上一节我们介绍了使用加号(+)拼接字符串和使用str()函数转换数字的方法。这种方法虽然可行,但在处理复杂字符串时并不理想。
本节中我们来看看如何使用format()方法更高效地构建字符串。
基本用法示例:
name = "Mikel"
number = 42
message = "Hello {}! Your number is {}.".format(name, number)
print(message)
# 输出:Hello Mikel! Your number is 42.
在上面的代码中,我们使用花括号{}作为占位符,然后通过format()方法将变量name和number依次填入。format()方法会自动处理字符串和整数等不同类型的数据,我们无需手动转换。
使用命名占位符提高可读性
为了使格式化字符串更具可读性,尤其是在文本可能被重写或翻译、变量顺序可能改变的情况下,我们可以在花括号内使用变量名作为占位符。
以下是使用命名占位符的方法:
message = "Hello {name}! Your number is {num}.".format(name="Mikel", num=42)
print(message)
# 输出:Hello Mikel! Your number is 42.
使用这种方式时,传递给format()方法的参数顺序不再重要,只需确保参数名与占位符名称匹配即可。
格式化数字输出
format()方法的功能远不止于此。我们接下来看看如何格式化数字,例如控制小数位数。
假设我们需要计算含税价格,并希望结果只显示两位小数。
控制小数位数示例:
price = 7.5
tax_rate = 0.09
price_with_tax = price * (1 + tax_rate) # 结果为 8.175
formatted_price = "The price with tax is ${:.2f}.".format(price_with_tax)
print(formatted_price)
# 输出:The price with tax is $8.18.
在{:.2f}这个格式化表达式中,冒号:后面是格式说明。.2f表示将数字格式化为浮点数(f),并保留两位小数(.2)。
美化输出:对齐与格式化
还记得我们在华氏度与摄氏度转换表中,输出因过多小数位而显得杂乱吗?使用format()方法可以轻松解决这个问题。
对齐与格式化示例:
# 假设我们有两个温度值
f_temp = 98.6
c_temp = (f_temp - 32) * 5/9 # 计算结果约为 37.0
# 使用格式化使其对齐美观
print("{:>3.0f} degrees Fahrenheit is {:>6.2f} degrees Celsius.".format(f_temp, c_temp))
# 输出: 99 degrees Fahrenheit is 37.00 degrees Celsius.
以下是表达式的含义:
{:>3.0f}:将第一个数字(f_temp)格式化为整数(.0f),并右对齐(>)在总共3个字符的宽度内。{:>6.2f}:将第二个数字(c_temp)格式化为保留两位小数的浮点数(.2f),并右对齐(>)在总共6个字符的宽度内。
通过这种方式,我们可以让程序的输出看起来更整齐、更专业,同时也能生成更有用的日志和调试信息。

总结
本节课中我们一起学习了Python中format()方法的核心用法。我们从基本的占位符替换开始,逐步深入到使用命名参数、控制数字格式(如小数位数)以及对齐文本输出。
记住,字符串格式化是一个强大的工具,它能让你的代码更简洁,输出更美观。无需一次性记住所有格式规则,在实践中遇到时查阅即可。在后续课程中,我们也会在需要时解释新的格式化选项,并为你提供速查表以供参考。
055:什么是列表?📚

在本节课中,我们将要学习Python中一个非常重要的数据结构——列表。列表允许我们存储和操作一组有序的元素,这在处理如文件名集合、网络数据包大小等场景时非常有用。
概述
正如我们所知,Python提供了许多现成的数据类型。我们已经详细了解了整数、浮点数、布尔值和字符串,但这些数据类型的功能有限。最终,在我们的脚本中,我们需要编写能够操作项目集合的代码,例如代表目录中所有文件名的字符串列表,或代表网络数据包大小的整数列表。这时,列表数据类型就派上用场了。
你可以将列表想象成一个长盒子,盒子内部的空间被划分成不同的槽位。每个槽位可以包含一个不同的值。
创建与查看列表
与之前首次接触Python列表时提到的一样,我们使用方括号来指示列表的开始和结束。让我们看一个例子。

x = ["a", "b", "c", "d"]
这里我们创建了一个名为x的新变量,并将其内容设置为一个字符串列表。我们可以使用之前见过的type函数来检查x的类型。
print(type(x)) # 输出:<class 'list'>
很好,Python告诉我们这是一个列表。与其他变量一样,我们可以使用print函数显示整个列表的内容。
print(x) # 输出:['a', 'b', 'c', 'd']
列表长度与成员检查
列表的长度是指它包含多少个元素。要获取这个值,我们将使用与字符串相同的len函数。
print(len(x)) # 输出:4
没错,我们的列表有四个元素。当为列表调用len时,每个字符串本身有多长并不重要,重要的是列表有多少个元素。
要检查列表是否包含某个特定元素,可以使用关键字in,如下例所示。
print("a" in x) # 输出:True
print("e" in x) # 输出:False
同样,就像我们将其用于字符串时一样,此检查的结果是一个布尔值,我们可以将其用作分支或循环的条件。
索引与切片
我们还可以使用索引来访问单个元素,具体取决于它们在列表中的位置。为此,我们使用方括号和我们想要访问的索引,就像对字符串所做的那样。
print(x[0]) # 输出:'a'
print(x[1]) # 输出:'b'
请记住,第一个元素的索引是0。这意味着列表的最后一个索引将是列表长度减1。
print(x[len(x) - 1]) # 输出:'d'

如果我们尝试访问列表末尾之后的元素会发生什么?
你可能已经预料到了。我们会得到一个索引错误。我们不能超出列表的末尾。

# print(x[4]) # 这将引发 IndexError: list index out of range
记住,因为列表索引从0开始,访问索引4处的项目意味着我们试图访问列表中的第五个元素。列表中只有四个元素,所以如果我们尝试访问索引号4,就超出了范围。
如果这看起来有点令人困惑,下面的可视化图示可能会帮助你理解。正如你所见,索引4没有指向任何东西,因为我们的列表中没有槽位4。
与字符串类似,我们也可以使用索引来创建列表的切片。为此,我们使用由冒号分隔的两个数字范围。同样,第二个元素不包含在切片中。所以范围是到第二个索引减1。

print(x[1:3]) # 输出:['b', 'c']
这里我们从索引1开始,一直到小于3的值,即2。我们也可以将范围索引之一留空。第一个值默认为0,第二个值默认为列表的长度。
print(x[:2]) # 输出:['a', 'b']
print(x[2:]) # 输出:['c', 'd']
列表与序列
如果所有这些听起来与我们之前关于字符串的讲解非常相似,那么本课程的目的就达到了。这是因为在Python中,字符串和列表是非常相似的数据类型。字符串和列表都是序列的例子。还有其他序列类型,它们都共享一系列操作,例如使用for循环进行迭代、使用索引、使用len函数获取序列长度、使用加号连接两个序列以及使用in来验证序列是否包含某个元素。
所以这是个好消息:理解索引虽然困难,但一旦你掌握了一种数据类型的索引,你几乎就掌握了所有数据类型的索引。所以你实际上知道的比你想象的要多得多。
总结
本节课中我们一起学习了Python列表的基础知识。我们了解了如何创建列表、检查其长度和成员、使用索引访问元素以及创建切片。我们还认识到列表是序列的一种,与字符串共享许多操作特性。掌握了这些,你就为学习更多列表特有的操作打下了坚实的基础。
接下来,我们将学习一些更多专门针对列表的操作。
056:修改列表内容 📝

在本节课中,我们将要学习如何修改Python列表的内容。列表与字符串的一个重要区别在于列表是可变的,这意味着我们可以添加、移除或修改列表中的元素。想象列表是一个长盒子,修改列表就是保持盒子不变,但改变盒子里的物品。
列表与字符串的区别 🔄
上一节我们介绍了列表的基本概念,本节中我们来看看列表与字符串的一个关键区别:可变性。列表是可变的,而字符串是不可变的。这意味着列表的内容可以更改,而字符串一旦创建就不能修改。
修改列表的方法 🛠️

现在,我们将逐一介绍用于修改列表的方法。如果这些细节看起来有些多,不用担心。像往常一样,课程最后会有备忘单,并且我们会有很多机会练习这些方法。你不需要死记硬背,当然,你也可以随时复习任何不清楚的内容。
添加元素到列表
我们将从最简单的修改开始:使用append方法向列表添加元素。
以下是append方法的使用示例:
fruits = ["Pineapple", "Banana", "Apple", "Melon"]
fruits.append("Kiwi")
print(fruits) # 输出: ['Pineapple', 'Banana', 'Apple', 'Melon', 'Kiwi']
append方法在列表末尾添加一个新元素。无论列表多长,元素总是被添加到末尾。你可以从一个空列表开始,然后使用append添加所有项目。
如果希望在特定位置插入元素,而不是在末尾,可以使用insert方法。
以下是insert方法的使用示例:
fruits.insert(0, "Orange")
print(fruits) # 输出: ['Orange', 'Pineapple', 'Banana', 'Apple', 'Melon', 'Kiwi']
insert方法将第一个参数作为索引,第二个参数作为元素。它将元素添加到列表中的该索引位置。要将其添加为第一个元素,我们使用索引0。我们也可以使用任何其他数字。
如果使用的数字大于列表的长度,不会出现错误。元素只会被添加到末尾。通常,你会在开头使用索引0的insert,或在末尾使用append。
从列表中移除元素
我们可以根据要移除的元素值来移除列表中的元素。
以下是remove方法的使用示例:
fruits.remove("Banana")
print(fruits) # 输出: ['Orange', 'Pineapple', 'Apple', 'Melon', 'Kiwi']
remove方法从列表中移除我们传递给它的元素的第一个出现项。如果元素不在列表中,我们会得到一个值错误,告诉我们该元素不在列表中。
另一种移除元素的方法是使用pop方法,它接收一个索引。
以下是pop方法的使用示例:
removed_fruit = fruits.pop(3)
print(removed_fruit) # 输出: Melon
print(fruits) # 输出: ['Orange', 'Pineapple', 'Apple', 'Kiwi']
pop方法返回在传递的索引处被移除的元素。
修改列表中的元素
修改列表内容的最后一种方法是通过为该位置分配其他内容来更改项目。
以下是修改元素的示例:
fruits[2] = "Strawberry"
print(fruits) # 输出: ['Orange', 'Pineapple', 'Strawberry', 'Kiwi']
我们的fruits变量的内容自本视频开始以来已经改变了很多,但它始终是同一个变量,同一个盒子。我们只是修改了里面的内容。

列表修改的实际应用 💼
修改列表内容在我们操作列表时会出现在大量的脚本中。如果列表包含网络上的主机,你可以在主机上线或离线时添加或移除主机。如果列表包含被授权运行某个进程的用户,你可以在权限被授予或移除时添加或移除用户,等等。
总结 📚
本节课中我们一起学习了多种修改列表内容的方法,包括添加、移除和更改列表中存储的元素。每当你需要编写一个处理可变数量元素的程序时,你都会使用列表。如果你需要一个固定数量元素的序列,我们将在下一个视频中介绍。
057:Python中的列表与元组 🧩

概述
在本节课中,我们将要学习Python中的两种重要序列数据类型:列表(List)和元组(Tuple)。我们将了解它们的定义、特性、区别以及各自适用的场景,帮助你理解何时该使用列表,何时该使用元组。

序列数据类型简介
正如之前提到的,Python中有多种数据类型属于序列。字符串(Str)是字符的序列,并且是不可变的。列表(List)是任意类型元素的序列,并且是可变的。
什么是元组? 🤔
第三种序列数据类型,与列表密切相关,就是元组(Tuple)。元组是任意类型元素的序列,但它是不可变的。我们使用圆括号 () 来定义元组,而不是方括号 []。
你可能会想,既然列表已经很好了,为什么我们还需要另一种序列类型?是的,列表非常强大。它们可以容纳任意数量的元素,并且我们可以随意添加、删除和修改其内容。
但是,在某些情况下,我们希望确保某个特定位置或索引的元素指向一个特定的事物并且不会改变。在这些情况下,列表就无法帮助我们了。
元组的含义与不可变性
在我们的例子中,有一个表示某人全名的元组。元组的第一个元素是名字,第二个元素是中间名首字母,第三个元素是姓氏。
如果我们在其中任意位置添加另一个元素,那么这个元素代表什么呢?这只会造成混淆,我们的代码也不知道该如何处理它。这就是为什么不允许修改元组。
换句话说,当使用元组时,元素在元组内的位置具有特定的含义。

元组的常见用途
元组在Python中有许多不同的用途。一个常见的例子是函数的返回值。当一个函数返回多个值时,它实际上返回的是一个元组。

还记得我们之前看到的将秒数转换为小时、分钟和秒的函数吗?这里再次展示以作提醒:
def convert_seconds(seconds):
hours = seconds // 3600
minutes = (seconds - hours * 3600) // 60
remaining_seconds = seconds - hours * 3600 - minutes * 60
return hours, minutes, remaining_seconds
这个函数返回三个值。换句话说,它返回一个包含三个元素的元组。让我们尝试一下:
result = convert_seconds(5000)
print(type(result)) # 输出: <class 'tuple'>
print(result) # 输出: (1, 23, 20)
我们看到结果是一个元组。打印它,可以看到它包含我们期望的三个元素。请记住,由于这是一个元组,顺序很重要:第一个元素代表小时,第二个代表分钟,第三个代表秒。
元组解包
我们可以对元组做一件有趣的事情,那就是解包(Unpack)。这意味着我们可以将一个包含三个元素的元组拆分成三个独立的变量。由于顺序不会改变,我们知道这些变量代表什么,就像这样:
hours, minutes, seconds = result
print(hours, minutes, seconds) # 输出: 1 23 20
现在,我们已经将元组拆分成了三个独立的值。我们之前也看到过,在调用函数时可以直接进行解包,而无需中间结果变量:
h, m, s = convert_seconds(5000)
在Python中,使用元组来表示具有多个值且需要保持在一起的数据是非常常见的。
元组的应用实例
例如,你可以使用一个元组来存储文件名及其大小,或者存储一个人的姓名和电子邮件地址,或者在某个时间点存储系统的日期、时间和总体健康状况。

你能看出这些不同的数据类型如何帮助你自动化一些IT工作吗?这很酷,对吧?
列表与元组的选择
起初,知道何时使用元组、何时使用列表可能有点模糊,但不用担心,随着我们处理更多的例子,这一点会变得更加清晰。
总结
本节课中,我们一起学习了Python中的列表和元组。我们了解到列表是可变的序列,使用方括号 [] 定义,适合存储需要频繁修改的数据集合。而元组是不可变的序列,使用圆括号 () 定义,适合用于表示固定的、有特定含义的数据组合(如函数的多返回值或记录结构)。理解它们的区别将帮助你在编程中做出更合适的数据结构选择。
058:遍历列表和元组 📚

在本节课中,我们将学习如何使用循环来遍历列表和元组,并探索一些实用的技巧,例如使用enumerate函数获取元素索引,以及如何安全地处理列表。
遍历列表 🔄
上一节我们介绍了循环的基本概念,本节中我们来看看如何用循环遍历列表。
我们创建一个动物列表,并计算所有动物名称的总字符数和平均长度。
animals = ["lion", "zebra", "dolphin", "monkey"]
chars = 0
for animal in animals:
chars += len(animal)
print("Total characters: {}, Average length: {}".format(chars, chars/len(animals)))
在这段代码中,我们遍历了一个字符串列表。对于每个字符串,我们获取其长度并将其添加到总字符数中。最后,我们打印出总数和平均值,平均值通过总数除以列表长度得到。
使用enumerate获取索引 🔢
如果你在遍历列表时想知道元素的索引,可以使用range函数并通过索引访问元素,或者直接使用enumerate函数。

以下是使用enumerate的示例:
winners = ["Ashley", "Dylan", "Reese"]
for index, person in enumerate(winners):
print("{} - {}".format(index + 1, person))
enumerate函数为列表中的每个元素返回一个元组。元组的第一个值是元素在序列中的索引,第二个值是序列中的元素本身。

实践:格式化电子邮件列表 📧
现在,我们利用所学知识解决一个稍复杂的问题。假设有一个包含元组的列表,每个元组有两个字符串:电子邮件地址和全名。我们需要编写一个函数,创建一个新列表,其中每个字符串包含姓名和用尖括号括起来的电子邮件地址。
以下是实现步骤:
首先,定义一个接收人员列表的函数。
def full_emails(people):
result = []
for email, name in people:
result.append("{} <{}>".format(name, email))
return result
然后,测试这个函数。
print(full_emails([("alex@example.com", "Alex Diego"),
("shay@example.com", "Shay Brandt")]))

常见错误与注意事项 ⚠️
由于我们经常在循环中使用range函数,你可能会想用它来遍历列表的索引,然后通过索引访问元素。如果你之前习惯其他编程语言,可能尤其倾向于这样做,因为在某些语言中,访问列表元素的唯一方式是使用索引。
这种方法虽然可行,但不够优雅。在Python中,更地道的做法是直接遍历列表元素,或者在需要索引时使用enumerate函数。
此外,如果你在遍历列表的同时修改它,需要格外小心。在迭代过程中删除元素可能导致意外结果。在这种情况下,最好使用列表的副本。
总结 📝
本节课中我们一起学习了如何遍历列表和元组,使用enumerate函数获取元素索引,以及如何安全地处理列表。列表是Python中非常强大的工具,掌握这些技巧将帮助你在IT自动化任务中更高效地处理数据。
接下来,我们将学习一种创建列表的强大技术。
059:Python列表推导式 🧠

概述
在本节课中,我们将要学习Python中一种高效创建列表的方法——列表推导式。我们将通过具体示例,了解其基本语法、应用场景以及如何结合条件语句使用。
列表推导式简介
上一节我们介绍了使用循环和append()方法创建列表。本节中我们来看看如何使用列表推导式更简洁地实现相同功能。
列表推导式允许我们基于序列或范围快速生成新列表。其基本语法模仿自然语言的表达方式,旨在使代码更简洁。
创建基于范围的列表

假设我们需要创建一个包含7到70之间7的倍数的列表。使用传统方法,代码如下:
multiples = []
for x in range(1, 11):
multiples.append(x * 7)
print(multiples)

使用列表推导式,我们可以将上述代码简化为一行:
multiples = [x * 7 for x in range(1, 11)]
print(multiples)
两种方法输出结果相同,但列表推导式使代码更加紧凑。
基于现有序列创建列表
列表推导式不仅适用于数字范围,也适用于任何Python序列,如列表、元组或字符串。
例如,我们有一个编程语言名称的列表,并希望生成一个包含各名称长度的新列表:
languages = ["Python", "Java", "C++", "JavaScript"]
lengths = [len(language) for language in languages]
print(lengths)
在列表推导式中使用条件
列表推导式允许我们添加条件语句,以过滤元素。
例如,生成0到100之间所有能被3整除的数字列表:
z = [x for x in range(0, 101) if x % 3 == 0]
print(z)

这里,if x % 3 == 0是一个条件子句,确保只有满足条件的x被包含在新列表中。
使用建议
在Python编程中使用列表推导式是可选的。有时它能使代码更清晰、更易读;但若试图在一行中塞入过多逻辑,也可能降低可读性。
总的来说,了解列表推导式是有益的,尤其是在阅读他人代码时。
总结
本节课中我们一起学习了Python列表推导式。我们了解了其基本语法,如何基于范围或序列创建列表,以及如何结合条件语句过滤元素。列表推导式是一种强大的工具,能帮助我们编写更简洁、高效的代码。
在接下来的阅读材料中,你将找到更多关于列表和元组操作的常见方法及官方文档链接。完成阅读后,你可以在随后的测验中练习新学到的技能。😊
060:Python列表推导式与for循环的选择指南 📘

在本节课中,我们将学习如何在Python中选择使用列表推导式或for循环。我们将回顾两者的基本概念,探讨它们各自的适用场景,并提供一些实用的决策指南。
回顾:列表推导式与for循环
上一节我们介绍了列表推导式和for循环的基本用法。本节中我们来看看如何在实际编程中选择使用它们。
for循环用于迭代一系列值,例如数字、字母等。其基本结构如下:
for item in sequence:
# 执行操作
列表推导式允许我们基于序列或范围创建新列表。它是构建新列表的一种简洁方式,基本结构如下:
new_list = [expression for item in sequence if condition]
列表推导式将for循环、条件判断和列表构建全部压缩在一行代码中完成。
何时使用列表推导式?何时使用for循环? 🤔
列表推导式和for循环功能相似,那么如何选择呢?简短的回答是:这取决于你的判断。两种方法本质上可以互换,没有严格的标准或最佳实践。选择使用列表推导式还是for循环完全由你决定。
尽管如此,许多程序员在决策时会考虑以下因素。
列表推导式的适用场景


程序员通常在代码较为简单时使用列表推导式,例如过滤列表以提取匹配项或将列表中的单词大写。如果代码可以放在一行内,那么使用列表推导式可能更合适。
以下是一个列表推导式的示例:
# 过滤出长度大于3的单词
words = ["cat", "window", "defenestrate"]
long_words = [word for word in words if len(word) > 3]
在这个例子中,列表推导式简洁地完成了过滤操作。
for循环的适用场景

对于更复杂的代码,通常建议使用for循环。for循环能更清晰地展示处理过程,使你和他人更容易阅读和维护代码。
例如,假设你在一家公司工作,需要维护一张发票列表。你需要计算列表中所有项目的销售税和应付余额,并首先更新逾期发票的状态。虽然可以用列表推导式完成,但代码会变得复杂且难以理解。
以下是使用列表推导式更新逾期发票状态的示例:
invoices = [...] # 假设这是一个发票对象列表
past_due = [i for i in invoices if i.age > 30 and not i.paid]
for j in past_due:
j.status = "Past Due"
在这个代码中,列表推导式用于筛选出逾期超过30天且未支付的发票,然后for循环更新这些发票的状态。虽然功能正确,但可读性较差。
for循环的清晰示例
相比之下,使用for循环可以使代码更直观:
for invoice in invoices:
if invoice.age > 30 and not invoice.paid:
invoice.status = "Past Due"
这段代码与之前的列表推导式示例结果相同,但更直接。它清晰地展示了每一步操作,便于编码和理解。

决策指南:如何选择? 🧭
回到最初的问题:何时使用for循环?何时使用列表推导式?以下是一些问题,可以帮助你做出决策:

- 哪种方法能使我的代码既清晰又简洁?
- 哪种方法能使其他人更容易阅读和理解我的代码?
记住,大多数开发者喜欢简短、精炼且切中要点的代码。无论选择哪种编码策略,请为所有变量、数据集和列表使用有意义的名称。始终假设其他人会阅读你的代码。
总结
本节课中我们一起学习了如何在列表推导式和for循环之间做出选择。我们回顾了两者的基本概念,探讨了它们各自的适用场景,并提供了一些实用的决策指南。现在你已经掌握了做出最佳决策所需的信息,可以继续深入Python学习,不断提升你的知识和技能。 😊
061:什么是字典 📚

概述
在本节课中,我们将要学习Python中的另一种重要数据结构——字典。我们将了解字典的基本概念、如何创建字典、如何访问和修改字典中的数据,以及它与之前学过的列表有何不同。
什么是字典? 🤔
上一节我们介绍了列表和字符串,它们是非常有用的工具。本节中我们来看看另一种数据类型:字典。
与列表类似,字典用于将元素组织成集合。但与列表不同,你不能通过位置来访问字典中的元素。字典内部的数据采用键和值的配对形式。要获取字典中的值,你需要使用其对应的键。
另一个不同点是:在列表中,索引必须是数字;而在字典中,你可以使用多种不同的数据类型作为键,例如字符串、整数、浮点数、元组等。
字典的名称来源于其工作方式类似于人类语言中的词典。在英语词典中,单词对应着定义。在Python字典中,单词就是键,定义就是值。
创建字典 🛠️

你可以用类似于创建空列表的方式来创建一个空字典,区别在于字典使用花括号 {} 来定义其内容。
x = {}
type(x)
创建已初始化的字典与我们在之前视频中创建已初始化列表或元组的语法没有太大不同。但我们不是一系列带有值的槽,而是一系列指向值的键。
以下是创建字典的示例:
file_counts = {
"jpeg": 10,
"txt": 14,
"csv": 2,
"py": 23
}
print(file_counts)
在这个 file_counts 字典中,我们存储了键(如 "jpeg")和对应的整数值(如 10)。创建字典时,我们在键和值之间使用冒号,并用逗号分隔每个键值对。
在字典中,像这样混合和匹配键和值的数据类型是完全可行的,并且非常有用。在这个例子中,我们使用字典来存储每种文件扩展名对应的文件数量。将文件扩展名编码为字符串是合理的,而将计数表示为整数也很自然。
访问字典值 🔑
假设你想找出字典中有多少个文本文件。为此,你需要使用键 "txt" 来访问其关联的值。
执行此操作的语法可能看起来很熟悉,因为我们在索引字符串、列表和元组的示例中使用了类似的方法。
file_counts["txt"]
你还可以使用 in 关键字来检查字典中是否包含某个键。
以下是检查几个键的示例:
"jpeg" in file_counts # 返回 True
"html" in file_counts # 返回 False
修改字典 ✏️
字典是可变的。这意味着我们可以添加、删除和替换条目。
要向字典中添加条目,只需使用方括号创建键并为其分配一个新值。
让我们在字典中为新的 "cfg" 文件扩展名添加一个文件计数 8。
file_counts["cfg"] = 8
print(file_counts)
这引出了一个关于字典的有趣问题:如果我们尝试添加一个字典中已经存在的键,会发生什么?
file_counts["csv"] = 17
print(file_counts)
当你使用一个已经存在的键来设置值时,与该键配对的旧值会被替换。正如你在本例中所见,与 "csv" 键关联的值过去是 2,但现在变成了 17。
字典中的键是唯一的。如果我们尝试为同一个键存储两个不同的值,我们只会用后一个替换前一个。
删除字典元素 🗑️
最后,我们可以使用 del 关键字从字典中删除元素,方法是传递字典和要删除元素的键,就像我们试图访问它一样。
del file_counts["cfg"]
print(file_counts)

总结
本节课中我们一起学习了Python字典。我们了解了字典是一种通过键值对组织数据的数据结构,它与列表不同,通过唯一的键来访问值。我们学习了如何创建字典、如何访问和修改其中的数据,以及如何删除条目。字典在处理需要快速通过特定标识符查找信息的场景时非常有用。
在接下来的课程中,我们将探索一些可以用字典完成的有趣操作。
062:遍历字典内容 📖

在本节课中,我们将学习如何使用循环来遍历字典的内容。我们将探讨如何访问字典的键、值以及键值对,并了解字典在数据统计和分析中的实际应用。
遍历字典的基本方法 🔄
上一节我们介绍了字典的基本结构,本节中我们来看看如何遍历字典的内容。
与字符串、列表和元组类似,你可以使用 for 循环来遍历字典的内容。让我们看看具体如何操作。
file_counts = {"jpg": 10, "txt": 14, "csv": 2, "py": 23}
for extension in file_counts:
print(extension)
如果你在 for 循环中使用字典,迭代变量将遍历字典中的键。
访问键和值 🔑
如果你想访问与键相关联的值,有两种方法。你可以将键用作字典的索引,或者使用 items() 方法。items() 方法会为字典中的每个元素返回一个元组。元组的第一个元素是键,第二个元素是值。
让我们用示例字典来尝试一下。
for extension, amount in file_counts.items():
print("There are {} files with the .{} extension".format(amount, extension))
单独获取键或值 📝
有时你可能只对字典的键感兴趣,有时可能只想要值。你可以使用对应的字典方法来访问它们。
file_counts.keys()
file_counts.values()
这些方法返回与字典相关的特殊数据类型,但你无需确切知道它们是什么。你只需要像遍历任何序列一样遍历它们。
for value in file_counts.values():
print(value)
以下是关键方法总结:
- 我们可以使用
items()来获取键值对。 - 使用
keys()来获取键。 - 使用
values()来获取值。
这并不难,对吧?
字典在计数中的应用 🧮
因为每个键只能出现一次,所以字典是计数元素和分析频率的绝佳工具。
让我们看一个简单的例子,统计一段文本中每个字母出现的次数。
def count_letters(text):
result = {}
for letter in text:
if letter not in result:
result[letter] = 0
result[letter] += 1
return result
在这段代码中,我们首先初始化一个空字典,然后遍历给定字符串中的每个字母。对于每个字母,我们检查它是否已存在于字典中。如果不存在,我们就在字典中初始化一个值为0的条目。最后,我们增加字典中该字母的计数。
总结一下,我们创建了一个字典,其中键是字符串中出现的每个字母,值是该字母出现的次数。
让我们尝试几个示例字符串。
print(count_letters("aaaaa"))
print(count_letters("tenant"))
print(count_letters("a long string with a lot of letters"))
在这里,你可以看到字典可以包含任意数量的条目,键值对总是统计字符串中每个字母的数量。
另外,你是否注意到我们的简单代码没有区分实际字母和特殊字符(如空格)?如果只想统计字母,我们需要指定要考虑哪些字符。

实际应用场景 💡
这项技术起初可能看起来简单,但在很多情况下非常有用。例如,假设你正在分析服务器日志,并希望统计日志文件中每种类型的错误出现了多少次。
你可以轻松地使用字典来实现这一点,将错误类型作为键,每次遇到该错误类型时就增加关联的值。
你是否开始看到字典在编写脚本时是多么有用的工具了?
总结 📚
本节课中我们一起学习了如何遍历字典。我们掌握了使用 for 循环遍历字典的键,以及使用 items()、keys() 和 values() 方法来分别访问键值对、键和值。我们还探讨了字典在数据计数和频率分析中的强大应用,例如统计字母出现次数或分析日志错误类型。理解这些遍历技巧是有效使用字典进行数据操作的关键。
063:Python字典与列表对比指南 📚

在本节课中,我们将学习Python中两种重要的数据结构:列表(List)和字典(Dictionary)。我们将探讨它们各自的特点、适用场景以及如何根据实际需求选择合适的数据结构。
列表与字典的基本用途 🧩
列表和字典都非常有用,它们在不同情况下各有优势。
那么,何时使用列表最佳,何时又该选择字典呢?这取决于你想要表示的信息类型。
如果你有一系列信息需要在脚本中收集和使用,那么列表可能是合适的选择。例如,如果你想存储一系列需要ping的IP地址,可以将它们全部放入一个列表中并进行遍历。


或者,如果你有一个主机名及其对应IP地址的列表,你可能希望将它们作为键值对存储在字典中。
字典的搜索效率优势 ⚡
由于字典的工作原理,在其中搜索元素非常容易且快速。
假设你有一个字典,其中用户名作为键,它们所属的组作为值。无论你有10个用户还是10000个用户,访问给定用户的条目所需的时间都是相同的。这很神奇。
但这对于列表来说并非如此。如果你有一个包含10个元素的列表,需要检查某个元素是否在列表中,这会是一个非常快速的检查。但如果你的列表有10000个元素,检查你要找的元素是否存在将花费更长的时间。
因此,一般来说,当你计划搜索特定元素时,应该使用字典。
存储数据类型的差异 🔢
另一个有趣的差异是列表和字典中可以存储的值的类型。
在列表中,你可以存储任何数据类型。在字典中,我们可以为值存储任何数据类型,但键被限制为特定类型。
允许哪些类型的推理可能很复杂,我们不想用不必要的细节让你感到困惑。因此,作为一个经验法则,你可以使用任何不可变的数据类型(如数字、布尔值、字符串和元组)作为字典的键。
另一方面,正如我们所说,与键关联的值可以是任何类型,包括列表甚至其他字典。你可以使用它们来表示更复杂的数据结构,例如文件系统中的目录树。
字典在系统管理中的应用 🖥️
在系统管理中,我们需要处理大量不同的键值对,因此我经常使用字典。当需要编写脚本从大型数据集中提取特定键以操作或修改关联值时,字典尤其有用。
但这并不总是那么严肃。有一次,仅仅为了好玩,我希望能够查找每个迪士尼主角对应的反派角色。于是我创建了一个字典,存储像“白雪公主”这样的键,其值为“邪恶皇后”。很不错,对吧?
其他数据结构:集合(Set)介绍 🔄
还有更多我们尚未探讨的数据类型。其中之一是集合(Set),它有点像列表和字典的交叉。
当你想要存储一堆元素,并确保它们只出现一次时,可以使用集合。集合的元素也必须是不可变的。

你可以将其视为没有关联值的字典键,或者将其看作一个列表,其中重要的不是元素的顺序,而是元素是否在列表中。
总结与展望 📈
我们已经涵盖了很多内容,但这仅仅触及了字典在脚本中能做的事情的表面。
随着你在IT职业生涯中的进步,你会遇到很多情况,其中字典是组织数据的最简单方法。如果你感兴趣,可以在官方文档中了解更多关于字典的信息。你可以在下一篇阅读材料中找到相关链接。
在本节课中,我们一起学习了列表和字典的核心区别、各自的优势以及适用场景。记住,列表适合存储有序序列,而字典适合通过键快速查找值。掌握这两种数据结构,将帮助你更高效地处理各种编程任务。
064:Python基础数据结构总结 🧱
课程编号:P64

在本节课中,我们将要学习Python中三种核心数据结构——字符串、列表和字典——的基本概念与应用。我们还会简要介绍元组和集合这两种关联数据类型。掌握这些结构是编写高效Python脚本、解决实际IT自动化问题的关键。
上一节我们介绍了本模块的学习目标,本节中我们来看看这些数据结构的具体内容及其重要性。
字符串、列表和字典是Python中最常用、最基础的数据结构。理解并熟练运用它们,能够让你编写的程序处理更复杂、更有趣的任务。
正如我们反复强调的,掌握这些结构并知道在何种场景下使用哪一种,关键在于实践。你编写的、运用这些概念的脚本越多,在需要时选择正确工具就会变得越容易。
核心数据结构详解
以下是三种核心数据结构及其关键特性的介绍:
-
字符串
- 用于表示文本信息。
- 由一系列字符组成,是不可变序列。
- 可以使用索引和切片进行访问。
- 示例代码:
my_string = “Hello, World!”
-
列表
- 用于存储有序的元素集合。
- 元素可以是任何数据类型,列表本身是可变序列。
- 同样支持索引、切片,并可以方便地添加或删除元素。
- 示例代码:
my_list = [1, ‘apple’, True]
-
字典
- 用于存储键值对映射关系。
- 通过唯一的键来快速访问对应的值,是无序集合。
- 非常适合用于表示具有关联关系的数据。
- 示例代码:
my_dict = {‘name’: ‘Alice’, ‘age’: 30}
关联数据类型
除了上述三种核心结构,还有两种重要的关联数据类型值得了解:
-
元组
- 类似于列表,但它是不可变序列。
- 一旦创建,其内容无法修改。
- 通常用于保证数据不会被意外改变的场景。
- 示例代码:
my_tuple = (10, 20, 30)
-
集合
- 用于存储唯一且无序的元素集合。
- 支持数学上的集合运算,如并集、交集。
- 示例代码:
my_set = {1, 2, 3, 3}(最终my_set为{1, 2, 3})
学习建议与鼓励
我们刚刚学习了许多新概念,如果感到有些吃力,这完全正常。每个学习编程的人在某些阶段都会有这样的感受。
如果你对已学内容中的任何部分感到不确定,现在是重新观看课程视频的好时机。你会惊讶于自己已经掌握了这么多知识。通常,第二次复习就能帮助你理解那些当前看似棘手的问题。
IT行业的工作需要解决问题能力和坚持不懈的精神。你能坚持学习到这里,本身就证明了你有掌握脚本编写所需的毅力。请坚持下去,我保证这会变得越来越容易。
课程总结
本节课中我们一起学习了Python的三种核心数据结构:字符串、列表和字典,并简要了解了元组和集合。掌握这些结构是有效进行Python编程和IT自动化的基石。

为了帮助你巩固所有新知识,我们准备了一个分级评估测试。请在感觉准备充分后完成它,不用着急,记住:你能行!😊
065:Python脚本挑战与计算复杂性 🧩
课程编号:P65
在本节课中,我们将通过一个真实的开发案例,探讨编写复杂脚本时遇到的挑战,并理解“可解问题”与“不可解问题”在计算理论中的核心概念。

当我还在阿根廷担任软件开发人员时,曾接到一项任务:编写一个极其复杂的脚本。
该脚本需要计算在一个特定尺寸的货运集装箱中,可以放入多少种不同尺寸的箱子。
具体来说,我们有一个固定尺寸的集装箱,以及一系列尺寸各异的箱子,目标是在集装箱内尽可能高效地摆放这些箱子。
为了完成这个脚本,我进行了大量的研究,过程中也遇到了许多挫折。
最终,我成功编写出了一个能够“基本运行”的程序,我对这个结果感到满意,用户也接受了它。
这个解决方案并非完美,存在一些不尽如人意之处,但它已经达到了“足够好”的程度。
然而,在接下来的大学学期里,我学习到了一个关键的理论。
我了解到,我所面对的这个“装箱优化问题”,在计算复杂性理论中,属于一类不可解问题。
这意味着,从理论上讲,不存在一个算法能在所有情况下都得出完美的最优解。
我那时得到的“足够好”的解决方案,实际上已经是该问题在现实约束下所能达到的最佳结果之一。
核心概念解析
以下是本案例中涉及的核心计算理论概念:
-
NP难问题:这是一类计算难度极高的问题。对于这类问题,验证一个给定解决方案的正确性相对容易,但要找到一个最优解决方案却极其困难,所需时间可能随问题规模呈指数级增长。装箱问题就是典型的NP难问题。
- 公式/概念描述: 对于规模为
n的问题,最优解的寻找时间可能为O(2^n)或O(n!),而验证时间可能仅为O(n)或O(n log n)。
- 公式/概念描述: 对于规模为
-
启发式算法与近似算法:面对NP难问题,我们通常不追求完美的精确解,而是采用以下策略:
- 启发式算法:基于直观或经验构造的算法,能在可接受的时间内给出一个可行的、但不一定是最优的解决方案。例如“首次适应递减算法”。
- 近似算法:能够在多项式时间内运行,并保证其找到的解与最优解之间的误差在一个明确的比率之内。
给初学者的启示
上一节我们介绍了计算复杂性的基本概念,本节中我们来看看从这个经历中可以总结出哪些对编程实践有益的启示。
在软件开发中,尤其是处理优化类任务时,理解问题的本质至关重要。
- 识别问题类型:在投入大量时间寻找“完美解决方案”之前,先尝试判断你面对的问题是否属于计算上的“难题”(如NP难问题)。这可以通过调研或学习计算理论基础知识来完成。
- 设定合理目标:如果确认问题是NP难的,应将目标从“找到最优解”调整为“在有限时间内找到一个足够好的可行解”。
- 利用现有方案:许多经典难题(如装箱、旅行商、调度问题)已有大量研究和成熟的启发式/近似算法。直接应用或借鉴这些方案是高效且明智的选择。
- “足够好”即是成功:在工程实践中,在时间、资源和性能之间取得平衡的“足够好”的解决方案,往往比追求理论上的完美更具价值。
本节课中,我们一起学习了一个真实的脚本开发案例,并由此引出了对计算复杂性,特别是NP难问题的讨论。
我们明白了并非所有问题都存在完美的算法解决方案,在面对这类“不可解问题”时,采用启发式或近似算法寻找一个“足够好”的可行解,是更为务实和高效的工程实践。
理解这一概念,能帮助我们在未来的开发工作中合理设定目标,选择正确的工具与方法。
066:最终项目介绍 🎯

在本节课中,我们将学习如何运用已掌握的Python知识来解决一个更复杂的实际问题。我们将遵循一个结构化的方法来分解问题、进行研究、规划方案,并最终编写和测试脚本。
恭喜你坚持到这里。课程已接近尾声。
这是一段有趣且收获颇丰的旅程。一路上,你学习了Python语法基础,包括函数、条件语句和循环。你也学会了如何使用最常见的数据类型,例如整数、字符串、列表和字典。你甚至还接触了面向对象编程。
现在,我们将把所有知识结合起来,解决更有趣、更激动人心的问题。我们将把这些新挑战当作需要用脚本解决的真实世界问题来对待。通过这样做,我们将再次看到这些编程技能如何使我们IT工作中的任务变得更快速、更高效。
在接下来的视频中,我们将探讨如何通过从头开始编写脚本来解决一个更复杂的问题。
结构化问题解决方法 🛠️
为此,我们将一步步进行,采用一种推荐的应对高级挑战的方法。
在课程开始时,我曾简单提过我编写的第一个Python脚本。一切都始于一个问题:我们团队的待命人员收到了过多的告警通知。处于待命状态是一项艰巨的任务,每当出现问题,待命人员都需要到场“救火”。这是一个令人疲惫的挑战。
为了帮助缓解部分压力,我们想构建一个更好的监控仪表盘。完成它需要进行大量的重构、调试和测试。这并不容易,但幸运的是,我不必从零开始。我得到了队友的帮助,以及互联网上成千上万分享过类似难题的人们的帮助。
当仪表盘最终上线运行时,松了一口气的不只是待命人员。要开始解决我们的问题,我们首先需要查看问题陈述,以理解我们需要做什么,以及我们需要编写的脚本的输入和输出是什么。
从研究到实施 📝
然后,我们将进行一些研究。我们将思考如何利用Python内置的工具来应对这个问题。请记住,我们总是希望避免重复造轮子。无论挑战看起来多么棘手和复杂,很可能之前已经有人解决过类似的问题。因此,花些时间利用现有资源来帮助我们解决问题是非常有价值的。
一旦我们明确了需要编写什么以及可以利用什么来实现,我们就会进行一些规划。我们将思考哪些数据类型对我们的解决方案有用,以及我们将如何操作它们。
最后,我们将实际编写脚本,然后检查代码是否按预期工作。
当我们采用这种结构化的方法来应对问题时,确实没有什么挑战是复杂到无法解决的。那么,让我们开始吧。
本节课总结:本节课我们一起回顾了已学的Python核心技能,并介绍了一个结构化的四步法来解决复杂编程问题:理解问题、研究方案、规划设计、编写测试。这为我们即将开始的最终项目实战奠定了方法论基础。
067:问题陈述与需求分析 🎯

在本节课中,我们将学习如何为一个具体的IT自动化任务定义清晰的问题陈述,并分析其输入、输出及核心需求。我们将为一个虚构的公司创建一份每日报告,用于追踪哪些用户登录了哪些机器。
概述
想象一下,你是一家中型公司的IT专家。你的经理希望创建一份每日报告,用于追踪机器的使用情况。具体来说,她想知道当前哪些用户连接到了哪些机器。你的任务就是创建这份报告。
在你的公司,有一个系统会收集网络上每台机器发生的所有事件。在收集的众多事件中,它记录了用户每次登录或注销计算机的时间。利用这些信息,我们需要编写一个脚本,生成一份报告,列出在特定时间点哪些用户登录了哪些机器。
输入分析
在着手解决问题之前,我们需要明确脚本的输入和输出信息。我们可以通过查看脚本所在系统的其余部分来弄清楚这一点。
在我们的报告场景中,输入是一个事件列表。每个事件都是Event类的一个实例。Event类包含以下属性:
- 事件发生的日期 (
date) - 事件发生的机器名称 (
machine) - 涉及的用户 (
user) - 事件类型 (
type)
在这个场景中,我们只关心“登录”(login)和“注销”(logout)这两种事件类型。事件类型是字符串,我们关心的两个值是 "login" 和 "logout"。
我们的脚本将接收一个Event对象列表,并访问这些事件的属性。然后,我们将利用这些信息来判断用户当前是否登录了某台机器。
输出设计
接下来,我们谈谈输出。我们需要生成一份报告,列出所有机器名称,并且针对每台机器,列出当前登录的用户。然后,我们希望将这些信息打印到屏幕上。
我们被委派生成报告,因此可以自行决定报告的具体呈现形式。一种选择是:在一行的开头打印机器名称,然后在单独的行上列出当前用户,并向右缩进。或者,我们也可以打印机器名称,后跟一个冒号,然后在同一行上用逗号分隔所有用户名。
在设计报告格式时,很容易陷入“让它看起来更美观”的部分。我曾掉入过这个陷阱。但真正重要的是脚本解决问题的能力。因此,最好首先专注于让程序运行起来。之后你总可以花时间让报告看起来更美观。目前,我们保持简单,采用打印机器名称后跟所有当前用户(用逗号分隔)的方法。
问题陈述总结
好的,我们现在对需要做什么有了清晰的认识。我们已经明确了问题陈述:我们需要处理一个Event对象列表,利用它们的date、type、machine和user属性,生成一份报告,列出当前登录到各台机器的所有用户。

我们有了一个良好的开端。下一步,我们将进行研究,以确定实际完成此任务的最佳方法。
本节课总结
在本节课中,我们一起学习了如何为一个IT自动化任务(生成用户登录报告)进行需求分析。我们明确了脚本的输入是包含特定属性的Event对象列表,输出是格式化的机器与当前登录用户对应关系。我们强调了在开发初期应优先关注功能实现而非界面美化。接下来,我们将研究实现这一目标的具体方法。
068:问题研究与列表排序 🧠

在本节课中,我们将学习如何通过研究来解决问题,并掌握在Python中对列表进行排序的方法。我们将从理解问题开始,逐步探索可用的工具,最终确定解决方案。
概述
我们面临的问题是需要处理一系列事件对象,并评估这些对象的属性,以输出当前登录到某台机器的所有用户报告。为了正确解决这个问题,我们必须按时间顺序处理事件,并学会如何对列表进行排序。

问题理解与参数明确
上一节我们明确了问题:输入事件对象列表,通过评估对象属性输出当前登录用户报告。本节中,我们来看看如何通过研究找到合适的工具来解决这个问题。
要确定哪些用户当前登录到机器,我们需要检查他们的登录和登出时间。
如果用户登录后已登出,则不再处于登录状态。如果尚未登出,则仍处于登录状态。在编程中,明确参数至关重要。
此外,这告诉我们,为了正确解决问题,必须按时间顺序处理事件。否则,如果先处理登出事件再处理对应的登录事件,代码可能会产生不可预测的行为。
研究:Python中的列表排序
那么,如何在Python中对列表进行排序?我们需要进行一些研究。
在搜索引擎中输入“sort lists Python”,会得到许多提到列表的sort方法和sorted函数的结果。
这两种选项的区别在于:sort方法会修改原列表,而sorted函数会返回一个新的排序列表。除此之外,它们的工作方式完全相同。
让我们通过实际操作来检查这一区别。
首先,创建一个数字列表并调用sort方法进行排序:
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(numbers) # 输出:[1, 1, 2, 3, 4, 5, 9]
可以看到列表元素已被排序。

现在,尝试使用sorted函数的例子:
names = ["Charlie", "Alice", "Bob"]
sorted_names = sorted(names)
print(sorted_names) # 输出:['Alice', 'Bob', 'Charlie']
print(names) # 输出:['Charlie', 'Alice', 'Bob']
再次打印原列表以确认它未被修改。
所以,sorted函数返回了一个新的排序列表,而原列表保持不变。
很好,我们现在知道了如何在Python中对列表进行排序。对于这个问题,修改原列表是可以接受的,因此我们将使用sort方法。
自定义排序条件
但是,请注意这两种方法默认都按字母顺序排序。这是Python的默认方式。
如果我们想根据不同的条件来组织列表呢?
再次查看在线文档,我们会发现sort方法可以接受几个参数。其中一个参数叫做key,它允许我们使用一个函数作为排序键。
让我们在名字列表上尝试一下。除了按字母顺序排序,我们还可以按每个字符串的长度排序。还记得我们可以使用哪个函数来实现吗?
是的,我们可以将len函数作为key传递:
names = ["Charlie", "Alice", "Bob"]
names.sort(key=len)
print(names) # 输出:['Bob', 'Alice', 'Charlie']
我们现在知道了如何根据函数的返回值对列表元素进行排序。
在我们的报告场景中,元素将是Event类的实例,我们希望按日期排序,日期是Event类的一个属性。
一种方法是编写一个名为get_event_date的函数,该函数返回事件对象中存储的日期。
如果我们能够修改类,也可以将其作为Event类的一个方法。但由于我们正在处理生成这些事件的更大系统,我们将假设不能直接向类添加方法。因此,我们将创建自己的函数。
总结
本节课中,我们一起学习了如何通过研究来解决问题,并掌握了在Python中对列表进行排序的方法。我们明确了问题参数的重要性,探索了sort方法和sorted函数的区别,并学会了如何使用key参数进行自定义排序。在下一课中,我们将深入探讨构建脚本的计划。
069:问题解决步骤之计划 🗺️

在本节课中,我们将学习如何为编程问题制定解决方案计划。我们将通过一个具体案例——处理用户登录/登出事件并生成报告——来演示如何将问题分解,并规划代码的结构和逻辑。
上一节我们介绍了如何定义问题陈述和研究可用工具。本节中,我们来看看如何为我们的解决方案制定一个清晰的计划。
我们知道输入将是一个事件列表,我们需要按时间对其进行排序。每个事件都包含机器名、用户名以及事件类型(登录或登出)。我们的脚本需要追踪用户在机器上的登录和登出状态。
那么,我们该如何实现呢?让我们思考对每个事件需要做什么,并找出最佳策略。
当处理一个事件时,我们会看到某人与一台机器发生了交互。如果事件是登录,我们需要将该用户添加到该机器的已登录用户组中。如果是登出,则需要从该组中移除该用户。
在这种情况下,使用一个集合来存储当前用户是合理的,在登录时添加用户,在登出时移除用户。
很好,但是,如果给定机器的当前用户存储在一个集合中,我们如何知道哪个集合对应我们正在查看的机器呢?
知道这一点的最简单方法是将这些信息存储在一个字典中。我们将使用机器名作为键,将该机器的当前用户集合作为值。
以下是处理每个事件的基本逻辑步骤:
- 首先,检查字典中是否已存在该机器。这是必要的,因为这可能是我们第一次处理该机器的事件。
- 如果机器不存在,则创建一个新条目。
- 如果机器已存在,则根据事件类型更新现有条目:如果是登录事件则添加用户,如果是登出事件则移除用户。
处理完所有事件后,我们希望打印生成的信息报告。
这是一个完全独立的任务,因此应该是一个单独的函数。这个函数将接收我们生成的字典,并负责打印报告。

将数据处理功能和屏幕打印功能分开是非常重要的。这是因为,如果我们想修改报告的打印方式,我们只需要更改负责打印的函数;或者,如果我们在数据处理逻辑中发现错误,也只需要更改处理函数。这种分离还允许我们使用相同的数据处理函数来生成不同类型的报告,例如生成一个PDF文件。
太好了!我们现在知道了需要做什么、如何去做,以及如何构建我们的代码。接下来,我们就可以进入实质性的部分——实际编写代码了。
本节课中,我们一起学习了为编程问题制定计划的关键步骤。我们明确了使用字典(以机器名为键,用户集合为值)来跟踪状态的核心数据结构,并强调了将数据处理(process_data)与结果输出(generate_report)分离的良好编程实践。这为下一步实际编写清晰、可维护的代码打下了坚实的基础。
070:编写脚本 - 第70课 🖥️

在本节课中,我们将学习如何将之前讨论的概念整合起来,编写一个完整的脚本。我们将处理事件数据,生成一份报告,展示当前登录每台计算机的用户。我们将使用Python字典和集合来存储数据,并编写函数来排序事件、处理数据以及生成最终报告。
概述 📋
我们已经学习了处理事件以生成报告所需的步骤。我们知道如何按时间顺序对事件列表进行排序,以及如何使用字典和集合来跟踪每台计算机的当前用户。我们还知道需要编写一个函数来生成字典,以及另一个函数来打印报告。现在,我们将把这些知识整合起来,编写完整的代码。
编写排序辅助函数 🔧
上一节我们介绍了处理事件的整体思路,本节中我们来看看如何实现第一步:按时间排序事件。
我们将定义一个简单的辅助函数,作为sort方法的参数,用于对事件列表进行排序。
def get_event_date(event):
return event.date
创建处理函数:current_users 🛠️
现在,我们开始编写处理函数,我们将其命名为current_users。
首先,我们定义这个函数。在函数内部,我们使用sort方法并传入刚刚创建的get_event_date函数作为key,来对事件进行排序。
def current_users(events):
events.sort(key=get_event_date)
在开始遍历事件列表之前,我们需要创建一个字典,用于存储计算机名和其用户集合。
machines = {}
现在,我们准备遍历事件列表。
以下是遍历和处理每个事件的步骤:
- 检查事件影响的计算机是否已在字典中。如果不在,则将其添加到字典中,并将值设为一个空集合。
- 对于登录事件,将用户添加到该计算机的集合中。
- 对于登出事件,将用户从该计算机的集合中移除。
for event in events:
if event.machine not in machines:
machines[event.machine] = set()
if event.type == "login":
machines[event.machine].add(event.user)
elif event.type == "logout":
machines[event.machine].remove(event.user)
遍历完所有事件后,字典machines将包含所有出现过的计算机作为键,其对应的值是一个包含该计算机当前登录用户的集合。最后,函数返回这个字典。
return machines
创建报告生成函数:generate_report 📄
我们已经有了一个包含数据的字典,现在需要将其打印出来。为此,我们创建一个名为generate_report的新函数。
在我们的报告中,需要遍历字典中的键和值。我们将使用items()方法,它返回字典中每个键值对。
在打印任何内容之前,我们需要确保不打印当前没有用户登录的计算机。这种情况可能发生在用户登录后又登出时。为了避免这种情况,我们告诉计算机只在用户集合元素数大于零时才打印。
我们之前提到,我们希望打印计算机名,后跟登录该计算机的用户,用逗号分隔。为此,我们使用join()方法为该计算机生成已登录用户的字符串。

最后,我们使用format()方法生成我们想要的最终输出字符串。
def generate_report(machines):
for machine, users in machines.items():
if len(users) > 0:
user_list = ", ".join(users)
print("{}: {}".format(machine, user_list))
总结 🎯
本节课中我们一起学习了如何将多个步骤组合成一个完整的脚本。我们编写了用于排序事件的辅助函数get_event_date,创建了处理事件并返回计算机-用户字典的核心函数current_users,最后编写了格式化并打印报告的函数generate_report。
我们已经编写了解决问题所需的所有函数。这是一个很好的时机,可以暂停一下,回顾从问题描述到编写代码的每个步骤,确保不仅清楚我们使用了哪个函数,而且明白为什么使用它。
如果还有任何不清楚的地方,请记住,讨论区随时可以为你提供帮助。在接下来的视频中,我们将执行这段代码,看看它是否正常工作。让我们拭目以待,测试我们的代码吧。
071:代码汇总与测试 🧪
在本节课中,我们将学习如何将之前编写的代码整合到一个Jupyter Notebook中,并进行测试,以确保其按预期工作。我们还将探讨在实际IT环境中可能遇到的一些边界情况。

代码整合与测试 🛠️
上一节中,我们根据研究和计划编写了解决问题的代码。现在,我们将所有代码放入一个Jupyter Notebook中,并执行它以观察结果。
以下是我们当前代码的样子,正如我们在上一个视频中所写:
# 示例代码:事件处理与报告生成
def process_events(events):
machine_events = {}
for event in events:
if event.machine not in machine_events:
machine_events[event.machine] = set()
if event.type == "login":
machine_events[event.machine].add(event.user)
elif event.type == "logout":
machine_events[event.machine].discard(event.user)
return machine_events
def generate_report(machine_events):
for machine, users in machine_events.items():
if len(users) > 0:
print(f"Machine: {machine}, Users logged in: {', '.join(users)}")
为了验证代码是否按预期工作,我们需要一个事件类来模拟场景。我们将使用一个非常简单的事件类。
class Event:
def __init__(self, event_date, event_type, machine_name, user):
self.date = event_date
self.type = event_type
self.machine = machine_name
self.user = user
使用这个构造函数,我们将创建一些事件并将它们添加到列表中。
events = [
Event('2023-10-01', 'login', 'webserver', 'jordan'),
Event('2023-10-02', 'logout', 'mailserver', 'chris'),
Event('2023-10-03', 'login', 'webserver', 'jordan'),
Event('2023-10-04', 'logout', 'webserver', 'jordan'),
Event('2023-10-05', 'login', 'mailserver', 'taylor'),
]
现在,我们有一系列事件。它们目前是未排序的,涉及几台机器和一些用户。我们将把这些事件输入到我们的函数中,看看会发生什么。
一切准备就绪,让我们执行代码。
machine_events = process_events(events)
print(machine_events)
输出结果:
{'webserver': set(), 'mailserver': {'taylor'}}
太好了!我们的代码正确地创建了一个以机器名称为键的字典。其中有一个空集合和两个包含一个值的集合。现在,让我们尝试生成报告。
generate_report(machine_events)
输出结果:
Machine: mailserver, Users logged in: taylor
成功!我们的报告正确地跳过了那台拥有空集合的机器。这很棒。
边界情况探讨 🤔
在IT世界中,可能会发生许多其他情况。例如,如果我们遇到一个用户从未登录过却尝试注销的事件,我们应该如何处理?
以下是一些可能的处理方式:

- 忽略注销事件:如果用户未登录,则忽略该事件。
- 记录错误:将此类事件记录为错误,以便进一步调查。
- 发出警告:在报告中添加警告信息,提示可能存在异常。
我们将在下一个练习中尝试解决这个问题。
总结 📝
本节课中,我们一起学习了如何将代码整合到Jupyter Notebook中并进行测试。我们创建了一个简单的事件类,模拟了IT环境中的登录和注销事件,并成功生成了报告。此外,我们还探讨了在实际应用中可能遇到的边界情况,为下一步的练习做好了准备。
通过本节课的学习,你应该能够理解代码测试的重要性,并学会如何处理实际场景中的异常情况。
072:祝贺与回顾 🎉

在本节课中,我们将回顾整个课程的学习历程,总结你已掌握的Python编程技能,并展望未来的学习方向。
概述
你已成功完成整个课程。这些概念学习起来并不轻松。
回想你刚开始这段旅程时的情景。你是否还记得观看最初那些视频时的感受?可能有些紧张、害怕,甚至兴奋,或许这些情绪同时存在。
你跟随我一起学习,观看了所有视频,并在内容变得复杂时坚持了下来。你应当为自己感到骄傲。现在,花点时间反思你当前所处的位置。
已掌握的技能回顾
上一节我们概述了学习历程,本节中我们来看看你具体掌握了哪些核心编程技能。

你从对编程知之甚少或一无所知,到现在能够编写各种复杂的函数。
以下是你在本课程中掌握的关键编程概念和结构:
- 条件语句:使用
if、elif、else来控制程序流程。 - 循环:使用
for循环和while循环来重复执行代码块。 - 字符串:处理和操作文本数据。
- 列表:使用
[]创建和操作有序的元素集合。 - 字典:使用
{}创建和操作键值对集合。
你甚至创建了自己的对象。你将所有这些知识结合起来,编写了属于自己的程序,应用了可能在日常IT工作中会用到的流程。
学习收获与未来展望
我们介绍了具体的编程技能,现在来谈谈你的整体收获和未来可能性。
希望你学习的过程和我教学的过程一样充满乐趣。你掌握了所有这些内容,这令人印象深刻。我希望这只是你Python旅程的开始。
在IT领域建立成功的职业生涯需要毅力、勇气和韧劲。通过坚持到现在,你已经证明了拥有大量这些品质。它同样需要技能和知识,而基础的Python无疑是你的IT工具箱中一个强大的工具。
了解如何编写脚本将使你在寻求职业发展时脱颖而出。我敢打赌,你现在会发现周围到处都是任务,并会激发你如何用脚本将其自动化的想法。可能性是无穷无尽的,而这仅仅是个开始。
总结与下一站
记住我们在最初视频中说过的话:千里之行,始于足下。还有很多令人兴奋的东西等待你去学习。
我们希望你能加入我们的下一门课程。在那里,我们将学习Python如何与计算机操作系统交互,以体验即将到来的内容。请留意下一个视频,我们将与你的下一位讲师Roger交流。
本节课中我们一起回顾了整个学习旅程,总结了从条件语句、循环到创建对象等核心Python技能。你已为IT自动化打下了坚实基础。现在,我祝愿你一切顺利。我期待在更广阔的天地里看到你和你的代码。
073:Python与操作系统交互 🚀

在本节课中,我们将预览下一门课程的核心内容,了解如何利用Python与操作系统进行交互。通过本课程的学习,你将掌握设置开发环境、操作文件与进程、使用正则表达式处理文本等关键技能,并最终编写出可用于实际工作的脚本。

课程衔接与展望
你已经完成了第一门课程的学习,但你的Python之旅才刚刚开始升温。
在下一门课程中,我的朋友兼同事Roger将担任你的导师,指导你学习Python如何与操作系统进行交互。
你将在此处学到的所有技能基础上继续构建,你的编程能力也将变得更加精进。
下门课程内容导览
以下是Roger对下一门课程主要内容的介绍。
Roger:
大家好,我是Roger。对于下一门课程,我感到非常兴奋。
我们将涵盖如何在Python中设置你自己的开发环境。很快,你就会开始习惯使用代码与系统进行交互。
我们还将学习如何操作操作系统上运行的文件和进程,并深入探讨正则表达式(Regx),这是一个用于处理文本文件的超级强大的工具。
你甚至将编写一个脚本,这个脚本可能类似于你在工作中会被分配到的任务。
但就我个人而言,整个课程中我最喜欢的部分绝对是讨论Linux操作系统的时候。这并不是因为Linux是我工作中使用的主要操作系统,而是因为Linux开启了一个充满定制化和配置可能性的全新世界,我觉得这非常有趣。
我们有很多强大而有趣的概念即将到来,所以不要错过。我在下一门课程中等你。
Christine:
谢谢Roger。也感谢每一位观看本课程并坚持学习的同学。我们下一门课程再见。
总结
本节课中,我们一起预览了下一门课程“Python与操作系统交互”的核心学习目标。你将学习设置开发环境、使用Python代码管理文件和进程、运用强大的正则表达式处理文本,并最终完成一个贴近实际工作场景的脚本项目。特别是对Linux操作系统的探索,将为你打开系统定制与配置的新视野。请准备好迎接更深入、更实用的编程挑战。
074:Python自动化与操作系统控制 🚀

在本节课中,我们将一起了解《用Python进行IT自动化办公》课程的整体框架、学习目标以及课程内容安排。无论你是刚刚完成Python入门课程,还是直接从这里开始,本课程都将帮助你掌握如何利用Python脚本控制操作系统、处理文件与文本,并最终实现自动化任务。
概述
如果你已经完成了Python入门课程,欢迎回来。如果你跳过了入门课程,这是我们的第一次见面,同样欢迎加入。在IT领域,编程技能能为你打开无数机会的大门。Python脚本是IT工具箱中一个强大的工具,而你已经迈出了学习Python的第一步。
我的名字是Roger Martinez,是Google的硬件系统管理员。我所在的团队负责维护和监控Google硬件工程师用于设计和测试硅芯片的服务器。我非常荣幸能成为本课程的讲师。
本课程由Google独家开发和设计,每门课程都在不同的园区进行,以带给你更多Google的独特体验。请放心,课程内容比我的笑话要扎实得多。
为什么这门课程对我很重要
多年前,当我在新泽西开始大学生活时,我并不清楚自己想学什么。一位朋友建议我了解一下IT课程。虽然我一直喜欢摆弄电脑,但我从未想过IT能成为我的职业。
当我走进那间教室时,我感到格格不入。教室里没有人和我长相相似,口音相同,或来自相似的背景。第二天,我退出了那门课,再也没有回去。回想起来,我有些后悔那个决定。如果我当时坚持下来,也许下一个走进教室的拉丁裔或其他少数族裔学生就会感到他们属于这里。
多元化的想法、经验和背景对IT行业乃至任何行业都至关重要。多元化的代表性对于向下一代展示他们属于这个领域并能在其中茁壮成长,意义重大。因此,教授这门课程对我而言意义非凡。也许它能以某种方式,帮助更多人推开那扇门,永不回头。
课程目标与内容
好了,关于我的部分就到这里。让我们来谈谈课程。学完本课程的最后一个视频后,你将能够:
- 操作计算机操作系统上的文件和进程。
- 学习正则表达式,这是一个处理文本文件的强大工具。
- 学会使用Linux命令行。
- 编写一个程序,处理实际日志文件中的一系列错误,并生成摘要报告。这是一项超级实用的技能,在本课程结束时你将掌握它。
现在听起来可能有些挑战,但你一定能做到。
课程大纲
以下是本课程将涵盖的核心内容:
我们将从探索如何在本地执行Python、以及如何跨不同Python文件组织和使用代码开始。
- 本地执行与代码组织:学习如何运行Python脚本并管理多文件项目。

接着,我们将学习如何读写不同类型的文件,并使用子进程和输入流。
- 文件操作与子进程:掌握使用Python处理文件和与系统命令交互的方法。
我们还将深入探讨Bash脚本和正则表达式,这两者对于系统工作者来说都是非常强大的工具。

- Bash脚本与正则表达式:利用Shell脚本和模式匹配来高效处理文本和系统任务。
我们甚至会接触自动化测试,它允许我们自动检查代码是否正确。



- 自动化测试:学习编写测试来验证代码功能,确保自动化脚本的可靠性。
最后,我们将综合运用所学的所有工具来处理数据并生成自动报告。
- 综合项目:数据处理与自动报告:将所学技能整合,完成一个实际的自动化任务。
我们还将解释如何在你的机器上设置自己的开发环境,并强烈建议你完成这一步。你需要拥有管理员权限来安装软件,或者请管理员为你安装。设置开发环境是能够编写和部署强大自动化工具的关键一步。
学习环境与预备知识
在本课程中,我们将使用Quicklabs,这是一个允许你在Linux虚拟机上测试代码的环境。这让你能在需要编写代码解决问题的同时,体验真实的Linux场景。
本课程的示例和练习将使用Linux。Linux是运行服务器的行业标准,因此我们选择了它。不过在某些时候,我们也会讨论在Windows或MacOS上如何完成相同任务,以给你更全面的认识。
虽然我们会大量使用Linux,但你不需要在自己的机器上运行Linux来跟随学习。你需要做的是确保已安装Python,并且知道如何安装额外的Python模块。别担心,我们稍后会详细讲解这些。
你已经学习了编程的基础构建模块。在本课程中,我们将研究你在日常活动中可能遇到的不同任务,并学习如何通过编程来解决它们。
如果你参加了Python入门课程,我打赌你会很快注意到一个不同点:我们将比以前使用更多的模块。这里我说的“模块”不是指本课程的章节,而是指我们可以用来为脚本获取额外功能的Python模块。
请记住,可能会有些复杂的主题和视频,第一次观看时可能无法100%理解。这完全正常。请慢慢来,如果需要,可以多看几遍视频。我保证你会掌握的。同时,请记住你可以使用讨论区与其他学习者联系,并提出你可能有的任何问题。
总结
本节课中,我们一起了解了《用Python进行IT自动化办公》课程的意义、讲师背景、核心学习目标以及详细的内容大纲。我们即将共同踏上一段有趣而迷人的Python宇宙之旅。那么,让我们开始吧!😊
075:Python编程入门与环境搭建 🐍


在本节课中,我们将学习如何开始使用Python进行编程,包括设置开发环境、运行Python脚本,并初步了解自动化概念。我们将从基础开始,逐步引导你配置本地环境,为后续的自动化任务打下坚实基础。
环境配置:安装Python与设置开发工具
上一节我们概述了本课程的目标,本节中我们来看看如何配置Python开发环境。拥有本地Python环境能帮助你理解如何运行程序、安装额外模块,以及如何整合所有工具。
以下是配置环境的几个关键步骤:
- 在计算机上安装Python解释器。
- 学习如何运行Python脚本。
- 探索如何将代码组织到不同的文件中。
- 了解代码编辑器的作用以及如何选择合适的工具。
完成环境配置并熟悉基本操作后,我们将深入探讨一些自动化概念。
深化自动化理解与实践
在Python入门课程中,我们多次讨论了自动化。我们看过一些自动化示例,并探讨了学习编程带来的各种可能性。在本课程中,我们将在此基础上继续扩展。
我们将学习如何判断某项任务是否适合自动化,以及实施自动化所需的条件。为了在实践中应用这些知识,在整个课程中,你将使用Quicklas工具在远程Linux机器上编写Python脚本。
这个工具能让你体验真实场景,模拟你在IT工作中可能遇到的编程问题。如果在学习过程中的任何时刻感到困惑,请不要担心。你可以根据需要多次观看视频以理解概念。此外,你还可以在讨论区提问,这是获取额外信息并与其他学习者联系的最佳方式之一。
总结与展望
本节课中,我们一起学习了开始Python编程之旅的初始步骤,重点是配置本地开发环境并理解自动化的重要性。我们准备好工具和基础概念,以便在接下来的课程中深入探索更强大的编程工具和自动化解决方案。
076:认识操作系统 🖥️


在本节课中,我们将学习操作系统的基本概念、主要组成部分以及常见的操作系统类型。理解这些基础知识,将帮助我们更好地使用Python与计算机系统进行交互。
概述

操作系统是管理计算机所有活动的核心软件。在本节中,我们将介绍操作系统的定义、主要功能以及它的两个核心部分:内核与用户空间。
什么是操作系统?

操作系统是一种软件,它管理计算机中发生的一切。它从硬盘驱动器读取、写入和删除文件。

它处理进程如何启动、如何相互交互以及如何最终结束。它管理内存如何分配给不同的进程、网络数据包如何发送和接收,以及每个程序如何访问不同的硬件组件。简而言之,操作系统是总管一切的核心。

操作系统的两个主要部分


操作系统实际上包含两个主要部分:内核和用户空间。

内核
内核是操作系统的核心。它直接与我们的硬件对话并管理系统资源。

用户空间
作为用户,我们不直接与内核交互。相反,我们与操作系统的另一部分——用户空间——进行交互。
用户空间基本上是内核之外的一切。这些是我们直接交互的东西,比如系统程序和用户界面。
因此,当我们说操作系统时,我们指的是内核和用户空间两者。
操作系统的功能与我们的焦点
操作系统执行许多任务。它做的事情如此之多,以至于我们需要很多课程才能涵盖所有内容。但对于本课程,我们将专注于管理文件和进程。
在我们计算机上运行的操作系统中,我们编写的脚本都将在用户空间中运行。不过,在某些情况下,我们的脚本可能会与操作系统的内核交互,以获取额外信息或要求它执行某些操作。
常见的操作系统类型
你可能已经知道,市面上有许多不同的操作系统。当今IT领域使用的主要操作系统是Windows、macOS和Linux。
- Windows:由微软开发,广泛应用于商业和消费领域。大多数个人电脑都预装Windows作为默认操作系统。
- macOS:由苹果公司开发,主要用于消费领域。如果你购买任何苹果电脑,它都会预装macOS。
- Linux:是一个开源操作系统。开源软件可以自由分享、修改和分发。Linux被大量用于商业基础设施。当今世界上大多数服务器都运行Linux。它也可用于消费领域,尽管不那么常见。
Linux本身实际上是林纳斯·托瓦兹最初开发的内核的名称。由于操作系统其余部分的演变,我们通常用Linux来指代内核和整个操作系统。如今,Linux已经发展成为一个巨大的社区努力,世界各地的开发者为它的成功做出了贡献。
因为Linux是开源的,许多不同的组织打包了他们自己的版本。这与仅由各自公司开发的Windows或macOS不同。我们将这些不同风格的Linux称为发行版。
一些常见的Linux发行版有Ubuntu、Debian和Red Hat。如果你听说过Chrome OS,你可能知道它是另一个基于Linux内核的操作系统,但与其他发行版不同,Chrome OS通常被视为一个独立的操作系统。最后,在智能手机上广泛使用的Android操作系统也运行Linux内核。
Unix与Linux的关系
你可能也听说过Unix。Unix是贝尔实验室在70年代开发的一个操作系统。在其最初发布之后,该操作系统经历了许多不同的版本,不同的公司发布了它的变体。
当今Linux工作原理的基本思想是基于Unix原则。我们用来与操作系统交互的许多工具都是最初为Unix开发的工具的开源版本。这就是为什么这些工具和操作原则通常被称为Unix,即使我们使用的操作系统叫做Linux。所以,林纳斯基于Unix创造了Linux,这基本上是一个编程绕口令。
macOS内核及其部分用户空间也基于Unix家族中称为BSD的内核和用户空间工具。因此,尽管两者的图形界面差异极大,但命令行实际上非常相似。
Python的跨平台优势

就像我们之前在本课程中提到的,我们将使用Python与操作系统交互。Python是一种跨平台语言,你可以在Windows、macOS、Linux甚至像FreeBSD这样不太知名的Unix变体上使用它。它甚至在手机上也可用。
由于它是跨平台的,我们可以使用相同的Python代码在任何操作系统上实现我们的目标,无论是打开文件、处理文本还是管理运行中的进程。这使得Python成为需要与不同操作系统交互的IT专家的绝佳工具。你可以将从一个平台学到的技能应用到所有其他平台上。这非常有用。
本课程的操作系统选择
正如我们之前指出的,在本课程的练习中,我们将使用Linux计算机进行实践。我们选择Linux是因为在远程管理和通过自动化管理的服务器方面,它是行业标准。在相关的时候,我们也会讨论相同的概念如何适用于Windows或macOS。
个人经验分享
在我作为系统管理员的工作中,我主要使用Linux操作系统。我从小使用Windows电脑,并通过图形界面与它们交互。我第一次使用Linux是在我十几岁的时候,当时我的个人电脑崩溃了,无法启动到用户环境。我有很多不同的文件和文档,我不想放弃。于是我做了一些研究,在朋友的电脑上,我将一个名为Slax的便携式Linux操作系统刻录到一张CD上。我用它启动了我的电脑,并成功抢救了大部分文件。
学习Linux为我打开了一个定制和配置的全新世界。当我刚开始时,我发现它非常有趣、迷人,甚至有点吓人。今天,Linux是我每天工作的主要操作系统。
总结
本节课我们一起学习了操作系统的基础知识。我们了解了操作系统的定义、内核与用户空间的区分,以及Windows、macOS和Linux等主流操作系统的特点。我们还探讨了Unix与Linux的历史渊源,并理解了Python作为跨平台工具在与不同操作系统交互时的巨大优势。最后,我们明确了本课程将主要使用Linux进行实践。如果你觉得这些不同的名字让你感到困惑,请不要担心,随着课程的深入,你会逐渐掌握它们。
现在我们已经对“操作系统”一词达成了共识,在下一个视频中,我们将准备好我们的计算机,开始使用Python。
077:为Python准备计算机 🖥️

在本节课中,我们将学习如何在本地计算机上准备Python编程环境。这包括检查Python是否已安装、安装Python 3(如果尚未安装),以及了解如何管理Python的外部模块。作为IT专家,掌握在不同操作系统中安装和管理软件是一项重要技能。
实践是最好的学习方法
人们常说,学习的最佳方法是不断练习。因此,我们鼓励你通过在自己的计算机上运行脚本来完成本课程的练习。这样做能帮助你尽可能磨练编程技能,并可能激发你通过编程实现新事物的想法。
检查Python是否已安装
正如上一节视频所说,Python可以在所有主流操作系统上运行。无论你使用的是Windows、Mac OS还是Linux,都应该能在本地计算机上运行Python。它甚至可能已经安装在你的系统中。
要检查计算机上是否已安装Python,请打开终端或命令提示符,并执行以下命令,将--version作为参数传递:
python --version

根据计算机上已安装的内容,可能会出现几种不同的情况。

- 它可能提示无法识别该命令,这意味着你没有安装Python。
- 它可能返回一个以数字2开头的版本号,这表示你安装的是Python 2。
- 它可能返回一个以数字3开头的版本号,这意味着你安装的是Python 3。
确保使用Python 3


在本课程中,我们将使用Python 3。我们涵盖的某些内容在Python 2和Python 3上是相同的,但有些可能截然不同。因此,请确保你安装了Python 3。
如果运行python --version返回以2开头的版本,请尝试运行python3 --version。你的计算机可能会提示该命令不存在,这意味着你需要安装Python 3。或者,如果返回以数字3开头的版本,则表示你已经安装了Python 3。
在接下来的几个视频中,我们将讨论如何在每个操作系统上安装和设置Python(如果尚未安装的话)。

了解Python模块
在确认安装了Python 3之后,我们还将学习安装不属于Python标准库的额外模块。本课程中的一些特定练习将需要这些额外模块。
那么,我们所说的这些额外模块是什么呢?在Python入门课程中,我们讨论过Python标准库。它作为Python安装的一部分,包含了用Python可以完成的最常见任务的模块。
但是,你的脚本中可能想做很多事情,而并非所有功能都在标准库中。这时就需要外部模块了。我们可以使用外部模块来完成一系列任务,例如生成PDF、提供网页服务、创建压缩文件、处理电子邮件以及许多其他事情。
如何查找可用模块
当开发者编写了一个他们认为可能对他人有用的Python模块时,他们会将其发布到PyPI,也称为Python包索引。我们可以浏览这个Python模块仓库来找到所需的模块。它包含了成千上万个项目,并按主题、开发状态和目标受众等不同类别进行分类。
这些外部模块通常使用一个名为pip的命令行工具进行管理。这是一个跨平台工具,因此你可以使用它在计算机运行的任何操作系统上安装、更新和删除外部模块。
后续内容预告
接下来,我们将讨论如何在Windows、Mac OS和Linux上安装主要的Python包以及外部模块。这些视频都是可选的。你可以观看与你最相关的部分,或者,如果你的计算机上已经安装了Python并且已经知道如何安装外部模块,可以随时跳过。
本节课总结
在本节课中,我们一起学习了为Python编程准备本地环境的关键步骤。我们了解了检查Python安装状态的方法,明确了本课程需要使用Python 3,并认识了Python标准库与外部模块的区别。我们还介绍了用于管理外部模块的工具pip以及查找模块的资源PyPI。掌握这些基础知识,将为你后续的编程实践铺平道路。
078:在 Windows 上配置 Python 环境 🛠️

在本节课中,我们将学习如何在 Windows 操作系统上安装和配置 Python 环境,并安装一个常用的外部模块。这是开始使用 Python 进行自动化工作的第一步。
检查 Python 是否已安装
Windows 计算机通常不会预装 Python。


要检查您的计算机是否已安装 Python,请运行我们之前讨论过的命令:
python --version
如果命令未返回 Python 版本信息,则说明 Python 未安装在这台计算机上,我们需要安装它。
选择安装方法
在 Windows 上有多种安装 Python 的方法。我们可以从官方网站下载可安装包进行安装;如果使用 Windows 10,也可以从应用商店获取;或者使用名为 Chocolatey 的包管理系统来管理安装。
在本视频中,我们将直接从官方网站安装软件包。但如果您想尝试 Chocolatey,可以自行查看并下载。
下载官方安装程序
要找到安装程序,请访问 Python 的官方 Windows 下载页面。
在该页面上,我们可以下载适用于 64 位架构的 Python 3.6.4 可执行安装程序。如今大多数计算机都安装的是 64 位系统。如果您不确定选择哪个,就选择 64 位版本。除非您确定您的计算机运行的是 32 位系统。
运行安装程序
可执行安装程序下载完成后,我们需要运行它。这将在我们的机器上安装新软件,因此我们需要以管理员身份运行它。
在点击“立即安装”之前,请确保勾选“Add Python 3.7 to PATH”复选框。

PATH 变量指示操作系统在从终端运行命令时,在系统的特定目录中查找可执行文件。您需要选中该框,以便当我们从命令行调用 Python 时,能够执行 Python 解释器。

安装过程可能需要一些时间。
验证安装
安装完成后,我们可以测试它是否成功。
我们通过打开一个新的 PowerShell 窗口并执行与之前相同的命令来验证:

python --version
很好,我们现在有了一个可执行的 Python 解释器,可以用来测试我们编写的脚本。
安装外部模块
正如我们所指出的,仅仅安装了 Python 3,并不意味着我们拥有所有可能脚本所需的模块。
假设我们的任务是编写一些从网站提取信息的自动化脚本。为了在 Python 中获取网站内容,我们可以选择用于与 Web 服务交互的 requests 模块。
首先,让我们检查是否已经拥有这个模块。在 Python 解释器中尝试导入:
import requests
如果解释器提示模块不可用,我们需要使用 PIP 安装它。为此,我们从命令行(而不是解释器)调用:
pip install requests

现在我们已经安装了该模块。让我们再次从解释器中尝试导入它:
import requests
成功了。为了再次确认,让我们尝试用这个模块做点什么。例如,我们可以使用 get 函数来获取网站的内容:
response = requests.get('https://www.example.com')
get 函数处理了网站,现在 response 对象包含了其内容。我们可以用它做很多事情。例如,使用 len 函数检查响应文本的长度:
len(response.text)
总结
本节课中,我们一起学习了如何在 Windows 环境中设置 Python。我们完成了从检查安装、下载官方安装程序、运行安装并配置 PATH,到使用 PIP 安装外部模块(如 requests)的完整流程。现在,您的 Windows 环境已经准备好运行 Python 脚本了。请自由探索并尝试一些操作。
接下来,我将向您展示如何在 Mac OS 上安装 Python。您可以选择观看,也可以跳过,这取决于您。
079:在macOS上配置Python环境(可选) 🍎

在本节课中,我们将学习如何在macOS操作系统上配置Python 3开发环境。我们将从检查系统自带的Python版本开始,逐步完成Python 3的安装、验证以及第三方模块的管理。

默认情况下,macOS系统预装了一个Python版本,但它是Python 2,而不是Python 3。
让我们来验证这一点。虽然这台电脑上安装了Python,但它只是Python 2。
我想知道我们是否将Python 3作为另一个不同的命令安装了。让我们检查一下。
所以,这台电脑没有预装Python 3。让我们来安装它。

在macOS上安装Python有两种方法。我们可以从官方网站下载可安装的软件包进行安装,或者使用一个名为Homebrew的包管理系统来管理安装。
在本视频中,我们将从官方网站安装软件包,但你可以自行了解Homebrew。
要在macOS上安装Python,请访问Python官方网站 python.org。
现在我们将点击“Downloads”菜单。因为我们在macOS电脑上运行,网站会自动为我们提供macOS版Python 3的安装链接。
我们正在下载macOS版的Python 3可执行安装程序。下载完成后,我们将执行它,浏览许可协议和使用条款页面,最后完成安装。


根据你的机器设置,你可能需要输入密码以使用管理员权限执行实际安装。
很好,现在我们有了一个可执行的Python 3解释器,可以用来测试我们将要编写的脚本。
让我们执行与之前相同的命令来检查它是否正常工作:python3 --version。
太好了,现在我们已经安装了Python 3。正如我们之前所说,仅仅安装了解释器并不意味着我们拥有执行所有可能脚本所需的所有模块。
假设我们需要编写一个用于处理事件安排的自动化脚本。为此,我们需要管理许多不同的日期和截止日期操作,例如计算两周后的日期。为了让所有这些日期操作变得更简单,我们可以使用arrow模块,它使得处理各种日期变得容易。
首先,让我们检查是否已经拥有这个可用的模块。解释器提示没有可用的arrow模块。为了获取该模块,我们将使用pip3命令来安装。
请注意,在Windows上该命令叫pip,而在macOS上它叫pip3。因此,要从命令行(而不是解释器)安装arrow模块,我们将调用pip3 install arrow。

现在我们已经安装了该模块,让我们再次尝试从解释器中导入它。很好,看起来成功了。为了检查我们能否使用它,让我们尝试用这个模块做点什么。
我们如何使用模块中的get函数从字符串创建日期对象呢?很好,arrow按照我们指定的格式从字符串中解析出了一个日期。现在,这个日期对象包含了那个日期。我们可以对这个对象进行操作。例如,我们可以要求使用shift方法将其增加六周,然后使用format方法打印它。
我们刚刚使用的format方法可以接收许多参数。这些参数让我们能够直观地格式化要打印的字符串。
我们的macOS环境已经准备就绪。现在,我们可以使用Python并开始用它做一些有趣的事情了。你可以自由探索,尝试其他一些操作。
接下来,我将向你展示如何在Linux上安装Python。你可以查看那一部分,或者直接跳过,这取决于你。
总结
本节课中,我们一起学习了在macOS上配置Python 3环境的完整流程。我们从检查系统自带的Python 2开始,然后通过官方网站下载并安装了Python 3。接着,我们验证了安装,并学习了如何使用pip3来安装和管理第三方Python模块(以arrow模块为例)。最后,我们通过一个简单的日期操作示例,实践了新安装模块的使用。现在,你的macOS环境已经准备好用于Python自动化脚本开发了。
080:在 Linux 上配置 Python 环境(可选) 🐧

概述
在本节课中,我们将学习如何在 Linux 操作系统上检查和配置 Python 3 环境。课程内容包括验证 Python 安装、安装缺失的模块,以及使用系统包管理器和 pip 两种方式来管理 Python 包。掌握这些技能是使用 Python 进行自动化工作的基础。

检查 Python 安装情况
如果你的计算机运行 Linux 系统,那么你的发行版极有可能已经预装了 Python。
你可以通过打开终端并运行以下命令来验证这一点:
python --version
运行后,你可能会发现系统安装的是 Python 2。这是一个旧版本的 Python,而我们需要使用 Python 3。
接下来,让我们检查系统是否安装了 Python 3:
python3 --version
在某些 Linux 发行版中,python 命令可能已经指向 Python 3。但在其他发行版(例如演示中使用的这个)中,你可能需要使用 python3 命令来访问 Python 3。
本系列所有课程都将使用 Python 3,因此请确保你为你的发行版运行了正确的命令。
安装 Python 3
如果由于某些原因,你的 Linux 系统没有安装 Python 3,你需要使用包管理系统来安装它。
用于管理本地软件包的工具名称取决于你使用的发行版:
- 在 Debian、Ubuntu 和 Linux Mint 上,它叫做
apt。 - 在 Red Hat 或 CentOS 上,它叫做
yum。 - 在 Fedora 上,它叫做
dnf。
如果你不确定你的发行版使用什么命令,最好做一些研究来找出答案。我们在下一份阅读材料中提供了更多信息的指引。
安装 Python 模块
即使我们的计算机已经安装了 Python 3,我们可能仍然没有执行所有脚本所需的全部模块。因此,我们仍然需要学习如何将这些模块添加到系统中,以充分利用我们的 Python 安装。
在本示例中,我们将使用一台 Ubuntu 计算机和 apt 工具来安装 Python 包。我们将讨论两种不同的安装包方式:第一种是通过系统包管理器,第二种是通过 pip。
方法一:使用系统包管理器
正如之前所说,Linux 发行版通常都有一个包管理系统,使用它来在计算机上安装额外的软件是一个好主意。
发行版通常为不同的可用 Python 模块提供单独的软件包。
假设我们的任务是编写一些自动化软件,用于将图像调整到特定尺寸。我们可以通过使用 Python 图像库(即 PIL 模块)来实现这一点。该库包含了大量图像处理功能。
要在你的 Ubuntu 计算机上安装此模块,我们可以使用 apt 工具来安装 python3-pil 包:
sudo apt install python3-pil
使用包管理系统安装软件包的一个优点是,我们可以设置系统自动升级到新版本。包管理系统确保任何依赖项也被安装,从而使模块可以立即使用。
让我们测试一下刚刚安装的模块。PIL 模块非常庞大,因为它包含了许多我们可以对图像进行的操作。
对于这个例子,我们想打开一张图片并检查其尺寸和格式。我们从 PIL 模块中导入了 Image 子模块。
现在,让我们使用 open 方法打开家目录中的一个文件:
from PIL import Image
img = Image.open('example.jpg')
很好,我们已经打开了图像。现在我们可以检查它的尺寸和格式属性:
print(img.size)
print(img.format)
模块运行正常。
方法二:使用 PIP 安装模块
在这种情况下,我们想要的模块是由包管理系统提供的,因此使用 apt 安装很容易。但在其他情况下,我们可能希望安装比发行版中提供的版本更新的模块,或者发行版中根本没有的模块。
对于这类情况,我们可以使用与 Windows 和 macOS 相同的命令:pip 命令。
对于这个场景,我们首先需要确保安装了 Python 3 版本的 pip,它被称为 pip3,由 python3-pip 包提供。我们将通过包管理系统安装这个包:
sudo apt install python3-pip
安装 pip3 后,我们就可以使用各种各样的外部模块来解决问题了。
例如,想象一下你的任务是创建一个自动化程序,用于处理我们 Web 服务的错误日志,然后生成关于错误数量或错误最常发生时间的统计数据。要进行这种数据处理,我们可以使用我们听起来最可爱的模块之一:pandas,它在数据分析领域被广泛使用。
让我们使用 pip3 安装 pandas 模块:
pip3 install pandas
现在我们已经安装了 pandas 模块,让我们用一些示例数字来试试看。
首先,导入模块。显然,由于这是一个数据分析工具,我们需要一些数据来使用它。
让我们从与网站相关的数据中生成几个示例列表。例如,一个过去五天访问者数量的列表:
visitors = [1235, 6420, 8570, 5390, 2050]
让我们再添加一个列表,包含同五天内生成的错误数量:
errors = [23, 45, 33, 45, 76]
现在我们有了这两个列表,可以用它们来生成一个 DataFrame,这是 pandas 模块用于数据分析的主要数据结构。
我们将使用列表生成 DataFrame,并添加星期几作为索引:
import pandas as pd
df = pd.DataFrame({'visitors': visitors, 'errors': errors}, index=['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
这样,我们就有了一个可以用于操作的 DataFrame。例如,我们可以以一种格式美观的方式打印它:
print(df)
打印东西总是很有趣,但这并不是真正的数据分析。pandas 模块允许我们对每列的数字进行操作。例如,我们可以使用 mean 方法计算其中一列的平均值:
print(df['errors'].mean())
总结
在本节课中,我们一起学习了如何在 Linux 系统上配置 Python 环境。我们首先检查了 Python 2 和 Python 3 的安装情况,并强调了使用 Python 3 的重要性。接着,我们探讨了两种安装和管理 Python 模块的方法:通过发行版自带的包管理系统(如 apt、yum)和通过 Python 专属的包管理工具 pip(具体是 pip3)。我们通过安装 PIL 模块处理图像和安装 pandas 模块进行数据分析两个实例,演示了这两种方法的具体操作。掌握这些技能将帮助你为后续的 Python 自动化编程准备好所需的环境和工具。

你已经准备好用它来玩点有趣的东西了吗?在下一个视频中,我们将讨论解释型语言和编译型语言,期待与你相见。
081:解释型与编译型语言 🧠


在本节课中,我们将要学习编程语言的两大主要类别:解释型语言与编译型语言。理解它们的区别,能帮助我们明白为何Python脚本能在不同操作系统间轻松运行,以及不同语言在开发效率和执行速度上的权衡。
我们之前提到过,可以在Windows电脑上用Python编写脚本,然后在Linux电脑上运行同一个脚本,反之亦然。对于许多其他解释型语言编写的脚本,情况也是如此。
你可能会问,什么是解释型语言?要理解它,我们需要先看看传统的编程语言(如C语言)是如何工作的。
编译型语言的工作原理 ⚙️

当你想要运行一个用C这类传统编程语言编写的程序时,源代码会被输入到一个叫做编译器的软件中。
编译器将此代码翻译成机器语言。这意味着生成的语言是针对其运行的计算机底层架构(如特定的CPU指令集)而特定的。
公式表示:
源代码 -> 编译器 -> 机器码(特定于平台)
计算机可以直接读取和执行机器码。这使得编译后的程序运行速度极快,但编译过程本身可能需要一些时间。
以下是一些常用的编译型编程语言示例:
- C
- C++
- Go
- Rust
解释型语言的工作原理 🐍
与编译型语言相反,用解释型语言编写的程序通常依赖于一个叫做解释器的中间程序。


这些程序使用解释器来执行代码中指定的指令,而不是先通过编译器进行编译。
公式表示:
源代码 -> 解释器(逐行读取并执行) -> 运行结果
这使得用解释型语言编写的程序开发周期更快,因为开发者无需等待代码编译完成即可执行它。
并且,相同的代码可以被运行在不同操作系统上的解释器读取,而无需进行任何额外修改。
其代价是,解释型语言的运行速度通常慢于编译型语言。
以下是一些解释型编程语言的示例:
- Python
- Ruby
- JavaScript
- Bash
- PowerShell
混合型方法:两全其美? 🔄
上一节我们介绍了纯粹的解释和编译,本节中我们来看看一种折中的方法。Java和C#是采用混合方法的语言。

代码需要先被编译,但它被编译成中间代码。这意味着它不是被编译成针对当前操作系统的特定机器语言,而是被编译成可以在不同平台上执行的可移植代码。
我们使用一个特定于操作系统的程序来执行这段中间代码:对于Java是Java虚拟机,对于C#是公共语言运行时。
流程表示:
源代码 -> 编译器 -> 中间码(如Java字节码) -> 平台特定运行时(如JVM) -> 运行结果
跨平台运行的实践意义 💻
让我们通过一个例子来理解这些概念的实际影响。假设你有一个用C语言编写的程序,并且你在Windows上运行它。

但你想在Linux服务器上运行这个程序。要在与你当前运行环境不同的操作系统上运行该程序,你需要在目标操作系统上重新编译它。


在我们的例子中,这意味着你需要在Linux操作系统上编译源代码,最好是在与目标服务器安装了相同版本库的Linux系统上进行编译。


相反,如果你用Python编写程序源代码,情况就不同了。无论你是在Windows、macOS还是Linux上运行,你都可以在本地编写和测试程序,然后直接将脚本复制到服务器上,无需修改即可使用。

这是因为Python解释器本身是一个针对特定平台编译的可执行文件。但一旦你安装了它,就可以在任何地方运行你的脚本。

本节课中我们一起学习了编程语言的两种主要类型。编译型语言(如C)通过编译器生成高效的机器码,运行速度快,但依赖特定平台。解释型语言(如Python)通过解释器逐行执行,跨平台性好,开发周期快,但运行速度相对较慢。此外,我们还了解了像Java这样的混合型语言,它结合了编译和解释的特点。
好了,我们已经讨论了很多关于运行Python脚本的内容。是时候开始动手实践了!请继续观看下一个视频,我将带你一步步创建并运行一个Python脚本。😊
082:如何运行Python脚本 🚀

在本节课中,我们将学习如何运行Python脚本。我们将介绍几种不同的运行方式,并重点讲解如何在命令行中执行Python脚本。通过本课,你将掌握如何创建和运行可执行的Python脚本。
概述
Python脚本可以通过多种方式运行。本课程将重点介绍在基于Linux的环境中从命令行运行脚本的方法。虽然我们使用Ubuntu作为示例,但这些技巧稍作调整后也适用于Windows或Mac OS。
运行Python交互式解释器
当我们运行python3命令时,会启动一个交互式解释器。该解释器会显示Python版本信息、编译器详情以及一些使用建议。
在交互式解释器中,我们可以执行所有在Python入门课程中学到的操作。例如,打印“hello”10次:
print("hello" * 10)
这种方式适合实验和尝试新概念,但代码在关闭解释器后不会被保存。
创建和运行Python脚本文件
为了使代码持久化,我们可以将其存储在文件中。Python脚本通常以.py扩展名结尾,例如hello_world.py。
在Linux系统中,可以使用cat命令查看文件内容:
cat hello_world.py
要运行保存在Windows系统中的Python脚本,只需键入脚本名称,操作系统会根据文件扩展名识别为Python可执行文件。
在Linux和MacOS上,可以通过调用Python解释器后跟文件名来执行脚本:
python3 hello_world.py
这里,python3命令会读取hello_world.py的内容,并指示计算机执行文件中的指令。
使用Shebang行简化脚本执行
每次运行脚本时都输入python3可能会很繁琐。我们可以通过在文件开头添加一行特殊的注释(称为Shebang行)来避免这种情况。Shebang行告诉操作系统使用哪个命令来执行该脚本。
以下是添加Shebang行的步骤:
首先,在编辑器中打开文件。在Linux系统中,可以使用nano编辑器:
nano hello_world.py
然后,在文件开头添加以下魔法行:
#!/usr/bin/env python3
这行代码告诉操作系统我们希望使用python3来运行脚本。
保存并退出编辑器(在nano中按Ctrl+X,然后确认保存并接受原文件名)。
现在,系统知道应该使用Python解释器执行该文件。
使脚本文件可执行
为了能够直接运行脚本而无需每次调用解释器,我们需要使用chmod命令使文件可执行。该命令允许我们更改文件权限。

文件的可能权限包括读、写和执行。为了直接运行文件,我们需要使其可执行:
chmod +x hello_world.py
将脚本标记为可执行后,我们现在可以通过在脚本前加上./来运行它:
./hello_world.py
因为脚本已被标记为可执行,并且解释器的路径已在第一行指定,操作系统将运行该解释器并将脚本名称传递给它。这意味着运行./hello_world.py等同于运行python3 hello_world.py。这种方法在Linux和Mac OS上完全相同。

为什么需要./前缀?
你可能会好奇为什么我们需要在脚本前加上./,而不是直接写脚本名称。原因是脚本不在PATH变量列出的任何目录中。PATH变量告诉操作系统在哪里查找要执行的程序。
./表达式中的点代表当前目录,因此我们基本上是告诉操作系统在当前目录中找到脚本并执行它。
总结
本节课中,我们一起学习了如何运行Python脚本。我们介绍了从交互式解释器执行代码、创建和运行脚本文件、使用Shebang行简化执行过程,以及使脚本文件可执行的方法。掌握这些基础技能对于后续的Python编程至关重要。
现在,你可以尝试在自己的机器上练习运行脚本。如果有任何不清楚的地方,建议回顾本视频并多次练习。接下来,我们将进入更令人兴奋的内容:创建自己的Python模块。
083:创建你自己的Python模块 🧩
在本节课中,我们将要学习如何创建和使用Python模块。模块是组织和重用代码的强大工具,它能让你将函数、类和其他代码块保存在独立的文件中,并在不同的脚本中轻松调用。
概述
我们已经学会了安装Python、运行本地脚本以及创建可执行文件。在编程中,我们经常需要重用自己或他人编写的代码,这被称为代码重用。函数是实现代码重用的基础,它允许我们将代码分组为逻辑块,以便后续多次执行。然而,随着脚本变得越来越大、越来越复杂,我们可能需要重用整个脚本或其他程序。
代码重用的挑战
假设你编写了一个脚本,用于向经理发送每日完成工单的摘要邮件。该脚本有两个主要任务:首先,通过与公司的问题跟踪系统交互,组装你关闭的工单列表;其次,使用该列表创建邮件并发送给经理。
在另一个项目中,假设你需要自动解析系统日志并搜索其中的特定事件。如果在日志中找到该事件,你希望触发邮件通知自己。

你能发现这两个脚本之间的功能重叠吗?两个自动化项目都需要发送邮件消息。
最直接的方法是复制邮件发送代码,从一个Python文件复制到另一个。


整体来看,这似乎很简单。但以这种方式复制代码有一些明显的缺点。
以下是主要问题:
- 每次需要对任一脚本进行更改时,你必须记住在两个地方都进行修改。这意味着你需要进行两次更新和错误修复。
- 如果你的同事想在他们自己的项目中使用你编写的相同邮件代码,他们可能也需要创建新的副本。
- 跟踪所有代码被复制的位置会很快变得棘手,共享不同版本也是如此。


解决方案:创建Python模块
为了避免维护多个代码副本的麻烦,我们可以将想要重用的代码放入一个单独的模块中。这样,我们的脚本和同事的脚本就可以导入我们的代码,而无需创建多个副本。
首先,我们需要创建自己的Python模块。方法是将想要成为模块一部分的内容放入一个单独的文件中。要使用该模块,我们将使用文件名导入它。
我们可以使用点表示法访问文件中定义的每个函数、类和变量。

让我们通过一个例子来实践。我们有一个名为 areas.py 的文件,其中包含计算不同几何图形面积的函数。
我们可以使用 cat 命令查看该文件的内容。
以下是该模块定义的三个函数:
import math
def triangle(base, height):
return base * height / 2
def rectangle(length, width):
return length * width
def circle(radius):
return math.pi * (radius ** 2)
circle 函数使用了 math.pi 常量,这就是为什么我们在顶部导入了 math 模块以便使用它。
我们已经看到函数定义在 areas.py 文件中。要在解释器或脚本中使用它们,我们可以通过输入 import areas 来导入模块。
让我们实际操作一下。
import areas
完美,我们现在已经加载了 areas 模块,并可以使用它来计算面积。
让我们计算一个三角形和一个圆的面积来测试一下。
print(areas.triangle(3, 5)) # 输出:7.5
print(areas.circle(2)) # 输出:12.566370614359172
更复杂的模块结构
我们的 areas 模块非常小巧简单,因此可以很好地放在一个文件中。在某些情况下,我们处理的代码可能变得更加复杂,将其拆分为子模块可能更有意义。

在这种情况下,我们会创建一个以模块命名的目录,并为每个子模块创建单独的 .py 文件。
为了理解这一点,让我们使用 ls -l 命令查看这台计算机上安装的一个模块——requests 模块的文件列表。

这个模块非常复杂,因此它所做的所有事情都被拆分到单独的文件中。
请注意那个 __init__.py 文件。这是一个特殊文件。当模块被导入时,解释器会读取它,并用它来检查一个包含Python文件的目录是否应该被视为一个模块。
因此,如果你有一个被拆分成多个文件的模块,并且你希望解释器将该目录识别为一个模块,你需要创建 __init__.py 文件。即使你没有任何内容要放入这个文件,你也需要创建它。你可以让它保持为空,但它必须存在,解释器才能将该目录识别为Python模块。
总结
本节课我们一起学习了如何创建和使用Python模块。我们了解了简单复制代码的缺点,并学会了通过创建模块来优雅地实现代码重用。我们还探讨了模块的基本结构,以及对于更复杂的代码,如何通过创建包含 __init__.py 文件的目录来组织子模块。
虽然这些概念一开始可能有点复杂,但通过持续练习,你会逐渐掌握它们,直到能够熟练运用。
084:什么是IDE? 🖥️

概述
在本节课中,我们将要学习什么是集成开发环境(IDE),以及它如何帮助我们更高效地编写Python脚本。我们将探讨代码编辑器的基本功能,如语法高亮和代码补全,并了解如何选择适合自己的开发工具。
当你开始编写自己的脚本时,最终会遇到一些提及IDE的网站。
这个术语代表集成开发环境,通常指一个带有一些便捷额外功能的代码编辑器,这些功能使编写脚本变得容易得多。
我们大部分编程工作都在代码编辑器和IDE中完成。
因此,找到一个让你感到最舒适和最高效的工具非常重要。
现在花些时间了解几个编辑器和IDE,以找到你最喜欢的那一个,这是一个好主意。
市面上有很多不同的编辑器。有些只有少量附加功能。
而另一些则有很多功能。代码编辑器中最基本的额外功能之一是语法高亮。
这意味着编辑器能识别我们编写代码所用的语言,并高亮显示构成该语言语法的代码片段。
让我们在Linux上可用的一个名为Vim的文本编辑器中看看这个功能。
Vim包含语法高亮功能,所以如果我们在Vim中打开之前展示过的areas.py文件。
我们将看到代码包含了用于高亮语法的颜色。
我们可以看到,像def或return这样的保留关键字以一种颜色显示,函数名称以另一种颜色显示,甚至数字也以另一种颜色显示。要退出Vim,输入:q。
代码编辑器提供的另一个常见功能叫做代码补全。
让我们在另一个名为Atom的编辑器中查看这个功能的使用。
这里我们在Atom中打开了我们的areas模块。我们看到它也使用了语法高亮。
颜色不同,但理念相同。现在,让我们编写一个名为donut的新函数。
该函数将计算一个二维甜甜圈的面积为两个圆的面积之差。donut。
当我输入def时,编辑器告诉我这是一个用于编写新函数的关键字。
输入函数名后,我输入左括号,编辑器知道后面会有一个右括号。
所以它为我写上了。定义函数后,当我按下回车键时。
编辑器知道代码需要向右缩进。
所以它自动将光标定位在那里。很有帮助,对吧?😊
现在,当我输入ret时。
编辑器建议我可能想输入return。就像它能读懂我的心思一样。按下Tab键。

我接受了建议,于是我的ret被补全为return。很好。
让我们用Ctrl+S保存,并用Ctrl+Q关闭我们的程序。
这就是代码补全的力量。当你需要编写大量代码时。
有一个能自动补全变量和函数名的编辑器可以节省你大量时间。
你如何编写源代码取决于你的个人品味、偏好。

以及你的平台可用的应用程序。你可以使用计算机上已经安装的任何工具,比如Windows上的Notepad。
Mac OS上的TextEdit,或Linux上的Nano。
你可以选择更高级的代码编辑器,如Atom、Notepad++或Sublime Text。
或者选择功能齐全的图形化IDE,如Eclipse或PyCharm。
一旦你找到了最喜欢的工具,花时间熟悉编辑器的功能是值得的,这样你就能充分利用它。
请随意尝试编写一些脚本并执行它们,直到你感到编辑Python脚本很自如为止。
现在提醒一句。作为一名IT专家,你不想完全只依赖一个编辑器。
你可能需要在一台安装了不同编辑器的计算机上调试问题,而你不想浪费时间安装你偏爱的编辑器。
所以请确保你对如何使用你工作计算机上默认安装的编辑器有一个基本的了解。
像Atom或Eclipse这样具有额外功能的图形化代码编辑器非常方便,可以节省我们大量时间。
但你也应该至少学会使用一个命令行编辑器,比如Vim、Emacs或Nano,以备无法使用图形化编辑器之时。例如。
你可能需要连接到一个运行在云端的远程服务器,在那里你将无法使用图形化编辑器。我们已经讨论了很多关于设置环境的内容,你现在可以编写和运行你自己的Python脚本和Python模块了。接下来。
我们有一篇补充阅读材料,提供更多信息。然后有一个测验,以再次确认你掌握了所有这些新概念。
😊
总结
本节课中我们一起学习了集成开发环境(IDE)的概念及其核心功能。我们了解了语法高亮和代码补全如何提升编码效率,并探讨了从简单文本编辑器到功能齐全的IDE等多种工具的选择。重要的是,作为IT专家,我们应灵活掌握多种编辑器,包括命令行工具,以适应不同的工作环境。现在,你可以更自信地选择和使用工具来编写和运行Python脚本了。
085:自动化的好处 🚀


在本节课中,我们将探讨自动化在IT工作中的核心价值,理解它如何提升效率、可靠性与可扩展性,并初步认识自动化可能带来的风险。
在Python课程的介绍中,我们讨论了自动化对一系列活动的好处,例如执行重复性任务、分析文本、生成报告等。本课程中,我们将通过将自动化应用于越来越多的任务来深化这些概念。
作为一名IT专家,经过深思熟虑应用的自动化可以在你的工作中发挥重要作用。
你可以将自动化视为IT的“力量倍增器”——一种无需增加团队成员数量,就能提升IT团队效能的工具。
换句话说,自动化可以使IT基础设施实现扩展,从而跟上增长和需求的步伐。可扩展性意味着当系统被赋予更多工作时,系统能够完成所需的一切以处理这些工作。


自动化如何提升可扩展性 📈
上一节我们介绍了自动化作为力量倍增器的概念,本节中我们通过一个具体例子来看看它如何提升可扩展性。
例如,思考一下公司雇佣新员工时对IT部门的影响。
新员工可能需要访问一系列技术资源来完成工作。入职任务可能包括创建用户账户、邮箱和主文件夹,以及设置适当的权限以控制对各种系统和资源的访问。

如果公司在特定时期内雇佣的员工不多,每次有新员工加入时,可以有人手动执行这些任务,尽管我敢打赌这很快就会变得非常乏味。
但随着新员工数量的增加,在系统中为他们所有人进行设置所需的时间也会增加。

如果公司在一周内雇佣的新员工数量是平时的10倍,负责的IT人员可能会发现自己除了设置新员工账户外什么都做不了,同时也会感到抓狂。
他们可能不得不将一堆其他项目搁置,直到设置完所有账户。作为人类,他们也可能会在配置过程中犯一些错误,比如拼错名字、忘记某个步骤,或者给用户账户分配错误的权限。然后他们必须修复这些错误,这意味着更多的工作。
现在,想象一下如果公司继续以这个速度招聘。他们可能需要指派另一名IT专家来处理因所有新账户设置而被忽视的工作。或者,工作量可能大到需要两名IT专家来负责账户设置。
基本上,这在财务资源、精力投入或可靠性方面都无法很好地扩展,尤其是当公司持续增长时。如果新员工的雇佣率翻倍、翻三倍,甚至增长得更大呢?仅仅投入更多人力来解决问题很快就会变得不切实际。
从手动到自动:改进流程 🔄
既然我们都认识到手动入职流程存在问题,那么让我们思考一下如何通过自动化来改进这个过程。
与其让一个人与每个独立的系统交互来创建新用户账户、邮箱、共享文件夹和权限,更高效的做法是让IT专家编写一个脚本来完成所有这些工作。
我们可以让计算机在每次雇佣新员工时执行这些任务。当给定初始信息,如新员工的姓名和职位时,该脚本可以自动执行每个步骤,因此人类只需要在任务因某种原因失败时才进行干预。

计算机会按照脚本中给定的顺序,以完全相同的方式执行每个步骤,永远不需要偏离这些指令。
我们甚至可以进一步改进脚本:与其每次运行时都让IT专家将新员工的信息输入脚本,不如让脚本直接从公司的人力资源系统中读取数据。
这将使整个工作流程在员工入职日期自动开始。
在这个自动化示例中,我们使一项重复且耗时的任务变得更快、更可靠。我们还释放了人力资源,让IT专家能够专注于更具战略性或创造性的工作。

自动化的额外优势:集中化错误处理 ✅


自动化另一个微妙但极其有用的好处是集中化错误。
这意味着如果你在脚本中发现一个错误,你可以一劳永逸地修复它,这当然与人类犯的错误不同。
希望你现在比之前更加确信自动化的好处了。
总结与前瞻 📝
本节课中我们一起学习了自动化的核心好处:它作为力量倍增器提升团队效能,通过脚本处理重复任务实现可扩展性,提高工作速度与可靠性,释放人力资源,并能集中化处理错误。
但正如我们之前所说,自动化并非万能药。如果执行不当,自动化造成的问题可能和它解决的问题一样多。为了避免这种情况,我们需要了解它可能出错的方式。因此,接下来,让我们探讨一些自动化可能失败的情形。
086:自动化的缺陷 🚧


在本节课中,我们将探讨自动化在带来巨大便利的同时,可能引发的一些严重问题。我们将学习如何评估是否应该自动化一个任务,以及如何设计自动化流程以避免常见的陷阱,如静默失败和错误操作。

毫无疑问,自动化让我们的生活轻松许多。尽管它有很多好处,但如果实施时缺乏深思熟虑的设计,也可能导致一些严重问题。
让我们看看自动化可能失败的几种方式,以及我们可以采取哪些措施来避免它们。
权衡:是否值得自动化?⚖️

我们自动化的任何任务或流程都需要权衡利弊。编写脚本所需的时间和精力,是否值得潜在的自动化收益?

一个简单的启发式方法可以帮助我们做决定:估算完成某项任务所需的时间,然后乘以在给定时间窗口内执行该任务的次数。如果我们估计自动化该任务所需的时间少于手动完成的时间,那么它很可能是一个适合自动化的候选任务。


公式:自动化时间 < (单次任务时间 × 执行次数)
让我们看一个现实世界的例子。假设你每天生成一份系统使用报告,每天需要花费5分钟。

如果自动化这个任务需要你1小时,那么在12天后,你就已经节省了创建自动化所花费的60分钟。这将是一个很好的时间利用方式,因为它每天能为你腾出那5分钟去做其他事情。
相反,如果创建自动化需要你10小时,那么就需要120天或24个工作周才能开始在该任务上节省时间。这几乎是六个月,你才能开始收获自动化的好处。甚至有可能到那时,报告的要求已经改变,需要你投入更多时间。
通常,是否自动化的决定并不那么直接。如果一个任务很复杂且不常执行,自动化可能看起来比它的价值更麻烦。但请记住,一旦任务被自动化封装,任何人都可以执行它。对于一个复杂且容易出错的任务,如果确保其正确执行至关重要,即使它不经常执行,自动化也非常有用。
关于何时自动化没有硬性规定,但成本与时间的权衡可以帮助指导你的决策。
帕累托原则的应用 📊

一个称为帕累托原则的概念,也可以作为决定自动化哪些任务的有用指南。

当应用于IT自动化时,帕累托原则指出,你所执行的20%的系统管理任务,占用了你80%的工作量。
如果你能识别并自动化那20%的任务,你就可以为自己节省大量时间。

自动化的脆弱性与“比特腐烂” 🧱

知道何时自动化最好是很棘手的,而一个已实施的自动化可能是脆弱的。如果底层系统发生变化,而自动化没有相应更新,工作流程就可能中断。

想象一个自动备份系统,它定期保存销售数据库的内容。假设自动备份程序使用一个磁盘标识符(如 /dev/sda1)来知道要保存的数据存储在哪里。

如果服务器添加了新磁盘,并且这个标识符变成了 /dev/sdb1,会发生什么?自动化将无法再访问它认为应该备份的磁盘,从而导致失败。
这种软件与环境脱节的过程有时被称为“比特腐烂”。脚本中的实际比特并不会真正腐烂,腐烂的是脚本所依赖的关于环境的隐含假设。
处理错误与静默失败 🔔
思考你的自动化将如何处理错误非常重要。自动化系统在没有人工干预的情况下执行操作,因此很容易“设置后即忘记”。如果一个自动化系统失败且未被察觉,后果可能非常严重。

让我们重新审视我们的备份示例。想象一下,备份因磁盘标识符更改而失败,但没有人注意到。一段时间后,销售数据库服务器崩溃,需要恢复数据。当IT专家发现自动化系统已经有一段时间没有备份时,他们会大吃一惊。


对自动化系统的错误信心也可能影响决策。例如,如果数据库需要升级,系统管理员可能更愿意进行有潜在风险的操作,因为他们相信可以从备份中恢复数据。
那么,我们如何避免这些静默失败呢?你可以在自动化系统中构建一种通知方法。这样,当自动化失败时,会通知人类,人类可以介入调查。
这种通知方法可以是一封电子邮件、内部问题跟踪器中的新条目、仪表板的更新,甚至是向负责该服务的值班人员发送的传呼。无论采用哪种方法,重要的是通知服务能报告错误,以便人员可以修复自动化。


错误的成功与定期测试 ✅
比自动化失败更糟糕的是,自动化成功执行,但执行了错误的操作。在我们之前的例子基础上,如果备份系统正确地执行了任务,但被配置为备份了错误的数据,会怎么样?
恢复错误的销售数据可能导致数据丢失甚至数据损坏,例如客户可能被收取错误的金额或被收取未购买产品的费用。


有时,任务完成了,但完成得不正确。对于这种更微妙的失败类别,我们可以使用定期测试来检查自动化系统的行为。
在我们的备份系统示例中,我们可以安排定期从销售数据库恢复数据,然后检查恢复的数据是否是你预期备份的内容。这个测试过程也可以自动化,编写脚本来安排恢复并将数据与某个主数据集进行比较。
同样,如果恢复过程的任何部分失败,自动化系统可以停止以防止进一步的数据损坏,并向可以调查问题的人员发送通知。

日志记录与调试 🗒️

除了标记问题,良好的自动化还会通过记录其执行的操作来简化调试。系统日志在调查问题时是非常有用的信息来源,我们说它具有取证价值。我们的脚本也可以配置为写入系统日志。这样做会创建一个有用的故障排除信息审计跟踪,有助于调试过程。
总结 📝
本节课中,我们一起学习了自动化的潜在缺陷。自动化是一个极其强大的工具,可以节省时间、减少错误并促进增长和可扩展性。但我们需要深思熟虑地应用它,以避免使用它时可能产生的一些陷阱。请记住以下几点:
- 权衡利弊:使用
自动化时间 < (单次任务时间 × 执行次数)的公式来评估是否值得自动化。 - 应用帕累托原则:优先自动化那占用你80%工作量的20%的关键任务。
- 警惕“比特腐烂”:自动化依赖于环境假设,当环境变化时,自动化可能失效。
- 避免静默失败:为自动化系统构建错误通知机制,确保失败能被及时发现。
- 进行定期测试:验证自动化系统是否在执行正确的操作,而不仅仅是“成功”运行。
- 记录操作日志:为自动化过程创建审计跟踪,以便于调试和问题排查。
将这些要点牢记于心,自动化就能成为你工具箱中的一个宝贵资产。
087:实际自动化示例 🛠️

在本节课中,我们将学习如何利用Python编写一个实际的自动化脚本,用于检查计算机的健康状态。我们将通过两个具体的检查示例——磁盘空间使用率和CPU使用率——来演示自动化脚本的编写过程。
概述
我们已经讨论了自动化的好处以及我们需要做的准备工作。现在,让我们来看一个使用Python实现自动化的具体例子。假设你需要检查计算机的健康状态,这可能涉及多种检查,例如验证磁盘空间是否充足、处理器是否过载、是否安装了最新的安全更新,以及是否运行了应有的服务。为了验证所有这些,我们需要知道如何检查每一项指标。当然,我们将利用一些方便的模块来实现这些检查。
检查磁盘空间使用率
首先,我们来看看如何检查磁盘空间使用率。为此,我们可以使用shutil模块中的disk_usage函数。这个函数能够返回磁盘的总字节数、已使用的字节数和空闲的字节数。
以下是检查磁盘空间使用率的步骤:
- 导入
shutil模块。 - 调用
disk_usage函数获取磁盘使用情况。 - 计算空闲磁盘空间的百分比。
让我们在交互式解释器中尝试一下:
import shutil
du = shutil.disk_usage("/")
print(du)
执行上述代码后,你将看到类似以下的输出:
usage(total=250685575168, used=100685575168, free=150000000000)
这表示磁盘的总字节数、已使用的字节数和空闲的字节数。我们可以通过以下公式计算空闲磁盘空间的百分比:
空闲百分比 = (空闲字节数 / 总字节数) * 100
检查CPU使用率
接下来,我们检查CPU的使用率。为此,我们可以使用psutil模块中的cpu_percent函数。这个函数返回一个数字,表示CPU的使用百分比。
由于进程随时都在启动和结束,每个瞬间的CPU使用率可能会有很大变化。因此,cpu_percent函数接受一个以秒为单位的时间间隔参数,并返回该时间间隔内的平均使用率百分比。
以下是检查CPU使用率的步骤:
- 导入
psutil模块。 - 调用
cpu_percent函数,并指定一个时间间隔(例如0.1秒或0.5秒)。

让我们在交互式解释器中尝试一下:
import psutil
psutil.cpu_percent(0.1)
多次执行上述代码,你会发现每次返回的值可能不同。这是因为CPU使用率在短时间内会有波动。如果你将时间间隔设置为0.5秒,函数需要更长的时间来计算平均值,但返回的结果会更加稳定。
psutil.cpu_percent(0.5)

编写健康检查脚本
现在我们已经完成了研究,可以开始编写我们的健康检查脚本了。我们将创建一个脚本,执行两项健康检查:磁盘空间使用率和CPU使用率。
以下是脚本的编写步骤:
- 设置脚本使用Python解释器。
- 导入所需的模块:
shutil和psutil。 - 定义两个函数:一个用于检查磁盘使用率,另一个用于检查CPU使用率。
- 编写脚本的主体部分,调用这两个函数并根据结果输出相应的消息。
以下是完整的脚本代码:
#!/usr/bin/env python3
import shutil
import psutil
def check_disk_usage(disk):
"""检查磁盘使用率,如果空闲空间大于20%则返回True,否则返回False"""
du = shutil.disk_usage(disk)
free = du.free / du.total * 100
return free > 20
def check_cpu_usage():
"""检查CPU使用率,如果使用率小于75%则返回True,否则返回False"""
usage = psutil.cpu_percent(1)
return usage < 75
# 主程序
if not check_disk_usage("/") or not check_cpu_usage():
print("错误:计算机健康状态异常!")
else:
print("一切正常。")


保存并运行脚本
完成脚本编写后,我们需要保存它,使其可执行,并运行它。以下是具体步骤:
- 将脚本保存为
health_check.py。 - 在终端中,使用
chmod +x health_check.py命令使脚本可执行。 - 运行脚本:
./health_check.py。
如果一切正常,你将看到输出:“一切正常。” 如果磁盘空间不足或CPU使用率过高,脚本将输出错误消息。
总结
在本节课中,我们一起学习了如何编写一个实际的自动化脚本,用于检查计算机的健康状态。我们通过两个具体的例子——检查磁盘空间使用率和CPU使用率——演示了如何使用Python的shutil和psutil模块来实现自动化检查。
通过这个练习,你不仅掌握了如何检查系统资源,还学会了如何将多个检查组合成一个完整的自动化脚本。随着课程的深入,我们将探索更多实际的自动化示例,并将这些知识应用到你的工作中。
记住,学习自动化需要一些手动工作,这其中的讽刺意味我们心知肚明。所以,卷起袖子,在你的计算机上练习这些脚本吧!如果你在某些地方感到困惑,随时可以回看课程内容。无论你是需要复习,还是准备直接进入下一个练习测验,你都做得很棒,继续加油!🚀
088:Python与操作系统入门 🐍💻

在本课程中,我们将学习Python编程语言的基础知识,以及如何利用Python与操作系统进行交互,实现自动化办公。课程内容涵盖操作系统的概念、Python的安装与运行、模块创建、开发环境设置以及自动化的基本理念。

恭喜你完成了本课程的第一个模块,并且成功通过了第一次创建性评估,正如我所预料的那样。
在过去的视频中,我们涵盖了大量内容,请花点时间为自己祝贺一下。
说真的,你应该为此感到非常自豪。不是每个人都能像你一样坚持下来。
让我们快速回顾一下你所学到的内容。我们讨论了一些新概念,其中一些你可能已经有所了解。
我们讨论了什么是操作系统,以及它们为何与IT世界相关。
我们讲解了如何在你的计算机上安装Python,如何运行Python脚本,如何创建我们自己的模块,以及如何通过选择一个代码编辑器来设置你的开发环境。
我们还进一步学习了自动化,包括它的好处和潜在的缺点,并查看了一些适合使用自动化的场景示例。
我们浏览了一个实际的自动化示例,随着课程的深入,这个示例将不断扩展。
最后但同样重要的是,你完成了本课程的第一次快速练习。
在那里,你将所有新知识付诸实践。你修复了一个Python脚本中的问题,使其正确运行,并且你还编写并使用了你自己的Python模块。这真是太棒了。
干得漂亮。花点时间,给自己一点鼓励。😊
你的辛勤付出正在得到回报。如果需要的话,现在是时候休息一下,然后精神焕发地迎接下一个主题。
在下一个模块中,我们将讨论如何使用Python管理文件。我们那里见。
本节总结
本节课中我们一起学习了:
- 操作系统的定义及其在IT中的重要性。
- Python的安装与脚本运行方法。
- 如何创建和使用自定义Python模块。
- 如何设置个人开发环境(如选择代码编辑器)。
- 自动化的优势、潜在风险及应用场景。
- 通过实践练习巩固了所学知识,包括修复脚本和创建模块。
你已经为接下来的文件管理主题打下了坚实的基础。
089:使用Python编程操作文件系统 📂


在本节课中,我们将学习如何使用Python与计算机的文件系统进行交互。作为IT专家,经常需要处理大量文件和目录,自动化可以极大地提高效率。我们将探讨文件系统的基本概念、路径表示方法,并介绍如何使用Python来操作文件和目录。
文件系统基础 🗂️
上一节我们介绍了Python环境的设置和脚本执行,本节中我们来看看文件系统的基本结构。操作系统(如Windows、Linux、macOS)使用文件系统来组织和管理数据的存储与访问。
数据通常存储在磁盘上,并保存在文件中。文件则存放在称为“目录”或“文件夹”的容器中。
文件系统通常采用树形结构进行组织,目录和文件嵌套在其父目录之下。
我们通过“路径”来确定资源(如目录或文件)在树形结构中的位置。
绝对路径与相对路径 🧭

以下是两种主要的路径表示方法:

绝对路径是文件系统中资源的完整路径。无论脚本在文件系统的何处运行,绝对路径总能定位到目标资源。
例如:
- 在Windows计算机上,用户Jordan文件夹的绝对路径可能是:
C:\Users\Jordan - 在Linux计算机上,等效目录的绝对路径可能是:
/home/Jordan
相对路径仅使用路径的一部分,表示资源相对于“当前工作目录”的位置。相对路径是一种快捷方式,无需写出完整路径,但它的意义取决于当前位置。
例如,列出 examples 目录的内容:
- 如果当前目录是
/home/Jordan,则列出的是/home/Jordan/examples的内容。 - 如果当前目录是
/usr/share/doc/python3,则列出的是/usr/share/doc/python3/examples的内容。
后续内容预告 🚀
在接下来的视频中,我们将详细介绍如何使用Python来操作文件和目录,完成各种任务。
我们还将学习一种名为CSV的特定文件格式,用于读取和写入数据。
精彩内容即将开始,让我们继续前进。
本节课中我们一起学习了文件系统的基本概念,包括其树形结构、以及定位资源的两种方式:绝对路径和相对路径。理解这些概念是使用Python自动化文件操作的基础。
090:Python文件操作基础 - 第16课 📖

概述
在本节课中,我们将学习如何使用Python读取文件。我们将了解文件对象的基本概念,学习打开、读取和关闭文件的方法,并探讨两种不同的文件操作模式。
从变量到文件:为什么需要文件操作? 📂
在Python入门课程中,我们通过创建变量和向函数传递参数来为脚本提供信息。这种方法适用于小型脚本,但对于处理大量数据通常不够理想。
处理大量数据时,从文件中读取数据是一个更好的选择。在编程中,我们经常需要处理文件。这项任务非常有用,以至于大多数编程语言都将文件操作功能内置在其核心特性中。
Python也不例外。它为我们提供了文件对象,我们可以使用这些对象来读取和写入文件。

打开文件:创建文件对象 🔓
要打开计算机上名为Spidder.txt的文件,我们可以编写以下代码:
file = open("Spidder.txt")
我们在这里创建了一个新的文件对象,并将其赋值给名为file的变量。传递给open函数的参数是我们想要打开的文件名。
在这个例子中,我们假设要读取的文件与正在运行的脚本位于同一目录中。但我们也可以轻松地传递绝对路径来打开不同目录中的文件。

当我们打开一个文件时,操作系统会检查我们是否有权限访问该文件,然后为我们的代码提供一个文件描述符。这是操作系统生成的令牌,允许程序对文件执行更多操作。
在Python中,这个文件描述符作为文件对象的属性存储。文件对象为我们提供了许多可用于操作文件的方法。
读取文件内容:逐行与全部读取 📄
现在,有了这个文件对象,我们可以读取文件的内容并将其打印到屏幕上。
以下是使用readline方法的示例:
print(file.readline())
readline方法允许我们读取文件的单行。如果我们再次调用它,会发生什么?
print(file.readline())
很好,这次我们得到了文件的第二行。那么这是如何工作的呢?每次我们调用readline方法时,文件对象都会更新文件中的当前位置,因此它会不断向前移动。
我们还可以调用read方法,该方法从当前位置读取直到文件末尾,而不仅仅是读取一行。
print(file.read())
在这个例子中,文件总共有六行。我们通过两次readline调用读取了前两行,然后通过一次read调用读取了其余四行。

与readline类似,read方法从我们当前在文件中的位置开始读取。但它不是只读取一行,而是读取直到文件末尾。
关闭文件:为什么重要? 🔒
最后,我们将使用close方法关闭文件。
file.close()
这种“打开-使用-关闭”模式是大多数编程语言中处理文件的典型方式。打开文件后关闭它们有几个重要原因:
以下是关闭文件的主要原因:
- 文件锁定:当文件在脚本中打开时,文件系统通常会锁定它,因此在您完成之前,其他程序或脚本无法使用它。
- 文件描述符限制:在文件系统耗尽文件描述符之前,您可以创建的文件描述符数量是有限的。尽管这个数字可能很高,但打开大量文件可能会耗尽文件系统资源。例如,如果我们在循环中打开文件,就可能发生这种情况。
- 避免竞态条件:让文件保持打开状态可能导致竞态条件。当多个进程同时尝试修改和读取同一资源时,就会发生竞态条件,并可能导致各种意外行为。在竞态条件中,没有人是赢家。

使用with关键字:自动管理文件 🛡️
现在,我要告诉你一个小秘密:我最不擅长记住关闭文件。你可能会同意我的看法,跟踪打开了哪些文件并记住关闭它们可能相当困难。
幸运的是,Python的创建者同意这一点。因此,为了帮助我们记住在使用完文件后关闭它,Python允许我们使用with关键字创建一个代码块。
让我们看看这是什么样子:
with open("Spidder.txt") as file:
print(file.readline())
如你所见,with关键字允许我们创建一个代码块,其中包含我们想要对文件执行的操作。在这个例子中,我们想要从文件中读取一行数据并将其打印到屏幕上,这正是print(file.readline())所做的。

当我们使用with块时,Python会自动关闭文件,因此我们不需要自己记住关闭它。太好了,少了一件需要考虑的事情。谢谢你,Python。
两种方法的比较:with块与显式关闭 🔄
“打开-使用-关闭”方法和with方法各有优势。
使用with块是打开和处理单个文件的好方法,然后在块结束时自动关闭文件。另一方面,在块外使用open意味着我们可以在代码的其他地方使用文件对象,因此我们不仅限于单个块。但采用这种方法时,我们需要记住在完成后关闭它。
总结
在本节课中,我们一起学习了如何使用Python读取文件。我们了解了文件对象的基本概念,学习了如何打开文件、读取文件内容(包括逐行读取和全部读取),以及关闭文件的重要性。我们还探讨了使用with关键字自动管理文件的方法,并比较了两种不同文件操作模式的优缺点。
希望这节课能让你对如何打开、读取和显示文件感到相当舒适。在下一个视频中,我们将探讨一些遍历文件内容的方法。😊
091:遍历文件 📂

概述
在本节课中,我们将要学习如何使用Python读取和遍历文件内容。我们将探索几种不同的文件读取方法,理解如何处理文件中的特殊字符,并了解如何高效地处理不同大小的文件。
文件读取方法回顾
上一节我们介绍了read()和readline()方法,它们分别用于读取整个文件内容和单行内容。本节中我们来看看如何更灵活地遍历文件。
与Python中的列表或字符串类似,文件对象也可以被迭代。这在需要逐行处理文件时非常有用。
例如,如果我们想在打印前将每一行转换为大写,可以这样做:
with open('file.txt', 'r') as file:
for line in file:
print(line.upper())
处理换行符
执行上述代码后,你可能会注意到输出行之间出现了空行。这是因为文件中每行末尾都有一个换行符(\n)。
当Python逐行读取文件时,line变量会包含这个换行符。而print()函数在输出时又会添加一个换行符,这就导致了空行的出现。
为了避免这种情况,我们可以使用字符串的strip()方法移除每行周围的空白字符(包括换行符和制表符):
with open('file.txt', 'r') as file:
for line in file:
print(line.strip().upper())
现在,输出将不再包含多余的空行。
将文件内容读入列表
另一种处理文件内容的方法是使用readlines()方法将文件的所有行读入一个列表。
以下是具体步骤:
首先,打开文件:
file = open('file.txt', 'r')
然后,读取所有行到列表中:
lines = file.readlines()
最后,关闭文件:
file.close()
即使文件对象已关闭,lines变量仍然保存着文件内容的列表,我们可以对其进行操作。
例如,对列表进行排序并打印:

lines.sort()
print(lines)
这段代码有两个需要注意的地方:
- 行已按字母顺序排序,不再保持文件中的原始顺序。
- Python在打印字符串列表时,会使用
\n来显式表示字符串中的换行符。
转义序列
Python使用反斜杠(\)开头的转义序列来表示不可打印的字符。
常见的转义序列包括:
\n:换行符\t:制表符\'或\":用于在字符串中转义引号
处理大文件的注意事项
像read()或readlines()这样一次性读取整个文件的方法虽然方便,但在处理大文件时需要谨慎。
如果文件非常大(例如几百MB的日志文件),将其全部内容读入变量可能会占用大量计算机内存,导致程序性能下降。
对于小文件(如几KB),在内存中完全读取和处理是可行的。但对于大文件,更高效的做法是逐行处理。
总结
本节课中我们一起学习了:
- 使用
open()函数打开文件。 - 使用
read()和readlines()方法读取文件。 - 使用
readline()函数和for循环逐行迭代文件。 - 使用
strip()方法处理换行符和其他空白字符。 - 理解转义序列(如
\n和\t)的用途。 - 根据文件大小选择合适的读取策略。
下一节,我们将学习如何向文件中写入内容。
092:写入文件 📝

概述
在本节课中,我们将要学习如何使用Python向文件中写入内容。我们将了解不同的文件打开模式,特别是写入模式,并掌握如何安全地将数据写入文件,避免意外覆盖重要信息。
文件写入基础
上一节我们介绍了如何读取文件,本节中我们来看看如何写入文件。写入文件的语法与读取文件相似,但需要使用不同的模式。
with open('novel.txt', 'w') as file:
file.write("这是要写入文件的内容。")

在这段代码中,我们使用 with 块模式打开一个名为 novel.txt 的文件。对文件对象使用 write 方法可以将内容写入文件,而不是从中读取。open 函数的第二个参数是新的,它指定了文件的打开模式。
理解文件打开模式
文件对象可以用几种不同的模式打开。模式类似于文件权限,它决定了你可以对刚打开的文件执行什么操作。
默认情况下,open 函数使用 r 模式,代表只读。如果你尝试向以只读模式打开的文件写入内容,将会收到一个错误。
由于只读是默认模式,当我们只想读取文件时,不必将 r 作为第二个参数传递。然而,写入则是完全不同的情况。
w 字符告诉 open 函数,我们想以只写模式打开文件。如果文件不存在,Python 会创建它。如果文件已经存在,那么它的当前内容将被我们决定用脚本写入的任何内容覆盖。
重要注意事项
记住,当以只写模式打开文件时,你无法读取其内容。如果你尝试这样做,解释器会引发错误。
如果你想向已存在的文件添加内容,可以使用其他模式,例如 a 用于在现有文件末尾追加内容,或者 r+ 用于读写模式,在这种模式下你既可以读取内容,也可以覆盖它。
这一点曾让很多人不止一次地感到困惑。所以我要再说一遍:如果你打开一个文件进行写入,并且该文件已经存在,那么文件一打开,旧内容就会被删除。
想象一下,意外删除了文件中的重要内容。

选择正确的模式
所以请记住,仔细检查你是否使用了正确的模式打开正确的文件。
以下是选择模式时的一些指导原则:
- 如果你正在生成程序遇到的事件日志文件,你可能希望使用追加
a模式打开文件。以写入w模式打开意味着你将覆盖该文件中的任何先前条目,这对于日志文件来说不是一个好主意。 - 如果你正在生成报告并希望将其写入一个新文件,使用写入
w模式,你可能需要检查文件是否存在,以避免丢失任何先前的内容。
我们将在接下来的视频中学习如何检查文件是否存在。
write 方法的返回值
最后,我们代码末尾那个孤零零的 30 是做什么的?
characters_written = file.write("这是要写入文件的内容。")
print(characters_written) # 输出:30

这是 write 方法的返回值。当成功时,此方法返回它写入的字符数,所以在这个例子中是 30。
其他文件模式
除了只读、写入、追加和读写之外,open 函数还支持许多其他模式。你可以在官方参考文档中找到所有相关信息,我们将在下一篇阅读材料中提供链接。
总结
本节课中我们一起学习了如何使用Python向文件写入数据。我们了解了不同的文件打开模式(特别是 w 写入模式和 a 追加模式),知道了写入模式会覆盖现有文件内容,以及如何通过 write 方法的返回值获取写入的字符数。正确选择文件打开模式对于安全地进行文件操作至关重要。
干得漂亮!你刚刚学习了一些复杂的概念。如果一时难以理解,请查看即将提供的速查表,它将所有信息集中在一处供你参考。记住,如果你在任何时候感到困惑,你随时可以重新观看视频或在讨论区寻求帮助。
在过去的几个视频中,你学习了如何打开和读取文件、如何遍历文件,最后是如何写入文件。在处理文件时,我们经常使用这些操作,因此了解如何使用它们非常重要。
现在,请继续查看那个速查表,之后我们可以在Jupyter笔记本中动手练习所有这些内容。
093:Python文件操作进阶 🗂️

在本节课中,我们将学习如何使用Python的os模块进行更高级的文件操作,包括删除、重命名文件以及检查文件是否存在。这些技能对于自动化处理文件任务至关重要。
概述
在之前的课程中,我们学习了如何读取、遍历和写入文件内容。这些是处理文件时最常见的操作。然而,在编写脚本时,我们可能还需要执行其他任务,例如删除、重命名、移动文件,或获取文件的元数据信息(如最后修改时间或文件大小)。本节课,我们将探索Python中os模块提供的这些功能。
使用os模块进行文件操作
os模块在Python和操作系统之间提供了一个抽象层。它允许我们与底层系统交互,而无需关心我们是在Windows、Mac、Linux还是Python支持的任何其他操作系统上工作。这意味着你可以在一个操作系统(如Windows)上编写和测试脚本,然后在另一个操作系统(如Linux)上运行它。
但需要注意一点:不同操作系统的文件路径可能不同。因此,在代码中使用绝对路径时,我们需要确保能为目标平台提供替代方案。
os模块让我们能够执行几乎所有在命令行中处理文件时可以完成的任务。我们可以通过代码更改文件权限、删除或重命名文件。这意味着你可以编写脚本来自动执行这些操作。
删除文件
要删除文件,我们可以使用os模块的remove函数。以下是具体步骤:
- 首先导入
os模块。 - 然后调用
os.remove()函数,并传入要删除的文件名字符串。
import os
os.remove("novel.txt")
执行后,指定的文件novel.txt即被删除。如果尝试删除一个不存在的文件,该函数将引发一个FileNotFoundError错误。
重命名文件
我们可以使用rename函数轻松重命名文件。该函数的第一个参数是文件的旧名称,第二个参数是新名称。
import os
os.rename("first_draft.txt", "finished_masterpiece.txt")
在Python中,重命名文件就是这么简单。同样,如果对不存在的文件执行此操作,也会引发FileNotFoundError错误。
检查文件是否存在
那么,如何检查文件是否存在呢?os模块内部有一个专门处理文件信息(如文件是否存在)的子模块,称为os.path。我们可以使用该模块中的exists函数来检查文件是否存在。
以下是使用示例:
import os
print(os.path.exists("finished_masterpiece.txt")) # 如果文件存在,返回 True
print(os.path.exists("useless.txt")) # 如果文件不存在,返回 False

exists函数非常有用。我们可以在尝试读取文件之前用它来检查文件是否存在,或者在尝试写入文件之前验证文件是否已存在,这有助于避免数据丢失。
总结
本节课我们一起学习了如何使用Python的os模块进行基本的文件系统交互。我们掌握了删除文件的os.remove()方法、重命名文件的os.rename()方法,以及使用os.path.exists()检查文件是否存在。这些操作为自动化文件管理任务打下了基础。
在下一节视频中,我们将进一步探索如何获取文件的其他信息,例如文件大小、最后修改时间等更多元数据。敬请期待!
094:获取更多文件信息 📄

概述
在本节课中,我们将学习如何使用Python的os.path模块获取文件的详细信息,例如文件大小和最后修改时间。我们还将了解如何将相对路径转换为绝对路径,并探索时间戳的概念及其处理方法。
获取文件信息
上一节我们介绍了如何使用os.rename和os.remove等函数操作文件,以及如何使用os.path.exists检查文件是否存在。本节中,我们将学习如何获取文件的更多详细信息。
os.path模块提供了多种函数,帮助我们获取文件的各种属性。例如,要检查文件的大小,我们可以使用getsize函数,它返回文件大小的字节数。
import os
file_size = os.path.getsize('example.txt')
print(f"文件大小: {file_size} 字节")
要检查文件最后一次修改的时间,getmtime函数非常有用。让我们看看它是如何工作的。
import os
mod_time = os.path.getmtime('example.txt')
print(f"最后修改时间戳: {mod_time}")
理解时间戳
那个长长的数字是什么?它看起来不像时间,对吗?这是因为它是一个时间戳。具体来说,它是一个Unix时间戳。
Unix时间戳表示自1970年1月1日以来的秒数。这个日期看起来有点随机,但实际上有很好的历史原因。多年前,这个日期被采用来存储与文件和计算机相关的时间,因为那是Unix操作系统开始发布的时期。
Unix使用这个日期是因为在那个时间之前不可能有文件被创建。尽管Unix时间戳有50年的历史,但今天仍然非常普遍。文件系统使用它们来显示文件的创建、访问或修改时间,数据库等其他系统也使用它们。
作为IT专家,你在日常工作中肯定会遇到它们。但尽管如此,这个数字很难理解。我们可以使用datetime模块让它更容易被人阅读。
import os
from datetime import datetime
mod_time = os.path.getmtime('example.txt')
readable_time = datetime.fromtimestamp(mod_time)
print(f"可读的最后修改时间: {readable_time}")
这里,我们使用了datetime模块中datetime类的fromtimestamp方法。它使日期更容易理解。
路径处理
os.path模块中的函数获取操作系统提供的信息,因此无论我们运行什么操作系统,都可以在脚本中使用它们。我们可以检查文件的大小或最后修改日期,而无需知道机器运行的操作系统或文件存储的文件系统类型。这很方便,对吧?
这些函数的另一个很酷的特性是,我们可以同时处理相对路径和绝对路径。在我们的例子中,我们一直使用相对文件名,而不需要指定它们的完整路径。
在某些情况下,我们可能需要确切指定文件的位置,以便在脚本中处理它。这时abspath函数可以派上用场。
abspath函数接受一个文件名,并将其转换为绝对路径。Python使用当前工作目录(即运行脚本的位置)开始查找文件,并构建标识它的完整路径。

import os
abs_path = os.path.abspath('example.txt')
print(f"文件的绝对路径: {abs_path}")
如果我们想存储文件的完整路径,或者无论当前目录是什么都能访问文件,这非常有用。
探索更多功能
os和os.path模块中有更多函数让我们能够处理文件。但别担心,你不必全部记住。每当你需要对文件进行操作时,最好查看文档,研究有哪些可用的函数,找到你需要的函数。你会在下一节的阅读材料中找到文档的链接。
总结
本节课中,我们一起学习了如何获取文件的详细信息,包括文件大小和最后修改时间。我们了解了Unix时间戳的概念,并学会了如何使用datetime模块将其转换为可读格式。此外,我们还掌握了如何将相对路径转换为绝对路径,以便更灵活地处理文件。
现在是一个好时机,尝试在计算机上运行我们的例子,或者甚至自己想出一些例子,以真正掌握所有这些内容。不用着急,当你准备好的时候,在下一个视频中我们会继续学习如何在脚本中处理目录。😊
095:目录操作 📁

概述
在本节课中,我们将学习如何使用Python处理目录。脚本处理文件时,通常也需要操作目录。例如,可能需要处理特定目录中的所有文件,或为数据分析结果创建目录。与文件操作类似,Python提供了一系列函数来创建、删除和浏览目录内容。
检查当前工作目录
上一节我们介绍了文件路径的重要性,本节中我们来看看如何确定脚本的执行位置。使用相对路径定位文件时,了解当前工作目录至关重要。
要检查Python程序执行的当前目录,可以使用os.getcwd()方法。
import os
current_directory = os.getcwd()
print(current_directory)
在类Unix系统中,打印工作目录的命令称为pwd。默认情况下,当前目录通常是用户的主目录,这是在Linux中打开终端时的起始目录。
创建目录
要创建目录,我们使用os.mkdir()函数。该函数名称与Windows和Linux中执行相同操作的命令一致。
os.mkdir("new_dir")
这段代码在当前工作目录中创建了一个名为new_dir的目录。
更改目录
我们可以使用os.chdir()函数在程序中更改目录,并将目标目录作为参数传递。与其他函数一样,可以使用相对路径或绝对路径。
os.chdir("new_dir")
执行后,当前工作目录更改为用户主目录内新创建的目录。
删除目录
我们使用os.mkdir()创建目录,相应地,可以使用os.rmdir()删除目录。
os.rmdir("new_dir")
但os.rmdir()函数仅在目录为空时有效。如果尝试删除包含文件的目录,会引发错误。实际删除前,需要先删除该目录中的所有文件和子目录。
列出目录内容
要了解目录中的内容,有几种技术可以使用。os.listdir()函数返回给定目录中所有文件和子目录的列表。
以下是列出目录内容的示例:
import os
dir_name = "website"
for name in os.listdir(dir_name):
fullname = os.path.join(dir_name, name)
if os.path.isdir(fullname):
print(f"{fullname} 是一个目录")
else:
print(f"{fullname} 是一个文件")

这段代码执行了几个关键操作。首先,定义变量dir_name存储要检查的目录名,使代码更可读和可重用。然后,遍历os.listdir()返回的文件名。这些只是文件名,不包含目录路径。因此,使用os.path.join()将目录与每个文件名连接,创建完整的有效路径字符串。最后,使用完整路径调用os.path.isdir()检查它是目录还是文件。

跨平台路径处理

你可能会好奇join函数的作用。它似乎只是在两个字符串之间添加斜杠,但实际上,join函数让我们再次独立于操作系统。
在Linux和Mac OS中,文件路径部分使用正斜杠/分隔。在Windows中,使用反斜杠\分隔。
# Linux/Mac示例路径
path_linux = "/home/user/documents/file.txt"
# Windows示例路径
path_windows = "C:\\Users\\user\\documents\\file.txt"
通过使用os.path.join()函数,而不是显式添加斜杠,可以确保脚本在所有操作系统上正常工作。这是另一个方便的小工具,帮助我们在不同平台上避免错误。
总结
本节课中我们一起学习了Python中目录操作的基本方法。我们介绍了如何检查当前工作目录、创建目录、更改目录、删除目录以及列出目录内容。同时,强调了使用os.path.join()处理跨平台路径的重要性。Python提供了许多管理目录的函数,这里只涵盖了一部分,随着课程深入,我们将根据需要学习更多。
掌握这些基础知识后,你将能更自如地处理文件和目录,为后续学习打下坚实基础。记得多加练习,巩固所学内容。
096:什么是CSV文件 📊


在本节课中,我们将学习一种非常常见的数据格式——CSV文件。我们将了解它的结构、用途,以及为什么在处理数据时,了解文件格式如此重要。
当我们最初讨论如何读取文件时,我们看的是由一行行纯文本组成的文件。这在很多情况下都很有用,因为许多程序将其状态存储在文本文件中。我们也可以将配置文件和日志文件作为文本来处理。
然而,除了纯文本,数据还以多种不同的格式存在,你可能需要在脚本中处理其中一些格式。格式赋予了数据结构,请记住,计算机喜欢结构和精确性。为了能够处理数据,提前知道数据将如何排列会很有帮助。如果你能预期数据以某种方式表示,就更容易从中提取信息。
让我们看一个非常简单的例子。如果我们有一个文件,其中每行代表一台机器以及登录该机器的用户详情,那么当我们读取该文件时,我们就知道如何解析它以获取我们想要的信息。
解析文件意味着分析其内容以正确地构建数据结构。




常见的文件格式
我们使用多种不同的文件格式来结构化、存储和传输数据。你可能已经熟悉其中一些。例如:
- HTML:一种标记格式,用于定义网页的内容。
- JSON:一种数据交换格式,常用于在网络(尤其是互联网)上的计算机之间传递数据。
- CSV:即逗号分隔值,是一种非常常见的数据格式,用于将数据存储为由逗号分隔的文本段。
在Python标准库中,你可以找到用于处理许多此类数据格式(包括CSV和HTML)的类和模块。对于不太常见的文件格式或更高级的操作技术,你可以找到更多作为附加Python模块提供的库。
在接下来的几个视频中,我们将了解如何使用CSV模块来处理CSV文件。这不仅展示了我们如何使用Python处理特定的数据格式,而且掌握处理CSV文件的技能本身也非常有用。
CSV文件的用途与优势
这种格式让我们可以轻松存储和检索脚本可能需要的各种信息,例如我们公司的员工或我们网络中的计算机。
在我作为系统管理员的工作中,当我希望将命令的输出转换为更易于后续解析的格式时,就会创建CSV文件。例如,df命令以一种易于人眼阅读的格式打印当前使用的磁盘空间,但将这些信息转换为CSV格式后,在我的脚本中处理数据就变得容易得多。
许多程序都能够将数据导出为CSV文件,例如Microsoft Excel或Google Sheets等电子表格应用程序。实际上,将CSV文件想象成一个电子表格会很有帮助:其中每一行对应一个数据行,每个逗号分隔的字段对应一个数据列。
总结

本节课中,我们一起学习了CSV文件的基本概念。我们了解到,CSV是一种用逗号分隔数据的文本格式,它结构清晰,便于计算机处理和脚本读取。许多工具和程序都支持生成或导出CSV文件,这使得它成为数据交换和存储的通用选择。既然我们已经知道了CSV文件是什么,接下来就让我们学习如何读取它们。
097:读取CSV文件 📄
概述

在本节课中,我们将学习如何使用Python读取CSV文件。CSV是一种常见的数据存储格式,Python的标准库提供了专门的模块来处理它。我们将从理解CSV格式的基本结构开始,逐步学习如何打开文件、使用csv模块解析数据,并最终提取和操作文件中的信息。
CSV格式简介
正如我们所说,CSV代表“逗号分隔值”。CSV是一种相当简单的格式。
这些文件以纯文本形式存储,CSV文件中的每一行通常代表一条数据记录。
每条记录中的每个字段由逗号分隔。字段的内容存储在逗号之间。
例如,如果我们要存储公司员工的信息,我们可能会这样存储数据:
Sabrina Green, 802-867-5309, System Administrator
观察这个例子,以“Sabrina”开头的那一行是一条数据记录。“Sabrina Green”代表姓名字段,后面跟着电话号码字段和角色字段。
使用Python的csv模块
Python的标准库包含一个让我们可以读取、创建和操作CSV文件的模块。
你想猜猜这个模块叫什么吗?如果你猜是csv,那就对了。
所有这些不言自明的名字让生活变得容易多了,对吧?
所以我们将使用csv模块。为此,我们需要像导入其他模块一样导入它。
import csv
打开并解析CSV文件
在解析CSV文件之前,我们需要像以前一样打开文件。
file = open('employees.csv')
现在,我们可以使用csv模块来解析这个文件。
reader = csv.reader(file)
好的,这给了我们一个CSV读取器类的实例。我们现在可以遍历其内容并访问它解析出的信息。
for row in reader:
# 处理每一行
访问和解析数据
现在,row变量将保存CSV文件中的每一行。
这个变量是一个列表,CSV中的每个字段对应列表中的一个元素。
根据前面的信息,我们知道第一个字段是姓名,第二个是电话号码,第三个是角色。
所以我们可以解包这些值,以便使用变量来引用它们。
for row in reader:
name, phone, role = row
请记住,要使此操作生效,我们需要在等号左侧拥有与右侧序列长度完全相同的变量数量。
使用解包后的数据
既然我们已经解包了这些值,让我们将它们打印到屏幕上。
for row in reader:
name, phone, role = row
print(f"Name: {name}, Phone: {phone}, Role: {role}")
正如我们提到的,我们解包行数据是为了不必使用索引来访问列表中的每个元素。
例如,我们本可以使用row[0]来访问员工的姓名。这是有效的,但在阅读大量代码时可能难以理解。
将列表解包到有意义的变量名中,可以使代码在后续阅读时更容易理解。
关闭文件
在我们忘记之前,既然我们已经处理完文件,现在让我们关闭它。

file.close()
总结
本节课中,我们一起学习了如何读取和遍历CSV文件。我们了解了CSV文件的基本结构,掌握了使用Python内置的csv模块来打开、解析和提取数据的方法,并学习了通过解包操作使代码更清晰易读的技巧。
接下来,我们将讨论如何生成你自己的CSV文件。
098:生成 CSV 文件 📄
在本节课中,我们将学习如何使用 Python 的 CSV 模块来生成和写入 CSV 文件。我们将从创建数据开始,逐步完成文件的写入过程,并最终验证生成的文件内容。

从读取到写入
上一节我们介绍了如何使用 CSV 模块的 reader 函数来读取 CSV 文件的内容。本节中,我们来看看如何使用 writer 函数向文件写入内容。
当你在脚本中处理了一些数据,并希望将其存储到文件中时,这个功能会非常有用。例如,你可能希望将数据导入电子表格,或在后续的脚本中再次使用它。
准备要写入的数据
我们首先需要将想要写入的数据存储在一个列表中。以下是创建列表的示例,该列表包含了我们网络中机器的名称及其对应的 IP 地址。
hosts = [["workstation.local", "192.168.25.46"], ["webserver.cloud", "10.2.5.6"]]
以写入模式打开文件
准备好数据后,让我们以写入模式打开目标文件。我们将使用之前见过的 with 代码块,以确保文件会被正确关闭。
with open('hosts.csv', 'w') as hosts_csv:
# 写入操作将在此进行
创建 CSV Writer 对象
现在文件已为写入而打开,我们可以调用 CSV 模块的 writer 函数,并将打开的文件作为参数传入。
writer = csv.writer(hosts_csv)
此时,writer 变量成为了 CSV writer 类的一个实例。
写入数据到文件
CSV writer 对象提供了两个主要的写入方法:
writerow(): 一次写入一行数据。writerows(): 一次性写入所有数据。
由于我们已经准备好了所有要写入的数据,因此我们将使用 writerows() 方法。
writer.writerows(hosts)
验证生成的文件
操作完成后,我们已经成功将数据写入了 CSV 文件。在继续之前,让我们使用 Python 之外的工具(如 cat 命令)来查看生成文件的内容。
文件内容应如下所示:
workstation.local,192.168.25.46
webserver.cloud,10.2.5.6
我们的代码运行成功,并生成了包含所需数据的 CSV 文件。

总结与展望
本节课中,我们一起学习了如何使用 Python 的 CSV 模块生成 CSV 文件。我们经历了准备数据、打开文件、创建写入器对象以及最终写入数据的完整流程。
我们进展顺利,让我们继续前进。在下一个视频中,我们将学习如何使用字典来读写 CSV 文件。我们下节课再见。
099:使用字典读写CSV文件 📂➡️📊

概述
在本节课中,我们将要学习如何使用Python的csv模块,以更灵活、更易读的方式处理CSV文件。我们将重点介绍csv.DictReader和csv.DictWriter这两个工具,它们允许我们使用列名(键)而非列的位置来访问和写入数据,这对于处理包含多列或列名已知的文件尤其有用。
使用DictReader读取CSV文件
在之前的示例中,我们学习了如何读写CSV文件,并在Python端使用列表(list)作为数据类型。当你知道每个字段的含义时,这种方法很有效。
但是,当CSV文件包含很多列,并且你需要记住哪一列对应哪个数据时,使用列表会变得相当繁琐。想象一下,如果你的员工列表不仅包含姓名、电话号码和角色,还包括入职日期、用户名、办公室位置、部门、首选代词等等。很快,跟踪哪一列对应行中的哪个位置就会变得困难。
对于这种情况,CSV文件通常会将列名作为文件的第一行,如下例所示。这个CSV文件列出了公司内部使用的一系列程序,包括最新版本、当前开发状态和使用人数。
我们可以利用这个额外的信息,通过使用csv.DictReader来读取文件。DictReader是csv模块提供的另一个读取器,它将CSV文件中的每一行数据转换成一个字典。这样,我们就可以使用列名而不是行中的位置来访问数据。
以下是使用DictReader的步骤:
- 打开CSV文件。
- 创建一个
DictReader对象来处理CSV数据。 - 遍历行,使用字典键(即列名)访问每行的信息。
让我们看看代码示例:
import csv
with open('software.csv') as software:
reader = csv.DictReader(software)
for row in reader:
print(("{} has {} users").format(row['name'], row['users']))
在这段代码中,我们使用row['name']和row['users']来获取程序名称和用户数量,而不是依赖列的索引位置。
执行这段代码,我们将成功打印出我们想要的两个字段的内容。
这里有两个要点需要强调:
- 第一,文件中字段的顺序无关紧要,我们可以直接使用字段名。
- 第二,从输出可以看到,程序“Chty Chicken”仍处于Alpha测试阶段,所以只有4个用户。不过,这个名字听起来很有潜力。
使用DictWriter写入CSV文件
类似地,我们可以使用csv.DictWriter,根据一个字典列表的内容来生成CSV文件。这意味着列表中的每个元素将成为文件中的一行,而每个字段的值将来自每个字典。
为了使写入器正常工作,在创建DictWriter对象时,我们还需要传递一个我们想要存储到文件中的键(列名)的列表。
让我们通过一个例子来了解其工作原理。首先,我们需要一个包含要存储数据的字典列表。在这个例子中,我们希望存储公司用户及其所在部门的数据。
以下是我们的字典列表,每个字典包含name、username和department这些键:
users = [{'name': 'Sol Mansi', 'username': 'solm', 'department': 'IT infrastructure'},
{'name': 'Lio Nelson', 'username': 'lion', 'department': 'User Experience Research'},
{'name': 'Charlie Grey', 'username': 'greyc', 'department': 'Development'}]
现在,我们想将这个列表写入文件,代码如下:
import csv
keys = ['name', 'username', 'department']
with open('by_department.csv', 'w') as by_department:
writer = csv.DictWriter(by_department, fieldnames=keys)
writer.writeheader()
writer.writerows(users)
代码执行步骤如下:
- 首先,定义要写入文件的键(列名)列表。
- 然后,以写入模式(
'w')打开目标文件。 - 接着,创建
DictWriter对象,并传入之前定义的键列表。 - 最后,在写入器上调用两个方法:
writeheader()方法会根据我们传入的键创建CSV文件的第一行(标题行)。writerows()方法会将字典列表转换为文件中的行。
让我们检查一下是否成功生成了CSV文件。运行代码后,我们成功地从字典数据生成了CSV文件。
总结与回顾

在本节课中,我们一起学习了如何使用Python高效地处理CSV文件。
我们首先回顾了使用列表处理CSV的局限性,特别是在列数众多时。接着,我们引入了csv.DictReader,它允许我们通过列名(字典键)来读取数据,使代码更清晰、更易维护。
然后,我们学习了csv.DictWriter,它使我们能够轻松地将一个字典列表写入CSV文件,并自动生成标题行。
通过掌握这些工具,你现在可以更灵活地读写结构化的表格数据,这是IT自动化任务中处理日志、配置或报告文件的必备技能。
你已经掌握了文件管理的核心知识,包括读取、写入文件和目录,以及读写CSV文件。你从Python基础知识起步,并在短短几节课中取得了巨大进步。请记住,我们不要求你死记硬背所有内容,通过实践,你会逐渐掌握它们。
接下来,我们为你准备了另一份速查表,其中总结了本节课涵盖的所有内容。你可以在需要回顾CSV文件操作时随时查阅。
看完速查表后,请前往测验,用你新学的知识来检验一下学习成果吧。
100:什么是Qwiklabs? 🖥️


在本节课中,我们将学习Qwiklabs在线学习平台。这个平台是本课程及后续项目中用于完成分级评估的核心工具。我们将了解什么是Qwiklabs、它如何工作,以及为什么选择它来帮助我们学习Python脚本和IT自动化。
概述:Qwiklabs简介
在本课程的评估环节,我们将使用Qwiklabs在线学习平台。在开始第一个实验之前,让我们先深入了解Qwiklabs。
Qwiklabs是一个在线学习环境,它能引导你体验IT专家可能遇到的真实场景。
Qwiklabs与谷歌云控制台协同工作,以启动和创建虚拟机。


什么是虚拟机?
虚拟机,简称VM,是通过软件模拟的计算机。
这个软件为运行在机器内部的操作系统模拟所有必要的硬件。

对于某些模拟硬件,虚拟机将使用底层硬件的一部分进行模拟。
例如,你可以在单台笔记本电脑上运行八个不同的虚拟机,甚至更多。
每个虚拟机都分配一部分磁盘空间、内存和CPU时间。
在其他情况下,它会通过与物理机器上运行的操作系统通信来模拟硬件。
例如,虚拟机将使用一个模拟网卡与外部世界通信。
流经该模拟网卡的网络数据包将在运行虚拟机的软件和物理机器的操作系统之间传输。
然后,操作系统会通过物理网络传输这些数据包。

虚拟机已成为许多IT部门的主要工具,因为它们允许我们按需创建新的虚拟计算机。
我们也可以在不再需要时回收它们使用的资源。
例如,如果你想使用仅在某特定操作系统上可用的软件,那么创建一个新虚拟机、使用该软件,然后在使用完毕后删除虚拟机,会更容易。
回想起来,我真希望在我最初学习Python时就有虚拟机可以练习。
我主要通过书籍和在线视频学习。为了练习,我会找一些数学例题,并尝试通过编写代码来解决它们。
模拟真实世界的应用几乎是不可能的,比如在没有一堆服务器的情况下,寻找练习编写自动化脚本的方法。
如果当时有虚拟机可以练习,那该多酷啊。
Qwiklabs如何工作? ☁️

于是,Qwiklabs登场了。这些虚拟机运行在云端,因此无论你在哪里,都可以通过互联网访问它们。
请记住,当我们说某项服务运行在云端时,意味着它运行在数据中心或远程服务器上。
每个实验在设置期间都有一个预配置的操作列表。

这包括启动一个具有特定CPU和内存配置的虚拟机,并为该虚拟机安装特定的操作系统。

实验还将配置练习所需的任何其他云资源。
这可能包括为虚拟机添加额外的虚拟磁盘,或者第二台机器。

在实验过程中,你可以使用SSH命令访问为你创建的Qwiklabs实例,该命令允许你与远程Linux计算机交互。
你可以像使用运行Linux的物理机器一样操作虚拟机。
一旦实验完成,Qwiklabs会销毁这台虚拟机。这样,虚拟机使用的任何CPU、内存和存储资源都会返回到提供商的可用资源池中。
这些资源也可以被其他执行不同工作的虚拟机使用。
如何使用Qwiklabs?
在本视频之后,我们将提供关于如何访问和完成实验的详细说明。
你将在这个项目以及本课程的其他部分使用Qwiklabs,因此花些时间熟悉它是很有必要的。
Qwiklabs是一个强大的工具,我们将在这个课程以及项目的其余部分使用它。
通过Qwiklabs,你将获得通过脚本解决现实世界任务的经验。
当然,你需要知道Qwiklabs如何工作,但同样重要的是记住我们为什么选择这个工具。
它将让你在Python脚本学习的旅程中不断建立信心。
在下一个视频和阅读材料中,我们将提供更多关于如何登录Qwiklabs以完成本课程评估的信息。如果你需要帮助,随时可以回顾这些内容。
总结
本节课中,我们一起学习了Qwiklabs在线学习平台。我们了解到它是一个基于云端的实践环境,通过提供预配置的虚拟机,让我们能够安全、便捷地体验真实的IT任务和编写自动化脚本。理解虚拟机的工作原理以及Qwiklabs如何管理这些资源,是有效利用这个强大工具的第一步。准备好,我们即将开始动手实践。
101:使用Python管理文件 📁

在本节课中,我们将学习如何使用Python来管理文件和目录。我们将涵盖读取和写入文本文件、处理CSV文件,以及操作文件和目录的基本技能。这些技能对于IT自动化办公至关重要,因为文件是存储和传输信息的主要方式。
模块总结 🎯
恭喜你完成了本模块的学习。现在你已经掌握了更多关于如何使用Python管理文件的知识。
这些概念目前可能看起来有些困难,但一旦你开始自己管理文件,你会发现自信心迅速提升。你正在学习的这些技能非常实用。
在之前的视频中,我们探讨了如何读取和写入文本文件和CSV文件,以及如何使用Python管理文件和目录。我们涵盖了很多内容,但实际上,我们只是触及了使用文件和目录所能完成的各种任务的表面。
请记住,在IT领域,文件是存储和传输信息的最重要方式之一。还有更多的文件格式、更多的遍历目录的方法,以及更多帮助我们完成任务的工具。
正如我们之前提到的,Python标准库只包含处理部分数据格式的模块。标准库未涵盖的数据类型还有很多。如果你需要使用不同的格式,或者需要完成比标准库提供的功能更高级的任务,你始终可以使用PP上提供的众多外部Python模块之一。
在课程的其余部分,我们将运用目前学到的知识,并探索更多可用于在Python中操作文件和目录的工具和功能。但在进入下一个主题之前,我们为你准备了一个分级评估。
你将再次使用Quicklase来模拟一个真实场景。我们会给你一些需要处理的数据文件,然后你需要编写一个脚本,该脚本将获取信息并使用它生成一份报告。
不要紧张,你能做到。如果你需要回顾任何视频内容,请慢慢来。完成评估后,我会在这里等你。现在,开始行动吧。
核心概念回顾 📝
以下是本模块涵盖的核心概念:
- 文件操作:使用
open()函数、read()、write()等方法进行文件的读取和写入。 - CSV文件处理:使用
csv模块来读取和写入CSV格式的数据。 - 目录管理:使用
os和shutil模块来创建、删除、移动和遍历目录与文件。
总结
本节课中,我们一起学习了使用Python进行文件和目录管理的基础知识。我们掌握了读取和写入不同格式文件的方法,并了解了Python标准库及外部模块在文件处理中的作用。这些技能是IT自动化办公的基石,希望你通过实践不断巩固和提升。
102:模块3 - 正则表达式介绍 🧩
在本节课中,我们将学习一个非常强大的文本处理工具——正则表达式。我们将了解它的基本概念、语法规则以及如何在Python中应用它来灵活地查找和操作文本。

在上一模块中,我们学习了如何管理文件中的信息,特别是处理CSV文件来存储和处理数据。本节中,我们将把数据处理能力提升到一个新的层次,学习如何使用正则表达式。

正则表达式是一种用于匹配和处理文本模式的强大工具。它允许我们以比之前更灵活的方式在文本中查找、提取和操作特定的字符串片段。
什么是正则表达式?🔍
正则表达式,常简写为“regex”,是一系列字符,它定义了一个搜索模式。这个模式可以用来检查一个字符串是否包含某种特定的子串、替换匹配的子串,或者从字符串中提取符合某个条件的部分。
它的核心思想是使用模式来描述文本,而不是固定的字符。例如,模式 \d+ 可以匹配一个或多个数字。
正则表达式的基本语法 📝
以下是正则表达式中一些最常用的元字符和它们的含义:
.(点号):匹配任何单个字符(除了换行符)。- 示例:模式
a.c可以匹配 “abc”、“a c”、“a&c”。
- 示例:模式
\d:匹配任何数字(0-9)。- 示例:模式
\d\d可以匹配 “12”、“45”、“99”。
- 示例:模式
\w:匹配任何字母、数字或下划线(相当于[a-zA-Z0-9_])。- 示例:模式
\w\w可以匹配 “ab”、“A1”、“_z”。
- 示例:模式
\s:匹配任何空白字符(包括空格、制表符、换行符)。- 示例:模式
hello\sworld可以匹配 “hello world”、“hello world”(中间有制表符)。
- 示例:模式
[](字符集):匹配括号内的任何一个字符。- 示例:模式
[aeiou]可以匹配任何一个元音字母。 - 示例:模式
[A-Z]可以匹配任何一个大写字母。
- 示例:模式
|(竖线):表示“或”逻辑。- 示例:模式
cat|dog可以匹配 “cat” 或 “dog”。
- 示例:模式
^(脱字符):匹配字符串的开始。- 示例:模式
^Hello只匹配以 “Hello” 开头的字符串。
- 示例:模式
$(美元符):匹配字符串的结束。- 示例:模式
world$只匹配以 “world” 结尾的字符串。
- 示例:模式
量词:控制匹配次数 🔢
量词用于指定一个模式可以出现多少次。
*(星号):匹配前面的模式零次或多次。- 示例:模式
lo*l可以匹配 “ll”、“lol”、“lool”。
- 示例:模式
+(加号):匹配前面的模式一次或多次。- 示例:模式
lo+l可以匹配 “lol”、“lool”,但不能匹配 “ll”。
- 示例:模式
?(问号):匹配前面的模式零次或一次(即可选)。- 示例:模式
colou?r可以匹配 “color” 和 “colour”。
- 示例:模式
{n}:匹配前面的模式恰好 n 次。- 示例:模式
\d{3}可以匹配 “123”、“456” 等三位数字。
- 示例:模式
{n,}:匹配前面的模式至少 n 次。- 示例:模式
\d{2,}可以匹配 “12”、“123”、“1234” 等至少两位的数字。
- 示例:模式
{n,m}:匹配前面的模式至少 n 次,至多 m 次。- 示例:模式
\d{2,4}可以匹配 “12”、“123”、“1234”。
- 示例:模式
在Python中使用正则表达式 🐍
Python通过内置的 re 模块提供了对正则表达式的完整支持。下面介绍几个最常用的函数。
1. re.search() - 搜索匹配
re.search() 函数扫描整个字符串,寻找第一个匹配模式的位置。如果找到,返回一个匹配对象;否则返回 None。
import re
text = “我的电话号码是 123-456-7890。”
pattern = r“\d{3}-\d{3}-\d{4}” # 模式:三个数字-三个数字-四个数字
match = re.search(pattern, text)
if match:
print(“找到电话号码:”, match.group()) # 输出:找到电话号码: 123-456-7890
else:
print(“未找到匹配项。”)
2. re.findall() - 查找所有匹配
re.findall() 函数返回字符串中所有非重叠匹配的列表。
import re
text = “苹果售价5元,香蕉售价3元,橙子售价4元。”
pattern = r“\d+元” # 模式:一个或多个数字后跟“元”
prices = re.findall(pattern, text)
print(“所有价格:”, prices) # 输出:所有价格: [‘5元’, ‘3元’, ‘4元’]
3. re.sub() - 替换匹配项
re.sub() 函数用于替换字符串中所有匹配正则表达式模式的部分。
import re
text = “今天是2023-08-25,明天是2023-08-26。”
pattern = r“(\d{4})-(\d{2})-(\d{2})” # 分组匹配年、月、日
replacement = r“\2/\3/\1” # 替换为 月/日/年 格式
new_text = re.sub(pattern, replacement, text)
print(new_text) # 输出:今天是08/25/2023,明天是08/26/2023。
分组与捕获 ( )
圆括号 () 在正则表达式中用于创建分组。分组有两个主要用途:
- 将多个字符视为一个整体来应用量词,例如
(abc)+可以匹配 “abc”、“abcabc”。 - 捕获匹配到的子串,以便后续通过
match.group(n)或替换模式中的\n来引用。
import re
text = “姓名:张三, 年龄:30”
pattern = r“姓名:(\w+), 年龄:(\d+)”
match = re.search(pattern, text)
if match:
print(“完整匹配:”, match.group(0)) # 输出:姓名:张三, 年龄:30
print(“姓名:”, match.group(1)) # 输出:姓名: 张三
print(“年龄:”, match.group(2)) # 输出:年龄: 30
本节课中,我们一起学习了正则表达式的基础知识。我们了解了正则表达式是一种用于描述文本模式的强大语言,掌握了其基本元字符(如 ., \d, \w)、量词(如 *, +, ?, {})以及分组 () 的用法。最后,我们学习了如何在Python中通过 re 模块的 search(), findall() 和 sub() 函数来实际应用正则表达式进行文本搜索、查找和替换操作。
正则表达式初学可能有些复杂,但通过不断练习和尝试,它将成为你IT工具箱中处理文本数据的利器。
103:什么是正则表达式?🔍


在本节课中,我们将要学习正则表达式的基本概念、用途及其在IT自动化中的重要性。正则表达式是一种强大的文本处理工具,能帮助我们高效地搜索、匹配和处理字符串。

我们之前提到会讨论正则表达式。那么,这些表达式是什么?为什么它们被称为“正则”?正则表达式,常缩写为RegEx或RegX,本质上是一种用字符串模式表达的文本搜索查询。当你针对特定文本运行搜索时,任何与你指定的正则表达式模式匹配的内容都会作为搜索结果返回。


正则表达式让你能够回答诸如“文件中所有四个字母的单词是什么?”或“这个错误日志中有多少种不同的错误类型?”等问题。
换句话说,正则表达式允许我们根据特定模式搜索文本中的字符串。
了解正则表达式对任何需要执行文本处理的人都非常有用。从IT专家到软件工程师、系统管理员和数据分析师,掌握正则表达式的基础知识都是一项方便的工具。作为一名系统管理员,当我需要从包含其他信息的文件中提取信息时,就会使用正则表达式。例如,如果我有一个列出NFS挂载和选项的文件,并且我只想提取服务器名称,我可以编写一个正则表达式来去除每行的多余数据,只返回我需要的信息列表。
正则表达式在IT领域是一个相当广泛的话题。在本课程中,我们将涵盖最重要的部分,但不会涉及所有内容。对于你的脚本编写,基本的正则表达式通常足以让你入门,并且它们将增强你的程序处理文本的能力。随着时间和练习,你将掌握更高级的技术。
我们可以通过多种方式应用正则表达式。我们可以在各种编程语言中使用它们,当然也包括Python。我们也可以使用支持正则表达式的命令行工具,如grep、sed或awk。我们甚至可以在文本处理工具(如代码或文档编辑器)中使用正则表达式。与其他广泛使用的技术一样,有许多工具都集成了正则表达式,实现细节可能因工具或语言而异,但幸运的是,其基本原理始终相同。一旦我们学会了基础知识,就可以很快地将相同的概念应用到不同的应用程序中。
在接下来的几个视频中,我们将探索处理正则表达式的Python模块。我们将了解如何将正则表达式应用于脚本读取的文本的处理、解析和意义提取。我们还将查看一系列不同的示例,在这些示例中,我们可以使用正则表达式来解决一些实际问题。
本节课中我们一起学习了正则表达式的定义、核心用途及其在IT自动化中的广泛应用。正则表达式是一种通过模式匹配来搜索和处理文本的强大工具,掌握它将极大提升你处理文本数据的效率。在接下来的课程中,我们将深入实践,学习如何在Python中使用正则表达式。
104:为什么使用正则表达式?🔍
在本节课中,我们将要学习正则表达式的基本概念,并理解为什么在处理文本时,正则表达式比简单的字符串查找更强大、更灵活。

此时,你可能会想:为什么我需要比在文本中查找字符串更强的处理能力?毕竟,我已经知道如何在Python中查找字符串了。
答案在于正则表达式的强大功能和灵活性。
从具体问题出发
例如,假设我们有一些日志条目,其典型的日志行格式如下所示:
Jan 31 00:09:39 ubuntu.local ticky: INFO Created ticket [#12345] (username)
我们想从这一行中提取进程标识符,即方括号之间的数字 12345。
在这条日志行中,有很多我们不需要的额外文本,比如日期、计算机名和其他信息。
尝试使用字符串索引方法
我们可以使用字符串的 index 方法来查找字符串中的第一个方括号,从而提取进程ID。
请记住,访问字符串时,字符的索引是该字符在字符串中的位置,从零开始计数。
在这个例子中,第一个方括号的索引是 39。
如果我们不想捕获方括号本身,我们将从下一个位置开始,并包括其后的五个字符。
让我们试一试。
log_line = "Jan 31 00:09:39 ubuntu.local ticky: INFO Created ticket [#12345] (username)"
first_bracket_index = log_line.index('[')
process_id = log_line[first_bracket_index + 1: first_bracket_index + 6]
print(process_id) # 输出:12345
潜在的问题
虽然我们得到了想要的文本,但未来可能会遇到一些问题。你能发现它们吗?
以下是可能遇到的问题:
- 长度不确定:我们无法确定在所有情况下进程ID字符串的长度。在这个例子中,我们看到它是五个字符长,但随着计算机或进程数量的增加,这个长度将来可能会改变。
- 格式变化:如果由于任何原因,该行在进程ID之前包含了另一个方括号,这种方法也会失效。
所以,这是一个解决方案,但非常脆弱。
更强大的解决方案:正则表达式
还有其他想法吗?
我们可以使用正则表达式以更健壮的方式提取进程ID。
为此,我们将导入 re 模块,它允许我们使用 search 函数在字符串中查找正则表达式。
import re
log_line = "Jan 31 00:09:39 ubuntu.local ticky: INFO Created ticket [#12345] (username)"
pattern = r"\[(\d+)\]"
match = re.search(pattern, log_line)
if match:
process_id = match.group(1)
print(process_id) # 输出:12345
正则表达式的优势
只要字符串中有一个由方括号标记的单一数字序列,这个正则表达式就会为我们提取出这些数字。

无论进程ID出现在哪里,或者日志行是长是短,这个正则表达式都能工作。
如果此时存储在 pattern 变量中的正则表达式看起来像天书,请不要担心,这是正常的。
我们将在接下来的视频中探索其语法以及如何使用这些表达式。
本节小结
本节课中,我们一起学习了正则表达式的基本动机。
目前的关键要点是:正则表达式是既强大又灵活的工具。
到本模块结束时,你将能够阅读和解析像本例中这样的语句。
我们有了一个良好的开端。接下来,我们将学习如何使用 grep 命令进行一些非常基础的匹配。
105:使用 grep 进行基本匹配 🎯

在本节课中,我们将学习如何使用 grep 命令进行基本的文本匹配。grep 是一个功能强大且易于使用的命令行工具,它允许我们使用正则表达式来搜索和匹配文本。通过本节课的学习,你将掌握 grep 的基本用法,并了解如何使用简单的正则表达式进行文本匹配。
基本匹配示例
在上一节中,我们通过一个复杂的正则表达式从 Python 程序中查找处理过的 ID。这只是我们在处理 Python 脚本文本时可能遇到的一个例子。除了 Python,我们还可以在命令行工具中使用正则表达式。grep 是一个特别容易使用且功能强大的工具,适用于应用正则表达式。它是尝试和熟悉正则表达式的绝佳方式。
接下来,我们来看看如何使用 grep 进行基本匹配。
最简单的匹配:搜索字符串是否存在
记住,grep 的工作原理是打印出任何匹配我们传入查询的行。因此,最简单的查询是传入一个普通的字符串。grep 会打印出文件中包含该字符串的所有行。
让我们尝试使用 grep 在 /usr/share/dict/words 文件中查找单词。这个文件是一些拼写检查程序用来验证单词是否存在。该文件每行包含一个单词。
我们将从查找包含字符串 "thawn" 的单词开始。看看会发生什么。
grep "thawn" /usr/share/dict/words
当我们以 "thawn" 作为匹配模式调用 grep,并传入单词列表作为文件时,我们会看到它匹配了许多不同的单词。这些单词都包含字符串 "thawn",因此它们出现在结果中。输出还会高亮显示,以不同颜色展示匹配的部分。
这种视觉指示是 grep 为我们提供的,以便我们轻松查看匹配发生的位置。
需要注意的是,我们传递给 grep 的字符串是区分大小写的,因此必须完全匹配。如果我们使用大写字母,它们只会匹配大写字母。如果我们希望不区分大小写地匹配字符串,我们需要向 grep 命令传递 -i 参数,如下所示:
grep -i "thawn" /usr/share/dict/words
正则表达式的特殊字符
现在我们知道,任何基本字符串本身就是一个正则表达式,它会匹配包含该字符串的行。为了充分利用正则表达式,我们需要学习更多语法,这些语法既复杂又强大。特别是,我们必须了解那些为我们创建的模式赋予额外含义的保留字符。
正是这些字符使我们能够进行比仅检查字面字符串更高级的匹配。例如,点号 . 匹配任何字符。这意味着如果我们在表达式中包含一个点号,该点号就是一个通配符,可以在结果中被任何其他字符替换。
让我们看一个例子:
grep "l.rts" /usr/share/dict/words
这个模式匹配三个不同的单词:alerts、blurts 和 flirts。注意,对于每个单词,我们模式中的点号都被不同的字母替换。
你是否开始看到正则表达式的强大之处?通过它们,我们可以找到匹配给定模式的文本部分,即使模式不是整个单词。例如,我们可以使用它来查找日志文件中匹配特定格式的条目,或者查找 CSV 文件中具有相同特征的行,即使它们不完全相同。这非常有用,对吧?
锚定字符:^ 和 $
其他可以在正则表达式中使用的特殊字符的简单例子是脱字符 ^ 和美元符号 $,它们是锚定字符。这些字符告诉我们正则表达式应该从行的哪个位置开始匹配。
^ 表示行的开头,$ 表示行的结尾。例如,要查找所有以字符串 "fruit" 开头的单词,我们可以这样写:
grep "^fruit" /usr/share/dict/words
看看正则表达式如何成为一个极其有用的工具。让我们再看一个例子。我们将使用 grep 查找所有以 "cat" 结尾的单词:

grep "cat$" /usr/share/dict/words
这工作得非常完美。你现在开始理解了吗?
需要记住的一点是,^ 和 $ 专门匹配行的开头和结尾,而不是字符串。以日志文件为例,每行包含许多不同的单词。我们可以使用 ^ 检查一行是否以某个模式开头,或者使用 $ 检查一行是否以某个模式结尾。但我们的模式只有在行符合这些条件时才会匹配,而不是包含的单词。
总结
在本节课中,我们一起学习了如何使用 grep 进行基本文本匹配。我们了解了 grep 的基本用法,包括如何搜索字符串是否存在,以及如何使用特殊字符如点号 .、脱字符 ^ 和美元符号 $ 进行更高级的匹配。这些工具使我们能够高效地处理文本数据,无论是在日志文件、CSV 文件还是其他文本格式中。正则表达式虽然语法复杂,但通过逐步学习和实践,你将能够掌握其强大功能。
106:在Python中进行简单匹配 🐍

在本节课中,我们将学习如何在Python中使用re模块进行基本的正则表达式匹配。我们将从导入模块开始,逐步探索如何使用search()函数查找字符串中的模式,并理解返回的匹配对象。
概述
正则表达式是处理文本的强大工具。在Python中,我们使用re模块来应用正则表达式。本节课将介绍如何使用该模块进行基础的字符串匹配,包括如何编写模式、执行搜索以及解读结果。
导入re模块
首先,我们需要导入Python的re模块。这个模块包含了许多用于操作字符串的函数。
import re
使用search()函数进行匹配
上一节我们介绍了re模块,本节中我们来看看如何使用它的search()函数进行基础匹配。
我们在re模块上调用search()函数,并让它对字符串“Plaza”使用模式“Aza”。然后将该函数的返回值存储在result变量中。

result = re.search(r"Aza", "Plaza")
模式开头的r表示这是一个原始字符串。这意味着Python解释器不应尝试解释任何特殊字符,而应原样将字符串传递给函数。
在这个例子中,没有特殊字符。原始字符串和普通字符串完全相同,但在Python中为正则表达式始终使用原始字符串是一个好习惯。

因此,我们将在所有示例中使用原始字符串。
解读匹配结果
说完这些,让我们打印result变量的结果,看看我们得到了什么。
print(result)
很好,我们的结果是一个匹配对象。调用print时得到的输出已经显示了一些有趣的信息,例如匹配在字符串中的位置以及实际匹配的字符串是什么。
让我们用另一个单词再试一次。
result = re.search(r"Aza", "Plaza")
print(result)
在这种情况下,我们可以看到span属性不同。这是因为匹配的子字符串在字符串内部的位置不同。然而,匹配的子字符串仍然是相同的,因为我们是用纯字符串进行匹配,还没有使用特殊语法。
处理无匹配的情况
如果你传递一个与表达式不匹配的字符串,你认为会发生什么?让我们尝试找出答案。
result = re.search(r"Aza", "mountain")
print(result)
你猜对了吗?如果表达式与我们传递的字符串不匹配,我们会得到None作为结果。请记住,None是Python使用的一个特殊值,用于表示那里没有实际值。
因此,当我们应用正则表达式时,我们现在知道,如果search()函数返回None,就意味着它没有找到匹配项。
练习特殊字符
让我们用几个例子来练习到目前为止我们见过的特殊字符。
以下是使用特殊字符的示例:
我们告诉search()函数在字符串“xenon”上使用模式^X。我们可以看到,正如我们预期的那样,它在行首匹配了我们的“X”。
result = re.search(r"^X", "xenon")
print(result)
如果我们使用可以匹配任何字符的点.,会发生什么?
现在我们使用P.ng作为搜索模式。它匹配我们传递的单词“penguin”,在匹配对象中,我们看到匹配的字符串是“pen”。
result = re.search(r"P.ng", "penguin")
print(result)
让我们用另外几个字符串试试看。
print(re.search(r"P.ng", "clapping"))
print(re.search(r"P.ng", "sponge"))
很好,所以在这里我们可以看到,match属性始终具有与搜索模式匹配的实际子字符串的值,而span属性则指示该子字符串在我们传递的字符串中的查找范围。

使用搜索选项
我们还可以向search()函数传递额外的选项。例如,如果我们希望匹配不区分大小写,可以通过传递re.IGNORECASE选项来实现。
result = re.search(r"p.ng", "Pangaea", re.IGNORECASE)
print(result)
总结
本节课中我们一起学习了如何在Python中应用基础的正则表达式。我们现在知道如何使用re.search()函数进行匹配,如何解读返回的匹配对象,以及如何处理无匹配的情况。我们还练习了使用^、.等特殊字符,并了解了如何通过re.IGNORECASE等选项使搜索不区分大小写。
你现在可以使用本地的Python安装来练习这些以及你能想到的任何其他正则表达式示例。不妨自己动手实验一下,直到你感到得心应手。慢慢来,你会掌握它的。
接下来,我们将更深入地研究正则表达式的语法以及我们可以用它们做些什么。
107:通配符与字符类 🧩

在本节课中,我们将要学习正则表达式中两个强大的功能:通配符和字符类。我们将了解如何使用点号(.)匹配任意字符,以及如何通过字符类([])精确匹配特定范围的字符。这些工具能帮助我们更灵活地处理文本数据,例如验证用户输入或筛选文件内容。
通配符:匹配任意字符
我们已经知道,在正则表达式中,点号(.)是一个特殊字符,可以匹配任何单个字符。
在正则表达式领域,这被称为通配符,因为它能匹配多种字符。
使用点号是最广泛的通配符,因为它能匹配绝对任何字符。
但如果我们想要更严格的匹配呢?例如,检查用户给出的答案是否包含有效字符,或者找出CSV文件中所有以元音字母开头的用户名。
为此,我们必须将通配符限制在特定字符范围内。为了实现这一目标,我们使用正则表达式的另一个功能:字符类。
字符类:匹配特定字符
字符类写在方括号([])内,允许我们列出想要匹配的字符。
例如,假设我们想匹配单词“Python”,但允许字母“P”既可以是小写也可以是大写。我们可以这样写:
[Pp]ython
在方括号内,我们还可以使用连字符(-)定义字符范围。例如,我们可以使用[a-z]表示任何小写字母。
因此,如果我们想查找前面有任意字母的字符串“way”,可以这样编写表达式:
[a-z]way
匹配成功!字符类定义的[a-z]被字母“h”匹配。
让我们尝试一个不同的字符串:
" way"
这次没有匹配成功。这是因为字符串“way”前面是一个空格,而空格不在我们定义的范围内。
我们可以定义更多范围,例如[A-Z]匹配所有大写字母,或[0-9]匹配所有数字。
我们可以组合任意多个范围和符号,例如:
[a-zA-Z0-9]
如你所见,我们可以匹配方括号内定义的任何内容。这非常有用,对吧?
排除字符类
虽然字符类非常有用,但有时我们可能想匹配不在某个组内的字符。为此,我们在方括号内使用脱字符(^)。
例如,让我们创建一个搜索模式,查找任何不是字母的字符:
[^a-zA-Z]
在这个例子中,我们的模式匹配了句子中的第一个空格。
如果我们还想排除空格呢?你或许已经猜到了,因为我们在字符类中添加了空格,所以现在匹配的是句子末尾的句点,而句点不在排除的字符列表中。
使用管道符号匹配多个选项
如果我们想匹配一个表达式或另一个表达式,可以使用管道符号(|)来实现。这允许我们列出可以匹配的替代选项。
例如,我们可以编写一个表达式,匹配单词“cat”或“dog”:
cat|dog
由于字符串包含子串“cat”,搜索函数可以找到它。
让我们尝试一个包含“dog”的例子:
dog
这个表达式包含子串“dog”,所以我们找到了匹配。
让我们尝试一个同时包含“dogs”和“cats”的句子:
"I like dogs and cats."
在这个字符串中,我们的搜索实际上有两个可能的匹配,但我们只得到第一个。这是搜索函数的工作方式。
如果我们想获取所有可能的匹配,可以使用findall函数,它也是re模块提供的:

re.findall(r"cat|dog", "I like dogs and cats.")
使用findall,我们不需要在“cats”和“dogs”之间做出选择。真是松了一口气!
总结与过渡
好了,我们已经学习了如何匹配不同的字符组甚至完全不同的字符串。你是否开始理解这些概念了呢?正如我之前所说,这些东西有点棘手,请随时花时间自己练习这些函数。这些工具在IT领域非常有用,所以你肯定想熟练掌握它们。
现在,如果我们想多次匹配某个内容,你认为应该怎么做呢?一旦你准备好了,请在下一个视频中与我见面,一起找出答案。
本节课中,我们一起学习了正则表达式中的通配符和字符类。我们了解了如何使用点号匹配任意字符,如何通过字符类精确匹配特定范围的字符,以及如何使用管道符号匹配多个选项。这些技能将帮助你在IT自动化任务中更有效地处理文本数据。
108:正则表达式重复修饰符详解 🧩

在本节课中,我们将要学习正则表达式中的重复修饰符。这些修饰符允许我们匹配字符的多次出现,从而更灵活地查找和提取文本中的模式。我们将探讨星号、加号和问号等修饰符的用法,并通过简单示例理解它们的工作原理。
匹配字符的多次出现
上一节我们介绍了如何匹配单个字符、字符组或任意字符。本节中,我们来看看如何匹配这些字符的多次出现。
假设我们想要在字符串中找到最长的单词,或者通过检查括号间的一串字母数字字符来查找日志文件中的主机名。我们可以使用正则表达式的另一个有趣概念——重复匹配来实现。
星号修饰符:匹配零次或多次
很常见的一种表达式是包含一个点号后跟一个星号:.*。这意味着匹配任意字符重复任意次数,包括零次。
以下是几个示例:
在纯英文中,你可以将这个模式解读为:匹配“pi”,后跟任意数量的其他字符,再后跟“n”。但通过我们的点星组合,我们将匹配范围扩展到了整个单词。
import re
pattern = r'pi.*n'
text = 'pink'
result = re.search(pattern, text)
print(result.group()) # 输出:pink
点号如何为每个字母取不同的值?让我们尝试一个不同的字符串:“Python programming”。你认为模式会匹配什么?
pattern = r'p.*n'
text = 'Python programming'
result = re.search(pattern, text)
print(result.group()) # 输出:Python programmin
你可能没有预料到这个结果。记住,星号会匹配尽可能多的字符。在编程术语中,我们称这种行为是“贪婪的”。可以修改重复修饰符使其不那么贪婪,但我们暂时不深入讨论。要了解更多信息,请查看后续阅读材料。
回到我们的例子,虽然我们的模式本可以匹配单词“Python”,但它一直扩展到了字符串中的最后一个“n”。如果我们只希望模式匹配字母,我们应该使用字符类来代替,像这样:
pattern = r'p[a-z]*n'
text = 'Python programming'
result = re.search(pattern, text)
print(result.group()) # 输出:Python
记住,零次也是一种可能性。这将让字符串“pin”也匹配我们的模式。让我们试试看:
pattern = r'pi.*n'
text = 'pin'
result = re.search(pattern, text)
print(result.group()) # 输出:pin
加号和问号修饰符
正如我们之前提到的,正则表达式的实现并不总是相同。重复修饰符是它们之间的一个差异点。一些实现(如GrP使用的)只包含我们刚刚讨论的星号修饰符。仅用星号修饰符就能做很多事情,所以这通常足够了。其他实现(如Python或EGp命令使用的)包括两个额外的重复修饰符:加号和问号,它们可以帮助我们构建更复杂的表达式。
加号修饰符:匹配一次或多次
加号字符匹配其前面字符的一次或多次出现。假设我们有模式 O+L+。让我们检查几个单词:
pattern = r'O+L+'
texts = ['OL', 'OOLL', 'OoLL']
for text in texts:
result = re.search(pattern, text)
if result:
print(f"匹配: {result.group()}")
else:
print(f"不匹配: {text}")
在这个例子中,每个字符出现了一次,匹配模式显示给我们最短的可能匹配字符串。这里,每个字符出现了两次。同样,我们可以看到匹配是整个满足条件的字符串。
让我们尝试一些不匹配的情况:
pattern = r'O+L+'
text = 'OoLL'
result = re.search(pattern, text)
print(result) # 输出:None
虽然我们的字符串中有一个“O”和一个“L”,但它们之间有另一个字符。因此,它不匹配搜索模式。这说得通吗?
问号修饰符:匹配零次或一次
问号符号是另一个乘数;它意味着其前面字符的零次或一次出现。让我们看看这是如何工作的:
pattern = r'p?ython'
texts = ['ython', 'python']
for text in texts:
result = re.search(pattern, text)
if result:
print(f"匹配: {result.group()}")
else:
print(f"不匹配: {text}")
“P”不存在,但使用问号,我们将其标记为可选的,所以我们仍然得到了匹配。让我们看看当“P”存在时会发生什么:
pattern = r'p?ython'
text = 'python'
result = re.search(pattern, text)
print(result.group()) # 输出:python

很好,“P”存在,所以匹配包含了它。
总结
本节课中我们一起学习了正则表达式中的重复修饰符。我们探讨了星号(*)用于匹配零次或多次,加号(+)用于匹配一次或多次,以及问号(?)用于匹配零次或一次。这些修饰符使我们能够更精确地匹配文本中的模式,并理解贪婪匹配的概念。
如果你对任何内容不清楚,现在花些时间在你本地的Python环境中查看示例。我相信一旦你自己尝试过,你就会完全掌握它。
你刚刚学习了重复修饰符,我们看到了如何使用一堆特殊字符来匹配不同类型的字符串。但是,当我们想要实际匹配其中一个字符,比如美元符号或问号时,会发生什么?幸运的是,我们将在下一个视频中找出答案。
109:Python正则表达式中的转义字符 🧩

在本节课中,我们将要学习正则表达式中的一个重要概念:转义字符。我们将了解为什么需要转义特殊字符,以及如何使用反斜杠来匹配这些字符本身。此外,我们还会介绍一些由反斜杠引导的预定义字符集,并讨论如何避免因字符串转义而产生的混淆。
转义字符的必要性 🔍
上一节我们介绍了正则表达式中的多种特殊字符,如点号、星号、加号等。这些字符在正则表达式中有特殊含义,用于匹配不同类型的字符串。例如,点号 . 可以匹配任何单个字符。
但如果我们想要匹配这些特殊字符本身,比如匹配字符串中的实际点号,该怎么办呢?如果直接使用点号,它会匹配任意字符,而不是我们想要的实际点号。
以下是一个例子。假设我们想匹配包含“dotcom”的字符串,但直接使用点号会导致匹配到其他内容:
import re
result = re.search(r".com", "welcome")
print(result) # 输出匹配对象,因为它将 `.` 匹配为 `l`
为了匹配一个实际的点号,我们需要使用转义字符。在正则表达式中,转义字符是反斜杠 \。
result = re.search(r"\.com", "welcome")
print(result) # 输出 None,因为没有实际的 `.com`

通过转义点号,我们成功避免了错误匹配。现在,让我们尝试一个应该匹配的例子:
result = re.search(r"\.com", "google.com")
print(result) # 输出匹配对象,成功匹配 `.com`
通过添加反斜杠,我们让正则表达式正确地匹配了我们想要的内容。
转义其他特殊字符与潜在混淆 ⚠️

我们可以用同样的方式使用反斜杠来转义任何特殊字符,包括那些我们尚未讨论的字符。
但需要注意的是,反斜杠本身也可能引起混淆,因为它在Python字符串中也用于定义一些特殊字符序列。例如:
\n表示换行符。\t表示制表符。
因此,当我们看到一个包含反斜杠的模式时,它可能是在转义正则表达式的特殊字符,也可能是在表示一个特殊的字符串字符。
使用原始字符串和预定义字符集 🛡️
为了避免这种潜在的混淆,我们一直使用原始字符串(在字符串前加 r)来定义正则表达式模式。在原始字符串中,反斜杠不会被Python解释为字符串转义字符,而只会被正则表达式引擎解释。
# 使用原始字符串
pattern = r"\n" # 这里 \n 会被正则表达式引擎解释为“匹配换行符”
# 而非原始字符串
pattern = "\n" # 这里 \n 在字符串生成时就被解释为换行符,然后再传给正则表达式引擎

此外,Python的正则表达式还使用反斜杠定义了一些预定义字符集,这些序列代表了常用的字符类别:
以下是几个重要的预定义字符集示例:
\w:匹配任何字母、数字或下划线(等价于[a-zA-Z0-9_])。re.search(r'\w+', 'hello world') # 匹配 'hello' re.search(r'\w+', 'user_name123') # 匹配整个字符串 'user_name123'\d:匹配任何数字(等价于[0-9])。\s:匹配任何空白字符(如空格、制表符\t、换行符\n)。\b:匹配单词边界。
学习资源与总结 📚
一下子接触这么多新字符和序列,你可能会觉得有些复杂。但请不用担心,你不需要记住所有内容。
以下是两个非常有用的资源:
- 速查表:你可以随时查阅正则表达式速查表,来查找每个序列代表的含义。
- 在线测试工具:例如 regex101.com 这类网站。你可以在这里测试你的正则表达式,分析模式的每个部分,并在表达式不工作时找出问题所在。

你已经掌握了非常多的知识,这些努力即将得到回报。接下来,我们将开始创建一些更复杂的模式,并将它们应用到实际场景中。
本节课中我们一起学习了:
- 使用反斜杠
\作为转义字符,来匹配正则表达式中的特殊字符本身(如\.匹配点号)。 - 反斜杠在Python字符串和正则表达式中可能引起的混淆,以及使用原始字符串(
r"pattern")来避免它。 - 由反斜杠引导的一些预定义字符集,如
\w(单词字符)、\d(数字)、\s(空白符)。 - 利用在线工具和速查表来辅助学习和调试正则表达式。
110:正则表达式实践 🧩

在本节课中,我们将学习如何组合使用正则表达式的特殊字符来构建匹配特定文本的模式。我们将通过两个具体示例——匹配以特定字母开头和结尾的国家名称,以及验证Python变量名的有效性——来巩固对正则表达式语法的理解。
上一节我们介绍了正则表达式的基本语法,本节中我们来看看如何将这些特殊字符组合起来,解决实际问题。
匹配特定模式的国家名称
假设我们有一个包含所有国家名称的列表,我们想找出哪些国家的名字以字母“A”开头并以字母“a”结尾。
我们最初尝试的模式可能是:A.*a。这个模式表示以大写字母“A”开头,中间是任意数量的任意字符(.*),最后以小写字母“a”结尾。
让我们测试一下这个模式。它似乎能匹配“Australia”。但当我们测试“Azerbaijan”时,它也被匹配了,尽管这个名字并非以“a”结尾。这是因为我们的模式没有限定必须匹配整个字符串。“Azerbaijan”内部包含字母“a”,因此被.*a部分匹配了。
我们需要通过添加行首(^)和行尾($)锚点来使模式更严格。修改后的模式是:^A.*a$。这个模式明确表示,整行字符串必须严格以“A”开头并以“a”结尾。
以下是验证过程:
^A.*a$匹配 “Australia”。^A.*a$不匹配 “Azerbaijan”。
验证Python变量名
使用正则表达式,我们还可以构建一个模式来验证一个字符串是否是有效的Python变量名。
Python变量名的规则是:
- 可以包含任意数量的字母、数字或下划线。
- 不能以数字开头。
基于这些规则,验证模式应如何构建?
- 变量名必须以字母开头。因此,我们使用
^表示字符串开始,然后是一个包含所有大小写字母和下划线的字符类:[a-zA-Z_]。 - 变量的其余部分可以有任意数量的数字、字母或下划线。因此,我们添加另一个包含数字、字母和下划线的字符类,并在其后加上
*表示零次或多次出现:[a-zA-Z0-9_]*。 - 最后,我们使用
$确保这是字符串的结尾,防止匹配到后面还跟着其他内容的字符串。
完整的验证模式是:^[a-zA-Z_][a-zA-Z0-9_]*$。
现在,让我们将这个模式应用到几个例子中,检查其匹配是否正确。
以下是测试示例:
my_variable:匹配。变量名中可以使用下划线。my variable:不匹配。因为空格不是允许的字符。variable2:匹配。变量名内部可以使用数字。2nd_variable:不匹配。以数字开头的变量名无效,我们的模式第一个字符类不包含数字,因此不匹配。

总结与练习
本节课中我们一起学习了如何组合正则表达式的特殊字符来构建实用的文本匹配模式。我们实践了如何通过锚点精确匹配字符串的边界,以及如何根据规则(如Python变量名规则)构建复杂的验证模式。
正则表达式的基础知识我们已经涵盖。虽然还有更多特殊字符和高级用法可以探索,但相信你已经初步体会到正则表达式强大的文本处理能力,它是IT工具箱中又一个超级有用的工具。
这些内容有些复杂,但也充满乐趣。建议你花些时间,用刚学到的字符进行练习,看看能得到什么结果。记住,熟能生巧,这些小小的字符蕴含着强大的力量,它们能在你的IT工作中提供巨大帮助,值得你与之成为朋友。

接下来,我们提供了一份速查表,总结了目前学到的所有语法。之后,你可以通过一个小测验来检验所有这些新知识。完成后,我们下一个视频见。
111:捕获组 🎯

在本节课中,我们将要学习正则表达式中一个非常实用的概念:捕获组。之前我们已经使用 search() 函数来检查字符串是否匹配特定模式,但通常我们不仅想知道是否匹配,更希望提取匹配到的信息并用于后续操作。本节将详细介绍如何使用捕获组来提取和重组字符串中的特定部分。
从匹配到提取:捕获组的作用 🔍
上一节我们介绍了如何使用正则表达式进行基本匹配。本节中我们来看看如何提取匹配到的具体内容。
到目前为止,我们使用 search() 函数检查字符串是否匹配特定模式,但仅将结果打印出来。打印有助于确认匹配,但更多时候我们需要提取匹配的信息并用于其他操作。例如,从日志行中提取主机名或进程ID,并用该值执行其他操作。为此,我们需要使用正则表达式的捕获组概念。
捕获组是模式中由括号括起来的部分。
实战:使用捕获组重组姓名 ✏️

假设我们有一个存储为“姓, 名”格式的全名列表,我们希望将其转换为“名 姓”的格式。这可以通过使用带有捕获组的正则表达式来实现。
以下是实现此功能的具体步骤:
- 创建匹配模式:首先,创建一个匹配模式,该模式匹配一组字母,后跟逗号、空格,然后是另一组字母。
- 定义捕获组:为了捕获两组字母,我们将每组字母放在括号内,例如
(\w+), (\w+)。 - 使用
group()方法:匹配成功后,match对象的group()方法可以返回捕获的内容。
import re
result = re.search(r"(\w+), (\w+)", "Lovelace, Ada")
print(result.groups()) # 输出:('Lovelace', 'Ada')
因为我们定义了两个独立的组,groups() 方法返回一个包含两个元素的元组。
我们也可以使用索引来访问这些组。索引 0 对应整个正则表达式匹配的字符串,后续索引则对应每个捕获组。
print(result.group(0)) # 输出:Lovelace, Ada
print(result.group(1)) # 输出:Lovelace
print(result.group(2)) # 输出:Ada
利用这些索引,我们可以构造出想要的姓名格式。
构建重组姓名的函数 ⚙️
现在,让我们将上述逻辑封装成一个函数,以便重复使用。
我们定义一个名为 rearrange_name 的函数,它接收一个姓名作为参数。函数内部使用之前看到的模式进行搜索。如果结果为 None(即不匹配预期格式),则直接返回原姓名。如果匹配成功,则利用两个捕获组(逗号前的字符和逗号后的字符)返回重组后的字符串。
import re
def rearrange_name(name):
result = re.search(r"^(\w+), (\w+)$", name)
if result is None:
return name
return f"{result.group(2)} {result.group(1)}"
让我们用几个名字测试这个函数。
print(rearrange_name("Lovelace, Ada")) # 输出:Ada Lovelace
print(rearrange_name("Ritchie, Dennis")) # 输出:Dennis Ritchie
处理更复杂的情况:扩展字符集 🔧
上面的函数似乎运行良好,但如果输入更复杂的姓名呢?例如 “Hopper, Grace M.”。
此时,正则表达式无法匹配,因为我们使用了 \w 字符,它只匹配字母、数字和下划线,无法识别中间名缩写中的点和空格。
我们需要扩展模式中允许的字符集。对于这个例子,我们希望在名字部分允许空格和点号。对于其他情况,可能还需要包括连字符。
更新后的模式如下,我们在字符类 [] 中添加了空格和点号:
def rearrange_name(name):
result = re.search(r"^([\w \.-]*), ([\w \.-]*)$", name)
if result is None:
return name
return f"{result.group(2)} {result.group(1)}"
print(rearrange_name("Hopper, Grace M.")) # 输出:Grace M. Hopper
通过更新模式,我们的函数现在可以处理更复杂的姓名格式了。
总结 📝

本节课中我们一起学习了正则表达式中捕获组的核心用法。我们了解到:
- 捕获组通过括号
()定义,用于提取模式中匹配的特定部分。 - 匹配成功后,可以通过
match对象的group()或groups()方法访问捕获的内容。 - 索引
0返回整个匹配的字符串,索引1,2... 依次返回各捕获组的内容。 - 通过组合这些捕获的内容,我们可以对字符串进行有效的重组和转换。
- 为了使模式更具包容性,可以使用字符类(如
[\w \.-])来指定允许的字符集合。

捕获组是处理文本和提取信息的强大工具,相信你可以想出更多使用它的创意例子。下一节,我们将深入探讨重复限定符的更多用法。
112:Python正则表达式进阶 🧩

在本节课中,我们将要学习Python正则表达式中更强大的重复修饰符。之前我们已经接触了星号、加号和问号,现在我们将探索如何精确控制模式重复的次数,这对于处理具有固定格式的数据非常有用。
回顾基础重复修饰符
上一节我们介绍了*、+和?这三种基本的重复修饰符。它们分别代表“零次或多次”、“一次或多次”以及“零次或一次”的重复。
本节中我们来看看如何指定更精确的重复次数。
使用花括号指定重复次数
当我们需要一个模式重复特定次数时,手动重复书写模式会降低代码的可读性和可维护性。因此,Python提供了数字重复修饰符,它们写在花括号{}中。
以下是数字重复修饰符的几种形式:
{n}:精确重复n次。{n,}:至少重复n次,无上限。{,m}:最多重复m次(从零次开始)。{n,m}:重复n到m次。
精确匹配:{n}
例如,要匹配任何恰好由五个字母组成的字符串,我们可以使用这样的表达式:
pattern = r'\w{5}'
表达式将匹配给定字符串中符合标准的任何部分。
在这个例子中,我们寻找重复五次的字母单词。字符串“ghost”有五个字母,因此是一个匹配项。在实际的字符串中,可能有更多匹配项,但默认只返回第一个。要找到所有匹配项,我们需要使用findall函数。
import re
result = re.findall(r'\w{5}', 'I spotted a ghost in the hallway.')
print(result) # 输出: ['ghost', 'hallw']
这里“hallway”的前五个字母“hallw”也被匹配了。如果我们只想匹配完整的五个字母的单词,可以使用\b(单词边界)来限定模式的开始和结束。
result = re.findall(r'\b\w{5}\b', 'I spotted a ghost in the hallway.')
print(result) # 输出: ['ghost']
指定范围:{n,m}
我们也可以在花括号中指定两个数字来表示一个范围。例如,要匹配5到10个字母或数字,可以使用:
pattern = r'\w{5,10}'
无上限匹配:{n,}
范围也可以是开放式的。一个数字后面跟着逗号表示至少重复那么多次,没有上限,仅受源文本中最大重复次数的限制。
pattern = r'\w{5,}'
零到指定次数:{,m}

最后,一个逗号后面跟着一个数字表示从零次到该次数的重复。让我们看一个例子:
result = re.findall(r'S\w{,20}', 'I love strawberries and cream.')
print(result) # 输出: ['Strawberries']
这里我们寻找的模式是字母“S”后面跟着最多20个字母数字字符。因此我们得到了“Strawberries”的匹配项,它以“S”开头,后面跟着11个字符。
总结
本节课中我们一起学习了Python正则表达式中强大的数字重复修饰符 {}。我们掌握了如何精确指定重复次数({n})、设定重复范围({n,m})、要求至少重复多次({n,})以及限定最多重复次数({,m})。这些工具使我们能更灵活、更精确地匹配具有特定长度或格式的文本模式。
虽然“ghost”和“strawberries”的例子很有趣,但我们现在已经准备好学习更多关于如何使用正则表达式解决实际问题的例子了。我们将在下一个视频中继续探索。
113:使用正则表达式从Python中提取PID 🆔

在本节课中,我们将学习如何运用正则表达式,从复杂的文本(如日志行)中提取特定信息,例如进程ID。我们将通过一个具体的例子,逐步解析正则表达式的构成,并编写一个健壮的Python函数来完成提取任务。
还记得我们在本模块第一个视频中讨论正则表达式时看到的例子吗?当时我们查看了日志行,并尝试提取其中的进程ID。现在,我们已经掌握了足够的知识来完全理解那个例子。让我们一步步来分析它。
解析正则表达式模式
首先,我们来看用于匹配进程ID的正则表达式模式:\[(\d+)\]。
- 模式的第一个字符是反斜杠
\,它被用作转义字符。 - 这意味着下一个字符——在这里是一个方括号
[——将被按字面意义进行匹配,而不是作为特殊字符。 - 在方括号之后是第一个圆括号
(。由于它没有被转义,我们知道它将用作一个捕获组。 - 捕获组的圆括号包裹着
\d+符号。 - 根据我们对特殊字符和重复限定符的讨论,我们知道
\d匹配任何数字字符,而+表示“一个或多个”。因此,这个表达式将匹配一个或多个数字字符。 - 在捕获组的闭括号之后,我们有一个闭方括号符号
],它前面也有转义字符。
在Python中应用搜索
在调用 re.search() 函数后,我们知道,因为我们在表达式中定义了捕获组,所以可以通过访问索引 1 处的值来获取匹配的数据。
import re
log_line = "July 31 07:51:48 mycomputer bad_process[12345]: ERROR Performing package upgrade"
regex = r"\[(\d+)\]"
result = re.search(regex, log_line)
print(result[1]) # 输出: 12345
让我们在一个不同的字符串上尝试我们的表达式,以验证无论其余文本是什么,它都能正常工作。
print(re.search(r"\[(\d+)\]", "A completely different string with [12345] in it.")[1]) # 输出: 12345
处理匹配失败的情况
但是,如果我们的字符串的方括号之间实际上没有数字块呢?
# 这将导致错误
# print(re.search(r"\[(\d+)\]", "99 elephants in a [cage]")[1])
程序出错了。发生了什么?我们试图访问一个值为 None 的变量的索引 [1]。正如Python告诉我们的,这是无法做到的。那么我们应该怎么做呢?
我们应该创建一个函数,在可能的情况下提取进程ID,如果无法提取则执行其他操作。思路如下:
创建健壮的提取函数
我们将定义一个名为 extract_pid 的函数。
- 首先,我们使用之前相同的正则表达式,并将
search函数的结果存储在result变量中。 - 我们知道,如果搜索不成功,
result将是None。因此,我们需要在这里做一些不同的处理。 - 我们选择做什么取决于我们希望代码的其余部分如何运行。假设如果我们找不到PID,就返回一个空字符串。
- 最后,如果程序执行到这一步,意味着
result是一个匹配对象,因此我们可以访问第一个捕获组并返回它。
以下是该函数的实现:
import re
def extract_pid(log_line):
regex = r"\[(\d+)\]"
result = re.search(regex, log_line)
if result is None:
return ""
return result[1]
现在,我们可以用原始的日志行测试我们的函数,检查它是否仍然正常工作。
print(extract_pid("July 31 07:51:48 mycomputer bad_process[12345]: ERROR Performing package upgrade"))
# 输出: 12345
最后,让我们用之前导致代码崩溃的字符串来测试它。
print(extract_pid("99 elephants in a [cage]"))
# 输出: (一个空字符串)

太好了!它没有匹配到任何内容,因此返回了一个空字符串。这正是我们想要的。
总结
在本节课中,我们一起学习了如何构建一个健壮的函数,使用正则表达式从日志行中正确提取进程ID,而不会因为不匹配的文本行导致程序崩溃。我们解析了正则表达式 \[(\d+)\] 的每个部分,理解了转义字符、捕获组和特殊序列 \d 的作用。然后,我们编写了 extract_pid 函数,它通过检查 re.search() 的返回值是否为 None 来优雅地处理匹配失败的情况。
希望现在这一切都开始变得清晰了。请记住,如果还有不太明白的地方,你可以随时复习课程内容并进行练习,直到你感到得心应手。
接下来,在我们探索正则表达式的最后一步,我们将查看 re 模块提供的其他一些有用函数。
114:分割与替换 🧩

在本节课中,我们将要学习Python re 模块中两个非常实用的函数:split 和 sub。我们将了解如何使用正则表达式来分割字符串,以及如何查找并替换文本中的模式。掌握这些技能将帮助你更高效地处理和分析文本数据。
1. 使用 split 函数分割字符串
上一节我们介绍了 search 和 findall 函数,本节中我们来看看 re 模块中的 split 函数。
split 函数的工作方式与我们之前用于字符串的 split 方法类似,但关键区别在于,它可以使用任何正则表达式作为分隔符,而不仅仅是一个固定的字符串。
例如,我们可能希望将一段文本分割成独立的句子。为此,我们不仅需要匹配句点,还需要匹配问号或感叹号,因为它们也是有效的句子结尾。实现方式如下:
import re
text = "Hello world! How are you? I'm fine."
sentences = re.split(r'[.!?]', text)
print(sentences)
# 输出: ['Hello world', ' How are you', " I'm fine", '']
请注意,我们写在方括号内的字符没有进行转义。这是因为在方括号内的任何内容都被视为字面字符,而不是其特殊含义。同时,分割符号本身不会出现在结果列表中。
如果我们希望分割后的列表包含用于分割的符号本身,可以使用捕获括号,如下所示:
sentences_with_marks = re.split(r'([.!?])', text)
print(sentences_with_marks)
# 输出: ['Hello world', '!', ' How are you', '?', " I'm fine", '.', '']
这样,我们就得到了句子和标点符号共同组成的列表元素。
2. 使用 sub 函数替换文本
另一个由 re 模块提供的实用函数是 sub。它用于通过将匹配到的部分或全部模式替换为不同的字符串来创建新字符串。
它类似于字符串的 replace 方法,但区别在于它使用正则表达式进行匹配和替换。让我们通过一个例子来理解。
假设我们的系统日志中包含用户的电子邮件地址,我们需要通过移除所有地址来匿名化数据。我们可以使用一个正则表达式来实现:
import re
log = "User contact: alice@example.com. Error reported by bob+test@company.co.uk."
anonymized_log = re.sub(r'[\w.%+-]+@[\w.-]+', '[REDACTED]', log)
print(anonymized_log)
# 输出: User contact: [REDACTED]. Error reported by [REDACTED].
我们用于识别电子邮件地址的表达式有两部分:@ 符号前的部分和其后的部分。
@符号前,我们包含了字母数字字符(用\w表示,包括字母、数字和下划线),以及点号、百分号、加号和短横线。@符号后,我们只允许字母数字字符、点号和短横线。
这个模式会匹配所有电子邮件地址,以及一些并非真正有效的地址(例如包含两个连续点号的地址)。在此场景下,我们宁愿“安全第一”,因此会屏蔽任何看起来像地址的内容。如果我们想验证地址是否真实有效,则需要制定严格得多的规则。
3. 在替换中使用捕获组
我们刚刚看了在纯字符串搜索和替换中使用正则表达式的例子。现在,让我们看一个在替换中也使用正则表达式的 sub 函数示例。
为此,我们回到之前调整人名顺序的代码,并使用 sub 来创建新字符串。
import re

name = "Lovelace, Ada"
# 使用捕获组匹配“姓, 名”的格式
swapped_name = re.sub(r'(\w+), (\w+)', r'\2 \1', name)
print(swapped_name)
# 输出: Ada Lovelace
我们再次使用括号创建了捕获组。
- 在第一个参数(模式)中,我们有一个包含两个欲匹配组的表达式:逗号前的一组和逗号后的一组。
- 在第二个参数(替换字符串)中,我们使用
\2来引用第二个捕获组(名字),后跟一个空格,再使用\1来引用第一个捕获组(姓氏)。
当引用捕获组时,反斜杠后跟一个数字表示对应的捕获组。这是正则表达式的通用表示法,不仅限于Python,许多支持正则表达式的工具都使用它。
我们还可以使用它们来匹配自身重复的模式,这被称为“反向引用”。我们在此不深入探讨,但如果你想了解更多,可以在网上找到大量相关信息。
总结
本节课中我们一起学习了Python正则表达式中两个强大的函数:split 和 sub。
split函数允许我们使用复杂的正则表达式模式作为分隔符来分割字符串。sub函数则允许我们查找并替换文本中匹配特定模式的部分,并且在替换时可以利用捕获组来重组文本。
虽然正则表达式并不简单,但它们极其有用,因此值得投入精力去掌握。为了帮助你巩固所学,接下来有一个练习测验,之后你将可以进入下一个实验环节。
115:文件路径 📂

在本节课中,我们将要学习文件路径的概念、类型及其在Python编程中的重要性。理解文件路径是自动化处理文件和与操作系统交互的基础。
概述
程序员通过代码指挥计算机执行任务,正如驯犬师使用指令和零食引导犬只。为了让程序(包括Python程序)正常运行,应用程序需要调用存储在本地计算机或云端的一个或多个文件,而调用这些文件的关键就是使用它们的文件路径。
什么是文件路径?
文件路径是文件在计算机或网络服务器上的具体位置。在Python代码中,文件路径被写成一个字符串,该字符串复制了本地机器上的文件路径,或通过URL检索到的远程服务器上的文件位置。
你还可以使用文件路径来调用环境变量,例如库、应用程序,甚至其他语言(如C++或JavaScript)。
文件路径的两种类型
文件路径主要分为两种:相对路径和绝对路径。理解它们的区别对于编写可移植的代码至关重要。
以下是两种路径类型的核心区别:
- 相对文件路径:仅通过文件名来读写文件。它默认指向最初运行Python命令的特定目录。由于其灵活性,可以在任何计算机上调用所需文件,因此通常是首选。
- 示例:
target_file.txt
- 示例:
- 绝对文件路径:详细说明文件的确切位置,格式为:驱动器名 -> 目录 -> 文件名。Python程序员倾向于避免使用绝对路径,因为驱动器名称可能因计算机而异。
- Windows示例:
C:\my_directory\target_file.txt - Mac/Linux示例:
/home/username/my_directory/target_file.txt
- Windows示例:
跨平台的注意事项
尽管Python脚本可以在任何能运行Python的计算机上执行,但依赖于Windows特定路径和文件系统的脚本可能无法在Mac或Linux上运行,反之亦然。不过,使用Mac和Linux文件路径的脚本可以无缝协作。
由于Windows与Mac/Linux之间的文件结构差异,许多Python程序员使用os.path命令来包装目录路径,以规避平台差异。
文件路径的常见用途

文件路径最常用于保存和加载信息。例如,在一个网络爬虫工具中,Python可以用来加载网页并将其内容保存到你计算机上选择的文件夹中。
常见错误与最佳实践
只要注意操作,文件路径的使用是非常直观的。最常见的错误发生在程序员混淆了“Python函数被调用的位置”与“调用该函数的脚本所在的位置”。
为了避免混淆,请记住:相对路径是相对于当前工作目录的,而当前工作目录可能因你运行脚本的方式而异。
总结
本节课我们一起学习了文件路径的核心知识。我们了解到,文件路径是文件在计算机或服务器上的具体位置,可用于调用环境变量。我们重点区分了相对路径和绝对路径,并明白了为何相对路径因其更好的可移植性而更受青睐。同时,我们也注意到了不同操作系统(Windows vs. Mac/Linux)在路径表示上的差异,以及使用os.path等工具处理这些差异的重要性。
回到驯犬师的类比,你使用零食和命令决定了狗的行为;同样地,你通过文件路径调用的应用程序、库和其他环境变量,决定了你的代码能做什么以及它完成任务的方式。
下一节,我们将探讨在具体的编程情境中如何使用文件路径。
116:Python文件路径编写指南 🗺️

概述
在本节课中,我们将学习如何在Python代码中编写和使用文件路径。文件路径是程序定位和操作文件、目录或环境变量的“路线图”。理解并正确使用文件路径,对于实现文件读写、数据存储和加载外部资源等自动化任务至关重要。
文件路径的本质与用途
上一节我们介绍了文件路径的基本概念,本节中我们来看看如何在代码中实际运用它们。
文件路径最常见的用途是:将信息保存到目标位置,或者从特定位置加载信息、应用程序或环境变量。因此,将文件路径视为指向文件或目录的“指引”会很有帮助。
例如,假设你正在编写一个应用程序,用于从网站检索特定的归档内容,并按日期将其存储到历史文件中。你的代码需要包含归档内容的文件路径位置,这样应用程序才知道去哪里寻找你指定的内容参数。检索到内容后,另一行或另一段代码会告诉应用程序在何处创建历史文件并存储信息。
关键在于,一旦你提供了正确的“指引”,你的应用程序就能轻松地找到并操作信息,根据代码中的命令进行加载、复制和重新保存。
操作系统与文件路径结构
正如你所知,文件路径的具体结构取决于你编写代码所使用的操作系统。
以下是不同操作系统下文件路径的差异:
- Windows:文件路径通常以驱动器名开头,如
C:或D:。 - macOS 和 Linux:文件路径以斜杠
/开头,这代表根目录。这个斜杠有时被称为正斜杠。
文件路径中的目录也由斜杠分隔。Windows 通常使用反斜杠 \,因此路径看起来像这样:
C:\my-directory\target_file.txt
但是,在 Python 中编写文件路径时,你可以使用正斜杠 /,路径看起来像这样:
C:/my-directory/target_file.txt
事实上,推荐使用正斜杠。因为反斜杠在 Python 中是特殊字符,如果你在文件路径中使用它,必须再次使用它来转义每一个实例,如下所示:
C:\\my-directory\\target_file.txt
绝对路径与相对路径
根斜杠和驱动器字母在使用绝对文件路径时很重要。但你也可以使用相对文件路径作为快捷方式,前提是使用当前工作目录作为文件路径的基础。
要使用当前目录,可以在代码中使用 os.getcwd() 命令,后接你想要访问的文件名。

以下是获取和设置当前目录命令的示例:
outputs['current_directory_before'] = os.getcwd()
常用文件路径操作
获取和设置当前目录只是在 Python 中使用文件路径引用外部文件的方法之一。
以下是其他几种常用操作:
-
列出文件和目录:使用以下代码可以列出当前目录下的内容,以找到所需的文件路径。
outputs['files_and_directories'] = os.listdir() -
访问环境变量路径:可以通过输入以下命令来获取环境变量的路径值。
outputs['path_value'] = os.environ.get('PATH')

在引用外部文件时,具体使用哪些命令,完全取决于你希望通过代码实现什么目标:创建或删除目录、创建、打开或删除文件、处理不同的文件路径,或是其他任务的组合。
实践与最佳实践
当然,学习文件路径及其工作原理的最佳方式,就是在你编写的代码以及更高级的 Python 训练项目中实际使用它们。
本视频仅涵盖了在代码中使用文件路径的基本原则。请记住,在代码中使用它们时,最好将文件路径简单地视为找到所需文件、应用程序或变量位置的“指引”。
以下是核心最佳实践总结:

- 使用正斜杠:在代码中编写文件路径时使用正斜杠
/,应被视为最佳实践。 - 理解路径类型:斜杠和驱动器字母或根目录在使用绝对文件路径时很重要。但你也可以使用相对文件路径作为快捷方式,通过当前工作目录直接使用文件或应用程序名。
- 多加练习:文件路径对于代码通常是必需的。正确使用时,它们可以使你的 Python 代码和生成的应用程序更好、更高效。这一切都归结于熟悉和练习。
总结
本节课中我们一起学习了如何在 Python 代码中编写文件路径。我们了解了文件路径作为“指引”的核心作用,比较了不同操作系统下的路径格式差异,强调了使用正斜杠的最佳实践,并区分了绝对路径与相对路径的用法。最后,我们还介绍了几种通过 os 模块操作文件路径的常用方法。掌握这些知识,将帮助你更高效地处理文件操作,为自动化任务打下坚实基础。
117:正则表达式 🧩
在本节课中,我们将回顾正则表达式模块的核心内容,总结所学知识,并了解如何在实际练习中应用这些技能。

概述 📋
在过去的视频中,我们从对正则表达式一无所知,到能够在不同文本中执行复杂的搜索和替换操作。我们涵盖了许多技术性内容,现在来总结一下。
正则表达式的核心概念
正则表达式是一种强大的文本处理工具,它使用特定的模式来匹配、搜索或替换字符串。以下是一些核心概念:
- 模式(Pattern):定义搜索规则的字符串,例如
\d+匹配一个或多个数字。 - 匹配(Match):在目标字符串中找到符合模式的文本片段。
- 搜索(Search):在字符串中查找第一个符合模式的位置。
- 替换(Replace):将匹配到的文本替换为指定的新文本。
在Python中,我们使用 re 模块来处理正则表达式。基本操作代码如下:
import re
# 搜索示例
pattern = r"\d+"
text = "订单号是12345"
match = re.search(pattern, text)
if match:
print(f"找到数字: {match.group()}") # 输出:找到数字: 12345
# 替换示例
new_text = re.sub(r"\d+", "***", text)
print(new_text) # 输出:订单号是***
学习感受与建议
这些内容可能让人感到有些压力,这完全正常。即使经验丰富的系统管理员也会觉得正则表达式具有挑战性,要准确掌握它们可能比较棘手。
虽然正则表达式可能有些令人困惑,但请不要被它们吓倒。如果你的脚本需要处理文本,它们可以为你节省大量时间和精力。
掌握正则表达式的关键方法
和许多技能一样,熟悉正则表达式的最佳方法就是使用它们。
以下是帮助你练习的建议步骤:
- 尝试视频中的例子:重新运行课程中演示的代码示例。
- 创造自己的模式:发明一些自己的正则表达式模式,观察它们的行为。
- 在即将到来的实验中进行实践:你将有机会在实验中将新获得的正则表达式技能付诸实践,以解决实际问题。
关于实验的说明
在练习中,你将像之前的实验一样处理CSV文件,但这次你将使用正则表达式来查找需要处理的数据并对其进行操作。
Quicklabs上使用虚拟机的时间是有限的,因此我们建议你先尝试在自己的计算机上解决问题。
一旦你对自己编写的代码有信心,就可以开始实验并让你的代码发挥作用。
总结 ✨
本节课我们一起回顾了正则表达式模块的学习旅程。我们总结了从基础模式匹配到复杂文本处理的核心概念,并强调了通过实践来巩固技能的重要性。请准备好将所学知识应用于接下来的实验挑战中,我们另一边见。
118:管理数据和进程介绍 🚀


在本节课中,我们将学习如何让Python程序与运行中的操作系统进行交互。我们将探索如何读取用户输入、利用操作系统提供的数据流,以及如何从Python中执行系统命令。最后,我们会学习如何分析和处理对IT专家至关重要的日志文件。
回顾与展望 📋
欢迎回来。恭喜你完成了上一个实验。你正在取得巨大进步,每学会一个新工具,你的视野都在随之扩展。
执行一个脚本并看到它按预期运行,这一定很有成就感。希望随着你学习Python提供的更多工具,你能看到越来越多的自动化可能性。
让我们快速回顾一下你在本课程中学到的所有内容。首先,你安装了Python并设置了本地环境。然后,我们深入学习了如何用Python管理文件。最后,我们开始学习正则表达式。
在本模块中,我们将探讨有助于我们与运行中的操作系统交互的概念,并看看如何充分利用可用的工具。
课程内容概览 🗺️
我们将从讨论如何交互式地读取用户数据开始。接着,我们将探索操作系统提供的标准输入和输出数据流,并看看如何从Python程序和系统程序与它们交互。
在我们的许多示例中,我们将通过命令行与操作系统交互。因此,我们将开始更熟悉Linux Shell。我们还将讨论如何从Python执行系统命令。
这允许我们的脚本利用操作系统其余部分的功能。因此,了解如何操作这些命令的输出并处理任何生成的错误对我们来说很重要。
最后,我们将深入探讨IT专家的一个重要信息来源:日志文件。我们已经在之前的一些视频中瞥见过几个日志文件。现在,我们将看看如何利用我们在整个课程中学到的工具来理解这些日志文件所提供的信息。
所以,我们面前有许多有趣的内容。你感到兴奋吗?我很兴奋。
那么,我们还等什么呢?让我们开始吧。
总结 📝
本节课中,我们一起学习了本模块的总体目标:探索Python与操作系统交互的核心方法。我们了解到,接下来将学习交互式输入、数据流处理、命令行操作、系统命令执行以及日志文件分析。这些技能将极大地扩展我们自动化任务的能力。
119:Python交互式读取用户输入 🖥️
课程编号:P119

在本节课中,我们将要学习如何在Python脚本中与用户进行交互,通过input()函数读取用户输入的数据,并将其用于自动化任务中。
我们之前已经讨论过文件的读取和写入操作。
使用文件存储信息,然后通过脚本处理这些数据,是实现自动化的有效方法。
但有时,我们需要与用户交互,询问一些无法存储在文件中的特定信息。
为此,Python提供了一个名为input的函数。
这个函数允许我们提示用户输入某个值,然后我们可以在脚本中使用这个值。
让我们看看具体是如何实现的。
一个简单的示例:问候脚本 👋
以下是一个名为hello.py的简单脚本。
它请求用户输入姓名,然后打印一条包含该姓名的问候语。
让我们执行这个脚本来看看效果。
name = input("请输入你的名字:")
print("你好," + name + "!")
input函数总是返回一个字符串。
如果我们希望读取的数据是其他数据类型,例如数字或日期,那么我们需要将字符串转换为我们想要的格式。
一个更复杂的示例:时间转换器 ⏱️
上一节我们介绍了简单的输入,本节中我们来看看一个更复杂的例子。
这个脚本执行多项操作,让我们逐段分析。
首先,我们定义一个函数,将小时、分钟和秒数转换为总秒数。
def to_seconds(hours, minutes, seconds):
return hours*3600 + minutes*60 + seconds
实际程序从打印欢迎信息开始,然后进入一个while循环。
注意,我们首先初始化了一个用于检查用户是否希望继续的变量cont。
cont = "y"
while cont.lower() == "y":
在while循环的主体中,我们请求用户提供要转换的小时、分钟和秒数。
由于我们的to_seconds函数需要整数参数,我们使用int()函数来转换input函数返回的值。
hours = int(input("请输入小时数:"))
minutes = int(input("请输入分钟数:"))
seconds = int(input("请输入秒数:"))
获得这三个值后,我们调用函数并打印结果。
print("总秒数是:" + str(to_seconds(hours, minutes, seconds)))
之后,我们询问用户是否希望进行另一次转换。
cont = input("是否继续? (y/n): ")
让我们尝试运行这个脚本,看看会发生什么。
我们的代码似乎运行正常。
我们输入了三个数字,它正确地进行了转换。
现在它询问我们是否要继续。

我们回答“是”,就可以进行下一次转换。
当我们回答“否”时,程序结束并退出。
总结 📝
本节课中我们一起学习了如何通过input()函数与用户进行交互式对话。
虽然交互式地向用户请求输入并不总是解决问题的最佳方法,但它是一个强大的工具,现在已加入你的IT工具箱中。
在本模块开始仅几分钟的时间里,你已经掌握了一个新概念。
想象一下,到本模块结束时,你将学到多少知识。
120:标准流 🖥️

概述
在本节课中,我们将要学习程序如何与外部世界进行信息交换。具体来说,我们将探讨输入/输出(IO)流的概念,了解标准输入、标准输出和标准错误这三种基本流的作用与区别。
什么是IO流?
上一节我们介绍了通过文件读写和键盘输入/屏幕输出的方式与程序交互。本节中我们来看看这些交互背后是如何实现的。
IO流是程序执行输入和输出操作的基本机制。你可以将这些流想象成程序与其输入源(如键盘)或输出目标(如屏幕)之间的通路。数据在这些通路中持续流动,因此被称为“流”。
三种标准IO流
大多数操作系统默认提供三种不同的IO流,每种都有其特定用途。
以下是三种标准流的详细介绍:
-
标准输入(STDIN)
- 这是程序与输入源(通常是键盘)之间的通道,数据通常以文本形式传递。
- 在Python脚本中使用
input()函数接收用户输入时,我们使用的就是标准输入流。
-
标准输出(STDOUT)
- 这是程序与输出目标(如显示器)之间的通路。
- 它通常表现为在终端中显示的文本。当我们使用
print()函数向屏幕写入信息时,就是在使用标准输出流。
-
标准错误(STDERR)
- 标准错误也用于显示输出,但它专门用作显示程序错误消息和诊断信息的通道。
- 它通常也会被打印到屏幕上。如果你运行Python代码时收到错误信息,那么该信息很可能就是通过标准错误流打印的。

代码示例解析
让我们通过一个例子来巩固理解。
# 第一行:从标准输入读取数据
data = input()
# 第二行:向标准输出写入数据
print(data)
# 第三行:制造一个错误(将字符串与整数拼接),该错误信息将通过标准错误输出
result = “hello” + 123
在这段脚本中:
- 第一行通过
input()从标准输入(键盘)读取数据。 - 第二行通过
print()将数据写入标准输出(屏幕)。 - 第三行尝试将字符串与整数拼接,这会引发一个
TypeError。这个错误信息将通过标准错误流输出。
系统命令中的IO流
需要强调的是,IO流并非Python程序独有。当我们运行系统命令时,同样在使用这些流。
例如,使用 cat 命令显示文件内容时,这些内容是通过标准输出流打印到终端的。
cat myfile.txt
而当命令产生错误时,错误信息则通过标准错误流显示。
ls --unsupported-flag
(此命令会因使用了不支持的标志而返回错误)

目前,标准输出和标准错误看起来都显示在屏幕上,所以似乎相同。但它们本质上是不同的通道,我们将在课程后续深入探讨它们的区别。
总结
本节课中我们一起学习了IO流的核心概念。我们了解到,IO流是程序提供和接收信息的途径,主要包括标准输入(STDIN)、标准输出(STDOUT)和标准错误(STDERR)三种。在接下来的课程中,我们将学习如何将这些流重定向到其他文件或进程,并探索向程序提供信息的其他方式,如环境变量和命令行参数。
121:环境变量 🌍

在本节课中,我们将要学习什么是环境变量,以及如何在Linux命令行和Python脚本中读取和使用它们。环境变量是操作系统和程序之间传递信息的一种方式,理解它们可以帮助我们更好地控制程序的行为。
当我们打开Linux计算机上的终端应用程序时,无论是本地计算机还是远程机器,读取和执行我们命令的应用程序被称为shell。
shell是一种命令行界面,用于与操作系统进行交互。Linux上最常用的shell是bash。其他流行的shell包括ZSH和fish。尽管它们在操作方式上相似,但在接下来的视频中,当我们提到Linux shell时,我们指的是bash。
我们的Python程序在shell命令行环境中执行。在该环境中设置的变量,被称为环境变量,是我们在脚本中可以使用的另一个信息来源。
环境变量的作用与查看 🔍

理解并能够更改环境变量对于快速改变程序行为非常有用。通常,我们只需对程序运行的环境进行一些微小的更改即可实现这一点。
从命令行提示符中,我们可以使用env或printenv命令来检查这些变量。让我们来看一下。
$ env
哇,有很多不同的变量,但它们有什么用呢?这完全取决于变量本身。有些变量比其他变量更重要。例如,PATH变量就是一个非常重要的变量。让我们使用echo命令仅打印出该变量的内容。
作为复习,echo是我们在Linux shell中用于打印文本的命令。当我们想要访问shell中变量的值时,我们需要在变量名前加上美元符号$。
$ echo $PATH
这里我们打印了PATH变量的内容。shell使用这个环境变量来确定当我们调用可执行文件时,应该在哪里查找它们,而无需指定完整目录路径。
列出的所有目录都是shell将查找程序的地方。例如,当我们调用python3程序时,shell会按顺序检查PATH变量中列出的每个目录。当它找到一个名为python3的程序时,就会执行它。
在Python中读取环境变量 🐍
正如我们所说,我们可以从Python中读取这些变量的内容。让我们用一个Python脚本来验证一下。
为了访问环境变量,我们使用os模块提供的environ字典。在这种情况下,我们使用了一个之前未用过的字典方法:.get()方法。
.get()方法与我们迄今为止访问字典值的方式有些相似。区别在于当值不存在时会发生什么。
当我们使用键来检索字典中的值时(例如os.environ['FRUIT']),如果键不存在,我们会得到一个错误。如果我们改用.get()方法,则可以指定当键不存在时应返回什么值。换句话说,.get()方法允许我们在查找的键不在字典中时指定一个默认值。
以下脚本尝试检索与键关联的值,但如果键未定义,则返回一个空字符串。我们对三个不同的变量HOME、SHELL和FRUIT执行此操作。
#!/usr/bin/env python3
import os
home = os.environ.get('HOME', '')
shell = os.environ.get('SHELL', '')
fruit = os.environ.get('FRUIT', '')
print(f"HOME: {home}")
print(f"SHELL: {shell}")
print(f"FRUIT: {fruit}")
让我们运行脚本看看会发生什么。
$ python3 script.py
我们得到了HOME和SHELL的值,但没有得到FRUIT的值。这是因为该变量在当前环境中没有定义。
设置环境变量 ⚙️
为了让我们的脚本能够看到FRUIT变量,我们需要在命令行中定义它。我们通过使用等号设置一个值来定义变量,并且等号前后不能有空格。此外,export关键字告诉shell,我们希望我们设置的值能被我们调用的任何命令看到。
$ export FRUIT=Pineapple
现在,让我们再次调用我们的脚本。
$ python3 script.py
很好!这次我们得到了我们想要的值。所以你现在知道了如何从Python脚本中获取任何环境变量的值。

总结 📝
在本节课中,我们一起学习了:
- Shell是命令行接口,bash是Linux上常用的shell。
- 环境变量是存储在shell环境中的键值对,程序可以读取它们来获取配置信息。
- 可以使用
echo $VARIABLE_NAME在命令行中查看环境变量的值。 - 在Python中,可以通过
os.environ字典或更安全的os.environ.get('KEY', 'default')方法来访问环境变量。 - 可以使用
export VARIABLE_NAME=value在命令行中设置环境变量,使其对后续命令可用。
理解环境变量是自动化和管理系统配置的基础。接下来,我们将深入探讨命令行如何告诉我们它们是成功还是失败了。
122:命令行参数与退出状态 🖥️

在本节课中,我们将要学习如何通过命令行参数向程序传递信息,以及如何利用退出状态来判断程序是否成功执行。这两个概念对于编写自动化脚本至关重要。

概述
到目前为止,我们已经了解了不同程序如何读写标准输入输出流,以及Shell环境如何影响程序的执行。另一种向程序提供信息的常见方式是通过命令行参数。
命令行参数
命令行参数是在程序启动时传递给它的参数。让脚本通过命令行参数接收特定值是一种非常常见的做法。这样做可以使脚本代码保持通用,同时允许我们自动运行脚本,无需任何交互式用户输入。这意味着这些参数对于系统管理任务非常有用,因为我们可以指定程序在启动前需要使用的信息,从而创建越来越多的自动化流程。
我们可以使用sys模块中的argv列表来访问这些值。让我们通过执行一个非常简单的脚本来查看这个列表的内容。
以下是argv脚本的代码:
import sys
print(sys.argv)
现在,让我们看看调用程序时会发生什么。
首先,我们调用脚本时不带任何参数:
$ python3 argv.py
['argv.py']
列表包含一个元素,即我们刚刚执行的程序名称。
接下来,我们尝试传递几个参数:
$ python3 argv.py hello world 123
['argv.py', 'hello', 'world', '123']

现在我们可以看到,我们传递的每个参数都作为列表中的一个独立元素被包含进来。
退出状态
接下来,我们介绍退出状态(或返回码)的概念。它提供了Shell与其内部执行的程序之间的另一个信息源。

退出状态是程序返回给Shell的值。在所有类Unix操作系统中,进程成功时退出状态为0,失败时则不为0。返回的实际数字提供了关于程序遇到何种错误的额外信息。
了解命令是否成功完成是有用的信息,可以被调用该命令的程序使用。例如,如果命令失败,程序可以利用此信息重试该命令。
要检查程序的退出状态,我们可以使用一个特殊的变量来查看最后执行的命令的退出状态。这个变量是$?变量,因此要查看其内容,我们使用echo $?。
让我们使用wc命令来尝试一下,该命令用于统计文件中的行数、单词数和字符数。
首先,我们将其传递给我们的variables.py脚本并检查退出值:
$ wc variables.py
5 13 105 variables.py
$ echo $?
0
在这里,我们首先运行了wc命令,它打印了Python脚本的行数、单词数和字符数。然后我们打印了$?变量的内容,可以看到退出值为0,这是因为wc成功运行了。
现在,我们尝试对一个不存在的文件运行wc:
$ wc non_existent_file.txt
wc: non_existent_file.txt: No such file or directory
$ echo $?
1
命令打印了一个错误,当我们打印$?变量的内容时,我们看到它以退出值1结束。
Python脚本的退出状态
以上是针对系统命令的,那么Python脚本呢?当一个Python脚本成功完成时,它以退出值0退出。当它因错误(如TypeError或ValueError)而结束时,则以非零值退出。我们可以让它以任何相关的值退出。
让我们看一个例子。以下脚本接收一个文件名作为命令行参数。它首先检查文件名是否存在。当文件不存在时,它通过写入一行来创建该文件。当文件存在时,我们的脚本会打印一条错误消息并以退出值1退出。
以下是脚本代码:
import sys
import os
filename = sys.argv[1]
if os.path.exists(filename):
print(f"Error: The file '{filename}' already exists.")
sys.exit(1)
else:
with open(filename, 'w') as f:
f.write("File created successfully.\n")
print(f"File '{filename}' created.")
为了尝试这个脚本,我们首先执行它并传递一个不存在的文件:
$ python3 exit_status.py new_file.txt
File 'new_file.txt' created.
$ echo $?
0
很好,看起来成功了。请注意,它以退出代码0退出,即使我们在代码中没有明确指定这一点,因为这是默认行为。
让我们查看文件内容以确保它包含应有的内容:
$ cat new_file.txt
File created successfully.

现在,如果我们再次运行相同的命令,你认为会发生什么?
$ python3 exit_status.py new_file.txt
Error: The file 'new_file.txt' already exists.
$ echo $?
1
你猜对了,我们得到一个错误,因为文件已经存在,因此我们得到退出代码1。
总结
本节课中我们一起学习了如何向Python程序传递命令行参数,以及如何让程序告诉我们它们是否成功完成。这两个都是创建自动化时将使用的重要工具。
我们将使用命令行参数来告诉我们的程序我们希望它们做什么,而无需与它们交互。我们将使用退出值来了解命令是成功还是失败,然后记录失败并在需要时自动重试命令。
在过去的几个视频中,我们肯定学到了很多。有时可能会有点棘手,但你在不让这些复杂概念阻止你前进方面做得非常出色。😊 既然你已经走到这一步,你必将掌握所有让我们的代码与Shell环境交互的方法。

一如既往,请花时间复习,然后前往测验,将你的新知识付诸实践。
123:在Python中运行系统命令 🖥️

在本节课中,我们将学习如何在Python脚本中执行系统命令。我们将探索subprocess模块,了解如何运行外部程序、处理其输出,以及根据命令的执行结果做出决策。
概述
到目前为止,我们主要通过Python的内置功能与操作系统交互。例如,我们使用文件对象读取文件内容,使用os模块检查磁盘空间,或使用sys模块处理标准输入和退出代码。
然而,有时我们需要从Python脚本中直接运行系统程序。例如,你可能需要在脚本中发送ICMP数据包来检查主机是否响应。与其寻找提供此功能的外部Python模块,不如直接运行系统自带的ping命令。
在某些情况下,使用系统命令来完成特定任务或利用Python模块(无论是内置还是第三方)中不存在的功能,可能更简单、更快捷。为此,Python的subprocess模块提供了在脚本中执行系统命令的方法。
运行简单命令
让我们看一个例子。首先,我们导入subprocess模块,然后使用subprocess.run()函数调用显示当前日期的date命令。
import subprocess
subprocess.run(["date"])
run函数返回一个CompletedProcess类型的对象。该对象包含与命令执行相关的信息。从打印的信息中,我们可以看到命令的返回代码是0。
理解子进程
为了运行外部命令,会为子进程(或称为subprocess)创建一个独立的环境来执行该命令。


当父进程(即我们的脚本)等待子进程完成时,它会被阻塞。这意味着在子进程结束之前,父进程无法执行任何其他工作。


许多为人父母者可能会对此深有体会。
外部命令完成其工作后,子进程退出,控制流返回到父进程。然后,脚本可以继续正常执行。
让我们通过调用sleep命令来观察这个过程,该命令会等待我们指定的秒数后再返回。
subprocess.run(["sleep", "2"])
你可能已经注意到,当sleep命令运行时,Python解释器被阻塞,我们无法与其交互。这正是我们所说的父进程在子进程完成前被阻塞的含义。
传递命令行参数
请注意我们是如何调用命令的。run函数接收一个列表,列表的第一个元素是我们想要调用的命令名称,后面跟着任何我们想要传递给该命令的参数。
因此,程序名之后的任何元素都是它的命令行参数。在上面的例子中,我们请求sleep等待两秒钟。
处理命令失败
在前两个例子中,命令都成功执行,因此CompletedProcess实例中的返回代码是0。
让我们看一个退出状态不为零的例子。如果我们用一个不存在的文件名调用ls命令,ls会打印一个错误并返回一个非零的退出状态。
result = subprocess.run(["ls", "non_existent_file"])
print("返回代码:", result.returncode)

这个非零的退出状态将存储在CompletedProcess实例的returncode属性中,我们可以在代码中访问这个值。我们可以看到命令失败了,存储的返回代码是2,这告诉我们发生了错误。我们可以在脚本中利用这些信息,在失败时执行不同的操作。
何时使用 run 函数
如果我们只想运行一个命令,并且只关心它是否成功,那么像这样使用run函数非常有用。命令的输出会直接打印到屏幕上,这意味着我们的脚本无法控制它。
这对于以下情况很方便:
- 没有有用输出的系统命令,如
cp、chmod、sleep等。 - 当我们不关心进一步处理该输出时。换句话说,当输出直接打印到屏幕上就足够了。
例如,如果我们正在编写一个脚本,用于更改目录树中一堆文件的权限,我们并不关心chmod命令的输出,我们只想知道它是否成功。
总结
本节课中,我们一起学习了如何使用Python的subprocess模块来运行系统命令。我们了解了如何执行简单的命令、传递参数,以及如何通过检查returncode属性来处理命令的成功与失败。我们还探讨了子进程的执行机制和父进程的阻塞状态。
然而,如果我们想要捕获外部命令的输出,然后对结果进行操作,就需要不同的策略。我们将在下一个视频中深入探讨这个问题。
124:获取系统命令的输出 📥

在本节课中,我们将学习如何在Python脚本中执行系统命令,并捕获其输出以便进一步处理。这对于需要从命令输出中提取信息并在脚本中使用的场景非常有用。
概述
上一节我们介绍了如何使用subprocess.run()函数执行系统命令。本节中,我们来看看如何捕获这些命令的输出,以便在Python脚本中进行处理和分析。
捕获命令输出
如果希望Python脚本能够处理所执行系统命令的输出,我们需要告诉run函数捕获该输出。当需要从命令中提取信息并在脚本中用于其他目的时,这可能会很有帮助。
例如,假设您想创建一些关于一天中哪些用户登录到服务器的统计信息。您可以使用一个调用who命令的脚本来实现,该命令会打印当前登录到计算机的用户。脚本可以解析命令的输出,每小时存储一次登录用户列表,并在一天结束时生成每日报告。
为了能够处理命令的输出,我们将在调用run函数时设置一个名为capture_output的参数,并将其值设为True。
示例:使用host命令
以下是使用host命令的示例,该命令可以将主机名转换为IP地址,反之亦然。调用时,我们将传递capture_output=True参数,并将结果存储在一个变量中以便访问。
import subprocess
result = subprocess.run(["host", "8.8.8.8"], capture_output=True)
我们知道result变量是一个可以访问的CompletedProcess实例。我们可以像之前一样检查returncode属性。

print(result.returncode)
我们还可以打印和操作命令生成的输出,该输出存储在stdout属性中。
print(result.stdout)
理解字节数组
输出字符串开头的b是什么?这个b告诉我们,这个字符串在Python中不是一个普通的字符串,它实际上是一个字节数组。

这是一个复杂的主题,请仔细听。计算机中的数据以字节形式存储和传输,每个字节最多可以表示256个字符。但世界上有成千上万种可能的字符,用于书写各种语言。例如,中文需要超过10000个不同的字符。
为了能够用这些语言书写,人们随着时间的推移创建了几种称为编码的规范,以指示哪些字节序列代表哪些字符。如今,大多数人使用UTF-8编码,它是Unicode标准的一部分,该标准列出了所有可以表示的字符。
回到我们的例子,当我们使用run执行命令时,Python不知道使用哪种编码来处理命令的输出,因此它只是将其表示为一串字节。
将字节解码为字符串
如果我们希望将其转换为正确的字符串,可以调用decode方法。此方法应用编码将字节转换为字符串。默认情况下,它使用UTF-8编码,这正是我们想要的。
综上所述,让我们将字节数组转换为字符串,然后将其拆分成几个部分。
output_string = result.stdout.decode()
print(output_string.split())
通过这种方式,我们可以操作所运行命令的输出,并对其进行任何需要的处理。例如,我们可以选择保留列表的最后一个元素,即对应我们查找的IP地址的名称。
print(output_string.split()[-1])
捕获标准错误输出
我们刚刚查看了捕获的标准输出。但标准错误呢?😊
如果我们使用capture_output参数,并且命令向标准错误写入任何输出,它将被存储在CompletedProcess实例的stderr属性中。
让我们看一个例子。我们将尝试执行用于删除文件的rm命令,并传递一个不存在的文件名。
result = subprocess.run(["rm", "does_not_exist.txt"], capture_output=True)

检查命令的返回码。
print(result.returncode)
它如我们预期的那样失败了。现在检查stdout和stderr属性的内容。
print(result.stdout)
print(result.stderr)
在这种情况下,标准输出为空,但有一个错误打印到了标准错误,我们可以通过stderr属性访问它。这是一个很好的例子,说明了标准输出和标准错误实际上是不同的流,因此Python会分别捕获它们。
总结
本节课中,我们一起学习了如何从Python执行系统命令并检查它们是否成功或失败。我们还学习了如何捕获它们的标准输出和标准错误流,以便在脚本中使用其内容。这些技能在编写使用系统命令执行某些复杂任务,并让我们的Python脚本覆盖更广泛任务的脚本时非常有用。
在下一个视频中,我们将通过了解调用外部命令时可以执行的一些更高级操作,来结束对subprocess模块的讨论。
125:高级子进程管理 🚀

在本节课中,我们将学习如何使用Python的subprocess模块进行更高级的系统命令管理。我们将探讨如何修改子进程的环境变量、使用run函数的其他参数,并了解直接调用系统命令的潜在风险与替代方案。
修改子进程环境变量 🌍
上一节我们介绍了如何运行系统命令并检查其输出。本节中,我们来看看如何通过修改环境变量来影响子进程的行为。
一种常见的方法是为子进程提供特定的环境变量。通过这种方式,我们可以改变进程查找可执行文件的位置、命令与系统交互的方式,以及生成的输出类型等。
修改子进程环境的通常策略是:首先复制当前进程的环境变量,进行必要的修改,然后将修改后的环境传递给子进程。
以下是具体步骤:
import os, subprocess
# 复制当前环境变量
my_env = os.environ.copy()
# 修改PATH变量,添加一个新目录
my_env["PATH"] = os.pathsep.join(["/opt/myapp", my_env["PATH"]])
# 使用修改后的环境运行命令
result = subprocess.run(["myapp"], env=my_env)

在这段代码中:
- 我们首先调用
os.environ.copy()来复制当前的环境变量字典,这样可以在不修改原始环境的情况下进行更改。 - 然后,我们修改
PATH变量,添加了/opt/myapp目录。PATH变量指示操作系统在哪些位置查找可执行程序。 - 我们使用
os.pathsep.join()方法将新目录与旧的PATH值连接起来,os.pathsep会根据当前操作系统提供正确的路径分隔符。 - 最后,我们调用
myapp命令,并通过env参数传入我们刚刚准备好的新环境。
总结来说,这个脚本通过添加一个目录来修改PATH环境变量的内容,然后使用这个修改后的变量运行myapp命令。这样,命令将在更新了PATH值的修改环境中运行。
run函数的其他选项 ⚙️
除了环境变量,subprocess.run()函数还提供了许多其他有用的选项。
以下是几个关键参数:
cwd参数:用于更改命令执行时的当前工作目录。当您需要在一组目录中的每一个上运行命令时,这非常有用。timeout参数:如果进程完成所需时间超过给定的秒数,此参数会导致run函数终止该进程。例如,当您运行的命令可能因尝试连接网络而卡住时,这很有用。shell参数:如果将其设置为True,Python将首先执行默认系统shell的一个实例,然后在其中运行给定的命令。这意味着我们的命令行可以包含变量扩展和其他shell操作。如果不设置此参数,这是不可能的。我们将在本课程后面学习更多关于shell的功能。目前请记住,如果您需要扩展变量或通配符,就需要设置此参数。但使用此功能可能存在安全风险,因此请确保您确实需要它,并在使用时小心谨慎。
使用系统命令的注意事项 ⚠️
在Python脚本中通过子进程和系统命令直接与底层系统交互可能很有用,尤其是在需要快速完成特定任务时,但这也会带来一些缺点。
使用这些系统级命令会在我们的脚本中构建关于自动化运行基础设施的假设。如果这些假设发生变化,就可能导致意外效果或故障。
这些假设可能以多种方式改变:
- 如果终端命令的标志发生变化,而我们的脚本继续使用旧的标志,我们的自动化会发生什么?
- 如果我们将操作系统从Linux切换到Windows,会发生什么?我们的脚本是会完全失败,还是会以意想不到的、可能有害的方式成功?
- 系统或我们脚本使用的外部命令的任何更改都会增加某些环节出问题的可能性。有时这种故障可能很明显,有时可能难以察觉。
如果我们正在自动化一个一次性的、定义明确的任务,而快速开发解决方案是最大的需求,那么使用系统命令和子进程会很有帮助。
但是,如果我们正在做更复杂或长期运行的事情,通常最好使用Python内置的或外部提供的模块。

因此,在决定使用子进程之前,最好检查标准库或PyPI存储库,看看是否可以使用原生Python完成任务,并检查是否已经有人创建了我们想要编写的自动化脚本。请记住,我们永远不想重新发明轮子。
总结与练习 📝
本节课中我们一起学习了subprocess模块的高级用法。我们探讨了如何通过修改环境变量来定制子进程的执行环境,了解了run函数的cwd、timeout和shell等参数,并讨论了直接调用系统命令的利弊。
这些关于高级子进程管理的信息量很大,可能需要一些时间才能完全消化。现在是一个好时机,使用您本地的Python安装尝试一些我们看到的函数和命令。
请查看下一份阅读材料中的速查表,它总结了如何使用subprocess模块。看看您是否能想出其他可以与系统命令一起完成的想法和事情,并尝试一下。当您准备好深入实践时,后面还有一个快速测验等着您。
126:什么是日志文件 📄


在本节课中,我们将学习日志文件的基本概念,了解它们如何记录系统事件,并探索如何使用Python工具处理这些文件以提取有用信息。
上一节我们介绍了如何与系统交互,包括读写文件、使用正则表达式和执行命令。本节中,我们来看看如何将这些技能应用于日常工作中的日志文件处理。
日志文件记录了系统中运行程序的各种事件,特别是那些未连接到终端的事件。这些文件包含大量有用信息,尤其在调试计算机上出现的复杂问题时非常关键。然而,日志文件通常包含大量行和内容,直接查找信息可能令人望而生畏。因此,学习如何处理这些文件并从中提取所需信息至关重要。
以下是日志文件的主要特点:
- 日志文件是文本文件,记录系统或应用程序事件。
- 它们常用于问题诊断和系统监控。
- 日志文件可能非常庞大,包含大量数据条目。
为了高效处理日志文件,我们将运用正则表达式的知识。在脚本中使用正则表达式为我们处理日志文件及其他文本数据源提供了极大的灵活性。通过编程,我们可以实现任何所需的行为,从而处理和操作文本数据,并获得我们需要的结果。



在接下来的视频中,我们将展示具体如何操作。
本节课中我们一起学习了日志文件的作用及其重要性。我们了解到日志文件是系统诊断的宝贵资源,但也因其数据量庞大而需要借助工具进行处理。通过结合Python脚本和正则表达式,我们可以灵活地从日志中提取关键信息,为自动化办公和系统维护提供强大支持。
127:使用正则表达式过滤日志文件 📝
在本节课中,我们将学习如何编写一个Python脚本,用于读取和分析日志文件。我们将重点介绍如何打开文件、逐行读取内容,以及如何使用正则表达式从特定格式的日志行中提取关键信息(例如,启动定时任务的用户名)。通过本教程,你将掌握处理文本日志文件的基本流程和技巧。

打开和读取日志文件
上一节我们介绍了课程目标,本节中我们来看看如何操作日志文件。
在脚本中处理日志文件时,第一步通常是打开文件,以便代码能够访问其内容。
我们讨论过多种操作文件的方法。通常的技术是调用 open 函数,该函数返回一个文件对象,然后使用 for 循环遍历其每一行。
例如,要打开一个作为脚本参数接收的文件,我们可以使用如下代码:
import sys
def main():
# 假设日志文件路径是第一个命令行参数
log_file_path = sys.argv[1]
with open(log_file_path, 'r') as file:
for line in file:
# 在这里处理每一行
process_line(line)
def process_line(line):
# 处理行的逻辑将在这里实现
pass
if __name__ == "__main__":
main()
出于性能考虑,当文件很大时,通常最好逐行读取,而不是将整个内容加载到内存中。
分析日志内容
上一节我们介绍了如何打开文件,本节中我们来看看如何分析其内容。
假设日志文件包含以下消息:
Jan 31 00:09:39 ubuntu.local ticky: INFO Created ticket [#4217] (mdouglas)
Jan 31 00:16:25 ubuntu.local ticky: INFO Closed ticket [#1754] (noel)
Jan 31 00:21:30 ubuntu.local ticky: ERROR The ticket was modified while updating (breee)
Jan 31 00:44:34 ubuntu.local ticky: ERROR Permission denied while closing ticket (ac)
Jan 31 01:00:50 ubuntu.local ticky: INFO Commented on ticket [#4709] (blossom)
Jan 31 01:29:16 ubuntu.local ticky: INFO Commented on ticket [#6518] (rr.robinson)
Jan 31 01:33:12 ubuntu.local cron: ERROR Failed to start session due to low disk space (user: sri)
Jan 31 01:33:18 ubuntu.local cron: ERROR Failed to start session due to low disk space (user: sri)
Jan 31 01:43:22 ubuntu.local ticky: ERROR Tried to add information to closed ticket (mcintosh)
生成此日志文件的服务器运行异常,我们怀疑是由系统管理员启动的某个Cron作业引起的。你可能记得,Cron作业用于在基于Unix的操作系统上调度脚本。
为了查明服务器发生了什么,我们需要审计日志文件,并准确查看是谁启动了Cron作业。
通过查看示例日志,我们可以看到最感兴趣的行是那些包含“cron”子字符串的行。这些行还显示了启动Cron作业的用户名,用户名被包裹在括号中。
有了这些信息,我们可以忽略任何不包含“cron”子字符串的行。我们可以使用 in 关键字来检查这一点。
以下是实现此过滤的步骤:
首先,我们使用 continue 关键字,它告诉我们的循环跳转到下一个元素。因此,如果该行不包含我们要查找的字符串,我们将跳过它并转到下一行。
def process_line(line):
if "cron" not in line:
return # 或者使用 continue,如果在一个循环中
# 继续处理包含 "cron" 的行
使用正则表达式提取用户名
上一节我们过滤出了相关日志行,本节中我们来看看如何从中提取具体的用户名。
一旦确定我们正在处理正确的日志行,就可以使用正则表达式的知识来提取用户名。
我们可以通过多种不同的方式实现。在本例中,我们将使用转义字符、捕获组和字符串结尾锚点。
在将表达式添加到脚本之前,我们先在解释器中构建并测试它。
让我们仔细看看这个表达式:
由于用户名位于日志行的末尾,我们使用美元符号锚点 $ 来仅匹配行尾的文本。为了找到用户名,我们查找单词“user”,后跟一个包裹在括号中的字符串,因为这些行就是这种结构。这意味着我们需要用反斜杠 \ 来转义这些括号。
因为我们想要提取实际的用户名,所以我们使用另一对括号来创建一个捕获组。
对于用户名本身,我们使用 \w+ 来匹配任何字母数字字符。
因此,完整的正则表达式模式是:user:\s*\((\w+)\)$
让我们用示例行测试一下:
import re
sample_line = "Jan 31 01:33:12 ubuntu.local cron: ERROR Failed to start session due to low disk space (user: sri)"
pattern = r"user:\s*\((\w+)\)$"
match = re.search(pattern, sample_line)
if match:
print(f"Found user: {match.group(1)}")
else:
print("No match found.")
看起来我们找到了一个“淘气”的用户。好消息是,我们的正则表达式运行正确。
整合脚本并运行
上一节我们成功构建了正则表达式,本节中我们将它整合到完整的脚本中并运行。
现在,我们可以在代码中使用这个表达式了。让我们将其添加到脚本中:
import sys
import re
def main():
log_file_path = sys.argv[1]
pattern = r"user:\s*\((\w+)\)$"
with open(log_file_path, 'r') as file:
for line in file:
line = line.strip()
# 1. 过滤出包含 "cron" 的行
if "cron" not in line:
continue
# 2. 使用正则表达式提取用户名
match = re.search(pattern, line)
if match:
username = match.group(1)
print(f"Found cron job started by user: {username}")
else:
# 这行包含cron但没有匹配用户模式,可能格式有误
print(f"Line contains 'cron' but no user found: {line}")
if __name__ == "__main__":
main()
我们的脚本应该能够处理之前显示的日志文件了。让我们保存它,使其可执行并运行它,传入我们展示的示例syslog文件。
chmod +x analyze_log.py
python3 analyze_log.py sample_syslog.log
我们的脚本进展顺利。我们已经定位了日志文件中启动Cron作业的每个用户,并将他们打印到屏幕上。

总结与回顾 🎯
本节课中我们一起学习了如何编写一个Python脚本来处理日志文件。我们涵盖了以下关键步骤:
- 打开和逐行读取文件:使用
open()函数和for循环高效处理大文件。 - 过滤相关行:使用
in关键字检查行中是否包含特定子字符串(如“cron”)。 - 应用正则表达式:构建并使用正则表达式模式(
r"user:\s*\((\w+)\)$")从格式化的字符串中精确提取信息(如用户名)。 - 整合与执行:将以上步骤组合成一个完整的、可执行的脚本。
我们采取了一些步骤来编写这个脚本。如果其中任何步骤不清楚,请回顾视频并自行练习,直到掌握为止。接下来,我们将对这些结果进行更多的处理。
128:理解数据 📊

概述
在本节课中,我们将学习如何通过Python脚本处理日志文件,并统计每个用户启动Chon作业的频率。我们将使用字典数据结构来存储和计数用户名出现的次数,从而更高效地分析数据。
回顾与目标
上一节中,我们编写了一个脚本,用于处理日志文件并提取启动Chon作业的用户名。虽然这很有帮助,但我们可能需要更多信息来改进输出。本节中,我们将学习如何统计每个用户名在日志中出现的次数。
使用字典计数
为了统计每个用户名出现的次数,我们可以使用字典数据结构。字典允许我们将用户名作为键,将出现次数作为值进行存储。以下是如何实现这一功能:
首先,我们创建一个空字典:
user_counts = {}
接下来,我们使用get方法来获取当前值,并更新字典:
username = "good_user"
user_counts[username] = user_counts.get(username, 0) + 1
这段代码的作用是:如果username已经在字典中,则获取其当前值并加1;如果不在字典中,则使用默认值0并加1。
整合到脚本中
现在,我们将上述逻辑整合到之前的脚本中。以下是需要修改的步骤:
- 在代码开头初始化一个空字典。
- 在处理文件时,检查正则表达式是否匹配成功。
- 如果匹配成功,将用户名作为键,更新字典中的值。
- 处理完文件后,打印最终的字典。
以下是修改后的代码示例:
import re
user_counts = {}
pattern = r"启动Chon作业的用户:(\w+)"
with open("logfile.txt", "r") as file:
for line in file:
result = re.search(pattern, line)
if result is None:
continue
username = result.group(1)
user_counts[username] = user_counts.get(username, 0) + 1
print(user_counts)
测试脚本
让我们用测试文件运行修改后的脚本。运行结果将显示每个用户名及其在日志中出现的次数。例如:
{'user1': 5, 'user2': 3, 'user3': 7}
这样,我们可以快速了解哪些用户在服务器上启动了Chon作业,以及它们的频率。
实际应用

通过这种方式,我们可以更深入地调查问题。例如,如果某个用户频繁启动作业,可能需要进一步检查其操作是否合理。这些数据处理技巧在实际工作中非常有用,尤其是在调试和分析日志时。
总结
本节课中,我们一起学习了如何使用字典统计日志中用户名的出现次数。通过整合正则表达式和字典,我们能够高效地提取和分析数据,从而更好地理解服务器上的作业情况。希望这些示例能帮助你掌握如何用Python快速获取所需信息,并在实际工作中应用这些技能。
接下来,我们将通过一个小测验来巩固本节课的知识。祝你学习愉快! 🎉
129:Python系统编程与数据处理 - 模块4总结 🎯

概述

在本节课中,我们将回顾模块4的核心内容,总结如何通过Python脚本管理数据和进程。我们将涵盖信息输入输出、系统命令执行以及日志文件处理等关键概念。
回顾模块4的核心内容
上一节我们介绍了Python脚本与操作系统交互的各种方式。本节中,我们来看看模块4涵盖的主要知识点。
我们学习了多种向脚本提供信息的方法。
以下是主要的信息输入方式:
- 从标准输入读取数据
- 使用环境变量传递配置
- 通过命令行参数接收指令
同时,我们也掌握了脚本如何向外部环境输出数据。
以下是主要的信息输出方式:
- 打印内容到标准输出
- 将错误信息输出到标准错误流
- 使用不同的退出值表示脚本执行状态
执行系统命令与处理日志
除了基本的输入输出,我们还探索了在Python中执行系统命令的方法。
我们使用 subprocess 模块来运行外部命令,其基本调用方式如下:
import subprocess
result = subprocess.run(["ls", "-l"])
最后,我们通过一个具体实例,学习了如何使用Python处理另一种重要的数据源——日志文件。这展示了如何将所学概念应用于实际的数据解析任务中。
知识应用与实践
目前这些概念可能显得有些抽象,因为我们讨论的主要是理论。但你应该能想到一些可以应用这些知识的实际例子。
将这些工具创造性地应用到日常活动中会非常有趣。接下来,你可以通过即将到来的实验课将所有知识付诸实践。在那里,你需要运用新掌握的系统编程技能来解决与日志文件相关的现实问题。
请记住,如果需要快速查阅某些内容,可以随时使用我们提供的速查表。你也可以根据需要多次回看视频。
总结
本节课中我们一起学习了Python系统编程的核心。我们回顾了脚本的多种数据交互方式、使用subprocess模块执行系统命令,以及处理日志文件的实际应用。请带着这些知识自信地迎接实践挑战,你完全可以做到。祝你好运!
130:Python测试入门 🧪


在本节课中,我们将要学习如何为Python代码编写自动化测试。我们将探讨测试的不同类型,了解它们如何使我们的代码更可靠,并学习如何处理和测试代码中的错误。
概述
欢迎回来,并衷心祝贺你坚持到这里。我们即将探讨的概念确实不简单。通过持续学习,你不仅扩展了编程视野,也证明了你有能力在IT领域取得成功。
在过去的几个模块中,我们学习了用Python可以做的所有事情,从管理文件到处理文本,再到启动系统进程等等。到目前为止,每当我们编写Python代码时,无论是在解释器中还是在脚本里,我们一直通过手动运行并观察其行为是否符合预期来进行测试。
做好准备,因为这种情况将在本模块中改变。我们将深入探讨如何创建自动化测试,让它们为我们执行这类检查。
为何需要自动化测试?
这使我们能够专注于编写代码,而不是检查我们对代码所做的任何更改是否会破坏原有的功能。它还将帮助我们验证我们添加的功能在各种可能的情况下都能按预期工作。
上一节我们介绍了自动化测试的必要性,本节中我们来看看我们将要学习的具体内容。
我们将了解现有的不同类型的测试,以及如何使用它们使我们的代码更可靠。最后,我们还将学习如何处理Python代码中的错误和异常:如何捕获这些错误以防止程序停止运行,如何在必要时引发错误,以及如何测试我们的代码是否生成了正确的错误类型。
这听起来很有趣,对吧?现在,让我们开始吧。
总结
本节课中我们一起学习了自动化测试的重要性。我们了解到,自动化测试可以帮助我们专注于开发,确保代码更改不会引入错误,并能验证功能在各种场景下的正确性。在接下来的课程中,我们将深入具体的测试方法和错误处理技术。
131:什么是软件测试?🧪


在本节课中,我们将学习软件测试的基本概念。我们将了解为什么测试对编写可靠代码至关重要,并初步探索测试的不同类型。
当我们编写一段非常简单的代码时,例如将两个变量相加,我们很容易理解代码的功能并确信它能正确执行。
随着操作变得更加复杂,例如使用了循环、条件判断,并调用了越来越多的函数,我们便更难完全确信代码会按预期执行。
这时,软件测试就派上用场了。软件测试是一个评估计算机代码的过程,目的是确定它是否能在测试时执行你期望它执行的操作。当你测试一个软件时,你希望发现其中的错误和缺陷,并找出问题所在。
软件测试在许多方面类似于新机器制造过程中进行的测试。


当一辆新车下线时,你需要确保踩下油门时车会前进,踩下刹车时车会停止。
软件测试的理念与此相同。你需要确保当你运行一个程序时,它的行为符合预期。这样,你才能真正“踩下油门”,放心使用。

脚本和程序可能会以各种奇怪的方式失败,尤其是当它们变得越来越复杂时。除了最简单的程序,几乎不可能测试所有可能出错的情况。
尽管这意味着你的脚本中可能存在一定数量的、你尚未意识到的错误,但别担心,编写测试可以帮助你消除大量错误,从而提高自动化的可靠性和质量。测试能让好代码变得出色。

软件测试的领域相当广泛。在接下来的几个视频中,我们将探讨一些基本概念,例如自动化测试、单元测试、集成测试和测试驱动开发。
与课程中涵盖的许多主题一样,我们将快速概述围绕测试的众多概念。这不足以让你成为测试专家,但应该能帮助你自动测试自己的脚本。
接下来,我们将讨论手动测试与自动化测试的区别。现在,让我们转换思路,开始学习。
本节课中,我们一起学习了软件测试的重要性及其基本目标。我们了解到,测试是验证代码行为是否符合预期的关键过程,它能帮助我们发现错误、提升代码质量。下一节,我们将深入探讨手动测试与自动化测试的具体区别。
132:手动测试与自动化测试 🧪

概述
在本节课中,我们将学习软件测试的基本概念,包括手动测试和自动化测试的区别与重要性。我们将了解为什么编写测试代码是开发过程中不可或缺的一环,并初步认识单元测试。
程序员在编写代码时,必须进行测试以确保其行为符合预期。
为我们的软件编写良好的测试,有助于在将脚本部署到实际自动化任务之前,发现错误和缺陷。
测试脚本最基本的方法是使用不同的参数运行它,并检查是否返回预期值。

在本课程中,我们已经为编写的一些代码进行过这种手动测试。
例如,使用不同的命令行参数执行脚本以观察其行为变化,就是手动测试的一个例子。
使用解释器在将代码放入脚本之前进行尝试,是手动测试的另一种形式。
正式的软件测试将这一过程更进一步,将测试本身编码成可以运行的软件和代码,以验证我们的程序是否按预期工作。
这被称为自动化测试。
自动化测试的目标是自动化检查返回值是否符合预期的过程。
与其让我们人类用不同的参数反复运行一个函数并检查结果是否符合预期,不如让计算机为我们完成这项工作。
自动化测试意味着我们将编写代码来执行测试。
你可能会问,为什么要编写更多的代码来测试已有的代码?因为当你测试代码时,你需要检查它是否能为许多不同的值执行预期的操作。
你需要验证它在许多可能的值(称为测试用例)下的行为是否符合你的预期。
假设你正在编写一个脚本,用于更新电子邮件地址列表以使用新域名,类似于我们之前编写的一个脚本。

你需要测试当电子邮件列表有一个元素、两个元素或十个元素时会发生什么。
你需要测试新域名长度为1个字符、20个字符甚至是空字符串时会发生什么。
你还需要测试列表仅包含需要更新的电子邮件、仅包含不需要更新的电子邮件或两者混合时会发生什么。
正如你所见,需要测试的事项列表会迅速变得非常庞大。
测试中包含的测试用例越多,代码的测试就越充分,你也就越能保证代码按预期执行。
如果我们手动进行测试,每当更改代码时,我们不太可能遍历所有情况。
我们可能只测试少数几种情况,这可能导致错误被遗漏,这并不理想。
这就是为什么我们不希望手动执行这些测试,而是希望让计算机为我们完成。
就像任何自动化示例一样,自动化测试的优势在于我们可以根据需要多次运行它们,并且总能获得相同的结果。
计算机会一遍又一遍地执行相同的检查,并始终确保返回值符合我们的预期。
当由于某种原因,结果不符合预期时,代码将引发错误,以便我们检查代码并找出问题所在。
我们可以编写多种不同类型的测试来执行自动化测试。
在接下来的几个视频中,我们将重点讨论一种称为单元测试的测试方法。
在介绍了单元测试之后,我们将讨论其他类型的测试及其各自的用途。
但在那之前,让我们确认一下学习进度。关于测试的讨论是否让你想快速做个小测验?
总结
本节课中,我们一起学习了软件测试的基础。我们明确了手动测试与自动化测试的区别,理解了自动化测试(特别是单元测试)在确保代码质量、提高效率和减少人为错误方面的重要性。下一节,我们将开始深入探讨单元测试的具体实现。
133:Python单元测试入门 🧪

在本节课中,我们将要学习什么是单元测试,以及为什么它在软件开发中如此重要。我们将通过一个简单的例子来理解单元测试的基本概念和编写方法。
什么是单元测试?
上一节我们介绍了自动测试的多种类型,本节中我们来看看其中最常用的一种:单元测试。
单元测试用于验证程序中小型、独立的部分是否正确。这类测试通常与代码一同编写,旨在测试如函数或方法等独立“单元”的行为。单元测试帮助开发者确保每一段代码都完成了其预期的功能。
单元测试的一个重要特性是隔离性。单元测试应仅测试其目标代码单元(即被测试的函数或方法)。这确保了测试的成功或失败完全由该单元的行为引起,而非由某些外部因素(如网络中断或数据库服务器无响应)导致。

换句话说,当测试一个函数或方法时,我们希望专注于检查该函数或方法中的代码行为是否正确,而不希望测试因外部原因而失败。
单元测试的核心原则
以下是编写单元测试时需要遵循的几个核心原则:
- 隔离性:测试应专注于单个代码单元,避免外部依赖。
- 不修改生产环境:测试绝不应修改用户交互的生产环境。在开发测试时,如果需要与其他软件交互,通常会在测试环境中进行,以便完全控制其行为。
- 验证输入与输出:单元测试的目标是验证程序的小型、独立部分是否正确。其核心模式可以归结为一个简单的问题:给定一个已知的输入,我们代码的输出是否符合我们的期望?
一个单元测试的实例
让我们通过一个具体的例子来理解如何实践单元测试。假设我们有一段代码,其功能是将“名, 姓”格式的名字重新排列为“姓, 名”格式。
我们将通过手动验证来开始测试:对于一个给定的输入,检查它是否产生预期的结果。
我们可以在Python解释器中导入并调用这个函数来进行检查。这里使用了一个新的关键字 from:
from rearrange import rearrange_name
在这个例子中,rearrange 是包含 rearrange_name 函数的模块名。通过这种方式导入,我们可以在调用函数时不必每次都写模块名。
print(rearrange_name("Lovelace, Ada"))
如果函数为我们提供的输入产生了预期的输出(即 "Ada Lovelace"),那么它就通过了这个特定的单元测试。

这个测试专注于代码中一个小型、独立的部分,并验证了我们对其工作方式的假设。由于测试范围被限制在一个特定的小单元内,这类测试通常运行得非常快,并且调试起来也很简单,因为导致失败的原因非常有限。
如何组织单元测试
为我们的代码创建单元测试,意味着需要编写一系列测试用例,来验证当我们输入某些参数时,能得到期望的输出。
当然,整个过程的要点在于自动运行这些测试,这样我们就不必每次都手动操作。在接下来的课程中,我们将讨论如何在Python中实际编写自动测试。
课程总结
本节课中我们一起学习了单元测试的基础知识。我们了解到单元测试是一种用于验证程序小型、独立部分正确性的自动测试方法,其核心在于隔离性和输入/输出验证。通过一个重排名字格式的简单例子,我们实践了手动测试一个函数的基本步骤,并理解了编写自动化测试用例的必要性。记住,好的单元测试是快速、独立且可重复的,它们是构建可靠软件的重要基石。
134:在Python中编写单元测试 🧪

概述
在本节课中,我们将学习如何在Python中编写自动化的单元测试。我们将了解单元测试的基本原理,并通过一个具体的例子来演示如何为Python函数创建和运行测试。
自动测试的原理
上一节我们介绍了自动测试的基本原理。我们知道,通过自动测试,我们可以根据需要多次运行测试,以确保代码按预期工作。
那么,在Python中我们如何实现这一点呢?我们需要编写一些代码来运行测试并验证输出。这样,我们就可以让计算机为我们完成工作。
为了演示测试工作流程,我们将为上一视频中的rearrange_name函数创建单元测试。
创建测试文件
正如之前提到的,自动测试通常与我们要测试的代码一起编写。在实践中,这意味着创建一个包含测试的单独的Python文件。
惯例是使用与要测试的模块相同的名称来命名脚本,并附加后缀_test。因此,对于我们的rearrange模块,我们将创建rearrange_test.py文件。
我们将测试rearrange模块的rearrange_name函数,所以让我们像之前在解释器中那样导入该函数。
使用unittest模块
现在,我们准备好开始编写测试了。为了帮助我们,Python提供了一个名为unittest的模块。这个模块包含许多类和方法,让我们可以轻松地为代码创建单元测试。
我们要做的第一件事是导入测试所需的unittest模块。unittest模块提供了一个TestCase类,其中包含许多可以直接使用的测试方法。
为了访问这些功能,我们创建自己的类,该类继承自TestCase,从而继承所有这些测试方法。
因此,我们将编写自己的TestRearrange类,该类继承自TestCase。你还记得语法是什么吗?我们需要将要继承的类包含在括号中。
我们称我们的测试类为TestRearrange,并指明它应该继承位于unittest模块中的TestCase类的功能。
我们在TestRearrange类中定义的任何以test前缀开头的方法将自动成为可以由测试框架运行的测试。
编写第一个测试用例
现在,我们准备好编写第一个测试用例了。它将是什么?在上一视频中,我们手动测试了一个简单的情况。让我们将那个手动测试转换为自动测试,以验证基本名称是否被正确格式化。
在这个我们称为test_basic的方法中,我们首先设置预期的输入和输出。然后,我们使用从继承的TestCase类提供的assertEqual方法来验证我们期望的结果是否与实际结果完全一致。
assertEqual方法基本上是说我的两个参数相等。如果该语句为真,则测试通过。如果为假,则测试失败,并在运行测试时将错误打印到屏幕上。
运行测试
好了,我们有了第一个单元测试,那么我们如何运行它呢?在程序的主要部分,我们将调用unittest.main()函数,它将为我们运行测试。
现在,我们准备好运行测试了。我们将通过执行刚刚创建的文件来实现这一点。
让我们使脚本可执行,然后运行它。

输出非常详细,打印了一些关于一组测试或测试套件运行时间的信息,以及测试数量和它们是否通过的信息。
就这样,我们测试了第一个函数。这很酷,对吧?我知道这里有很多内容。如果代码令人困惑、复杂或还没有真正理解,那没关系。花时间自己练习并复习内容,直到感觉自然为止。
接下来,我们将测试更多的情况。
总结
在本节课中,我们一起学习了如何在Python中编写和运行单元测试。我们了解了自动测试的基本原理,创建了测试文件,使用了unittest模块,编写了第一个测试用例,并成功运行了测试。通过自动测试,我们可以确保代码按预期工作,提高代码的可靠性和可维护性。
135:Python自动化测试与边缘案例处理 🧪

概述
在本节课中,我们将学习如何为Python代码编写自动测试,并重点关注如何处理“边缘案例”。边缘案例是指那些在正常操作中可能不会遇到,但会导致程序行为异常的输入。通过编写针对这些情况的测试,我们可以确保代码在各种情况下都能正确运行。
编写自动测试
上一节我们介绍了自动测试的基本概念。本节中,我们来看看如何为一个具体的函数编写测试。
我们有一个测试套件,但目前只包含一个测试用例。我们需要扩展它。选择测试用例可以锻炼创造力,思考代码可能以哪些不同方式出错,这实际上非常有趣。
我们通常会测试代码在一般情况下的工作状态。😊
但我们也应该看看,当给它一些在正常操作中可能不会遇到的输入时,会发生什么。
例如,如果给我们的函数一个空字符串,会发生什么?
让我们为此添加一个测试并看看结果。在这个案例中,我们测试的是空输入字符串。
我们期望函数在接收到空字符串时返回一个空字符串。

我们使用 assertEqual 函数来检查这个行为。
def test_empty(self):
self.assertEqual(rearrange_name(""), "")
好的,让我们运行这个测试。
发现边缘案例
运行测试后,我们的测试失败了,代码中存在问题。
让我们仔细看看失败提供的信息。毕竟,错误信息就是为此而存在的,对吧?
这个错误告诉我们名为 test_empty 的测试失败了,我们看到它失败的原因是 TypeError,提示 None 是不可下标的。

有趣,我们刚刚发现了一个边缘案例。
边缘案例是指那些能产生意外结果的输入,它们位于我们想象程序通常能处理的输入范围的极端末端。
处理边缘案例
边缘案例通常需要特殊处理和脚本修改,以使代码继续正确运行。
在我们的字符串重排示例中,我们可以通过在操作 result 变量之前执行一个简单的检查来处理这个边缘案例。
def rearrange_name(name):
result = some_operation(name)
if result is None or result == "":
return name
# ... 其余处理逻辑
😊,经过这个修改,如果我们使用正常输入调用函数,仍然会得到之前的结果。如果我们尝试使用空字符串,我们会在检查中捕获它,并返回原始的空字符串。
是否处理这类错误取决于我们希望脚本如何表现。
在我们的具体案例中,当无法重排时,返回原始值是有意义的。
但有时,你可能更希望程序因错误而崩溃,而不是像什么都没发生一样继续运行。
请记住,自动化任务静默失败是不好的。
其他类型的边缘案例通常包括:向期望数字的函数传递零、负数或极大的数字。
在编写测试时考虑这些情况是很好的,因为它们可能导致代码崩溃或以意外方式运行。
有时,做个悲观主义者是有好处的。你可以看到,想出这些例子可能需要一些创造力。
好处是,在编写自动测试时,一旦你想出了一个例子,它就会一直存在。
验证修复
现在我们已经修复了代码,使其能正确处理这个边缘案例,让我们再次运行测试套件,看看问题是否已解决。
是的,我们的测试通过了。我们修复了代码中的一个错误。通过添加自动测试,我们可以确保它不会再发生。

你能想到我们可能想添加到测试套件中的其他测试用例吗?我们将在下一个视频中探讨更多案例。😊
总结
本节课中,我们一起学习了如何为Python代码扩展自动测试套件,特别是如何识别和处理边缘案例。我们了解到,边缘案例是位于预期输入范围极端的输入,可能导致意外行为。通过编写针对这些特殊情况的测试,并在代码中添加适当的检查,我们可以使程序更加健壮和可靠。记住,良好的测试习惯是确保自动化脚本长期稳定运行的关键。
136:其他测试案例 🧪

概述
在本节课中,我们将学习如何为Python函数设计更多测试案例,以发现并修复潜在的错误。我们将通过实际例子,演示如何逐步完善测试套件,确保代码在各种情况下都能正确运行。
回顾与引入
上一节我们介绍了如何为函数添加基础案例和边界案例。本节中,我们来看看如何通过更多测试案例进一步验证代码的健壮性。
目前,我们的测试套件已包含一个基础案例和一个边界案例。添加边界案例时,由于函数未正确处理该情况,导致错误产生。我们随后修复了函数。现在,你能想到其他可能导致函数行为异常的例子吗?
添加更多测试案例
记得最初编写函数时,我们遇到了包含空格或点的姓名,这会导致正则表达式无法匹配。虽然我们已经修复了这个问题,但添加测试案例来确保代码按预期工作仍然是个好主意。
以下是测试案例:验证包含多个名字的人名是否仍能被正确重排。
运行测试套件,检查是否通过。
现在我们有了三个测试,且全部通过。为了发现更多错误,我们需要发挥创造力,思考其他可能导致代码失败的例子。
处理单名情况
考虑只有单个名字的情况。此时,字符串中没有逗号。我们期望函数返回与输入相同的名字。这会正常工作吗?
检查并找出答案。糟糕,这个测试失败了,对Voltaire来说是个坏消息。
这次的测试输出与之前略有不同。它显示了失败的测试名称,即“test_one_name”。但现在,我们看到的不是类型错误,而是断言错误,这意味着原始值与期望值不匹配。
看起来我们的函数返回了一个空字符串,而不是原始名字。这是因为代码中存在一个错误。
修复错误
当代码中出现错误时,我们该怎么办?我们修复它。
当我们检查结果是否为None时,我们返回了一个空字符串,这使得之前的测试通过。现在的情况是,我们传入了一个不包含逗号的名字,这导致result变量为None,因此函数返回了空字符串。
修复方法很简单。当result为None时,我们不返回空字符串,而是返回原始的name变量。这样应该就足够了吧?
保存更改,再次运行测试套件。

验证修复
太好了,我们修复了所有错误,所有测试都通过了。
在套件中运行测试的一个巨大好处是,我们现在知道所有编写的测试案例都得到了正确处理。我们的代码适用于基础名字、空字符串、双名和单名。
如果发现另一个导致测试失败的情况,我们可以将其添加到套件中,修复错误,然后再次运行整个套件,确保所有其他案例仍然正常工作。
总结
本节课中,我们一起学习了如何通过设计多样化的测试案例来完善Python函数的测试套件。我们探讨了如何处理单名情况,并修复了由此发现的错误。通过不断添加和运行测试,我们可以确保代码在各种边缘情况下都能可靠运行。
后续内容
接下来,我们将提供一份小抄,包含编写单元测试的所有语法,以及更多可能有用的信息指针。之后,你将有机会自己编写一些有趣的测试。
137:软件测试基础 - 黑盒测试与白盒测试 🧪


在本节课中,我们将要学习软件测试中的两个核心概念:黑盒测试与白盒测试。我们将了解它们的定义、区别、各自的优缺点以及在实际场景中的应用方式。
为了确保软件的行为符合预期,我们可以使用多种不同的测试方法。我们已经详细探讨了单元测试,这是一种编写简单且能有效发现缺陷的强大方法。但软件测试的范畴远不止于此。一个有趣的概念是区分我们的测试属于白盒测试还是黑盒测试。


白盒测试,有时也被称为透明盒测试或玻璃盒测试,依赖于测试创建者对被测软件内部结构的了解来构建测试用例。



在进行白盒测试时,测试创建者知晓代码的工作原理,并可以利用这种理解来编写测试用例,以确保所有功能都按预期执行。

另一方面,在黑盒测试中,被测软件被当作一个不透明的黑盒来对待。

换句话说,测试者不了解软件内部的工作机制。黑盒测试是基于程序应该做什么(即其需求或规格说明)来编写的,而不是基于它如何实现这些功能。

例如,一个简单的黑盒测试可以是验证当你在浏览器中输入 www.google.de 时,返回的是谷歌的德国搜索页面。你可能不知道谷歌服务器如何处理你的请求,但你知道最终结果应该是什么。
白盒测试和黑盒测试各有其优势。白盒测试很有帮助,因为测试编写者可以利用对源代码的了解,创建覆盖程序大多数行为方式的测试。黑盒测试则很有用,因为它们不依赖于对系统工作原理的了解。这意味着它们的测试用例不太可能受到代码本身的偏见影响,通常能覆盖到原始脚本编写者未预料到的情况。
并非我们编写的所有测试都必须严格归入某一类别。我们可以编写属于白盒或黑盒的单元测试,这取决于所选择的测试方法。
以下是两种单元测试的区分方式:
- 黑盒单元测试:如果在编写任何代码之前,仅根据代码应该实现的功能规格说明来创建单元测试,那么这些测试可以被视为黑盒单元测试。
- 白盒单元测试:如果单元测试是在代码开发过程中或之后编写的,并且测试用例的创建基于对软件工作原理的了解,那么它们就是白盒测试。
没有一种方法绝对优于另一种,因为每种方法都为你提供了不同的途径来使代码更可靠。并非所有事物都如此非黑即白,或者用编程世界的话说,并非都是二元的。
作为一名IT专家,你可能需要测试他人运行的软件是否符合你的预期。为此,你可以结合使用黑盒测试和白盒测试。
假设你有一个公司销售产品的在线目录。你可以设计一个黑盒测试,验证当你打开某个特定产品的页面时,该产品的详细信息会正确显示。除此之外,你还可以设计一个白盒测试,直接调用该页面使用的不同函数,检查价格是否以正确的货币显示、描述文本是否正确换行等等。
本节课中我们一起学习了黑盒测试与白盒测试的核心概念。我们明确了白盒测试基于对代码内部结构的了解,而黑盒测试则只关注输入与输出是否符合规格。两者在确保软件质量方面扮演着互补的角色,结合使用能更全面地验证系统的可靠性。
138:其他测试类型 🧪


概述

在本节课中,我们将要学习单元测试之外的几种常见软件测试类型。我们将探讨集成测试、回归测试、冒烟测试和负载测试,了解它们各自的目的、应用场景以及如何帮助我们构建更健壮的自动化脚本和系统。
上一节我们介绍了单元测试,它专注于验证单个函数或方法的预期功能。本节中我们来看看其他几种重要的测试类型,它们从不同层面确保软件质量。

集成测试 🔗
集成测试用于验证不同代码模块之间,以及代码与集成环境(如数据库、API)的交互是否按预期工作。
与单元测试不应跨越边界(如发起网络请求)不同,集成测试的目标正是验证这类交互,并确保整个系统协同工作。
集成测试通常将单元测试验证过的独立代码模块组合成组进行测试。根据程序功能及其与相关系统的交互方式,我们可能需要为测试创建一个独立的测试环境,运行待验证软件的测试版本。
如果代码不会对生产环境做出任何更改,我们也可以针对正在运行的系统实际版本运行测试。但通常,为集成测试搭建一个可控的测试环境是更安全的做法。
当公司部署一个较为复杂的系统时,进行集成测试有助于确保所有部分都能按预期组合在一起。
以下是集成测试的一些关键点:
- 设置集成测试通常需要更多工作,因为需要确保拥有所有相关系统的测试版本。
- 集成测试有助于发现单元测试无法检测到的问题,因此额外的努力是值得的。
- 例如,如果要测试的服务与数据库交互,就应该设置一个单独的测试数据库,包含测试用户和测试表。这允许我们在一个可控的环境中运行所有需要的测试,而不会冒险修改生产数据库。
回归测试 🔄
回归测试是单元测试的一种变体,通常作为调试和故障排除过程的一部分编写,用于在问题被识别后验证其是否已被修复。
假设我们的脚本存在一个错误,我们正在尝试修复它。一个好的方法是:首先编写一个通过触发错误行为而失败的测试,然后修复错误,使测试通过。


回归测试是测试套件中有用的一部分,因为它们确保相同的错误不会发生两次。同一个错误不能被重新引入代码中,因为引入它会导致回归测试失败。
冒烟测试 💨
冒烟测试,有时称为构建验证测试,其名称来源于硬件设备测试中的一个概念:接通给定的硬件设备,看看是否有烟冒出来。

在编写软件时,冒烟测试作为一种健全性检查,用于发现程序中的重大错误。

冒烟测试回答一些基本问题,例如:“程序能运行吗?”这类测试通常在更精细的测试之前进行,因为如果软件连冒烟测试都失败了,基本可以确定其他测试也不会通过。正如俗话所说:“无风不起浪”。
以下是冒烟测试的应用示例:
- 对于Web服务,冒烟测试是检查相应端口上是否有服务在运行。
- 对于自动化脚本,冒烟测试是使用一些基本输入手动运行它,并检查脚本是否成功完成。
负载测试 ⚖️
另一种测试类型是负载测试。这些测试验证系统在承受显著负载时的行为表现。要实际执行这些测试,我们需要为应用程序生成流量,模拟服务的典型使用情况。

在部署新版本的应用程序时,负载测试非常有助于验证性能是否没有下降。
例如,我们可能希望在网页每秒收到100个、1000个甚至10,000个请求时,测量网站的响应时间。具体的数字取决于我们对网站将接收多少流量的预期。
测试套件 📚
综合来看,一组一种或多种类型的测试通常被称为测试套件。多样化的测试类型可以创建一个更健壮的测试套件,有助于确保你的脚本和自动化程序按你的指令执行。
总结
本节课中我们一起学习了除单元测试外的几种重要测试类型:集成测试验证模块间交互,回归测试防止已修复错误复发,冒烟测试进行快速健康检查,而负载测试评估系统在高压力下的性能。将这些测试组合成测试套件,能全方位保障代码质量。软件测试领域还有许多其他类型的测试,我们只触及了最常见的几种。如果你有兴趣了解更多关于软件可能出错的方式以及如何测试,有很多相关的书籍和文章可供参考。
说到测试,我们即将面临一个巨大而困难的测试……开个玩笑。接下来,我们将学习一种称为“测试驱动开发”的技术。
139:测试驱动开发 (TDD) 🧪

概述
在本节课中,我们将要学习一种名为“测试驱动开发”的编程方法。这种方法强调在编写实际功能代码之前,先编写测试代码。我们将了解其基本流程、优势以及它如何帮助我们编写出更健壮、更可靠的程序。
你可能会认为,大多数测试发生在代码编写完成之后。这似乎是一个自然的流程:首先编写脚本,然后编写测试来验证脚本是否按预期工作。
但这并不总是最佳方法。一个称为“测试驱动开发”的过程,要求在编写代码之前先创建测试。这听起来可能有点违反直觉,但它能促使我们编写出更周密、更完善的程序。
当遇到一个可以通过自动化解决的新问题时,你的本能反应可能是打开代码编辑器并开始编写。然而,先创建一些测试,可以确保你已经深入思考了要解决的问题,以及可能用来解决它的不同方法。
先编写测试还有助于你思考程序可能失败和崩溃的方式,这可以带来一些有价值的见解,甚至可能促使你采用更好的方法。
测试驱动开发循环 🔄
上一节我们介绍了测试驱动开发的基本理念,本节中我们来看看它的具体实施循环。

测试驱动开发循环通常包括以下步骤:
以下是TDD循环的核心步骤:
- 编写测试:首先为一个新功能编写一个测试,并运行它以确认它会失败(因为功能尚未实现)。
- 运行测试(确认失败):验证测试确实失败了。这是关键一步,确保测试是有效的。
- 编写代码:编写最少量的、能使该测试通过的代码。
- 再次运行测试:运行测试。如果通过,则进入下一个功能;如果失败,则调试代码并重复此步骤。

这个循环会为脚本的每个新功能重复进行,直到整个程序完成并运行。
因此,在编写下一个Python程序之前,你可能需要思考可以创建哪些测试来确保它按预期工作。
延伸学习与总结 📚
上一节我们介绍了TDD的具体操作循环,本节中我们来看看它的更广泛应用和本课程的总结。
如果你想了解更多关于如何使用测试驱动开发方法创建代码的信息,外面有各种各样的资源。其中很多都以Python为中心,但其原理可以应用于你需要使用的任何语言。
希望你已经看到了编写测试来验证代码的好处,并对不同的可用测试技术有了一些了解。请记住,好的测试有助于使你编写的任何自动化和脚本更加健壮、更具弹性且错误更少。拥有可靠的自动化会让每个人的工作更轻松。
许多公司将测试更进一步,将其与版本控制系统和开发流程相结合。当工程师提交代码时,代码会被集成到主代码库中,并通过一个称为“持续集成”的过程自动运行测试以发现错误。虽然很有用,但建立持续集成流程可能是一项艰巨的任务。我们将在后续课程中更多地讨论它。
同时,如果你使用单元测试来验证你编写的代码,那么你已经走在通往更可靠、更健壮的自动化道路上了。
本节课总结
本节课中我们一起学习了测试驱动开发。我们了解到TDD是一种先写测试、后写代码的开发模式,其核心循环是“红-绿-重构”(即:写失败测试->写代码使测试通过->优化代码)。这种方法能促使我们更深入地思考问题设计,提前发现潜在缺陷,从而编写出质量更高的程序。记住,可靠的测试是构建健壮自动化系统的基石。
140:Python中的try-except结构 🛡️

在本节课中,我们将要学习Python中的try-except结构。这是一种强大的错误处理机制,它允许我们的程序在遇到错误时不会立即崩溃,而是能够优雅地处理这些异常情况,并继续执行后续的代码。
概述
在我们学习Python的旅程中,已经多次遇到过解释器生成的错误。我们见过TypeError、IndexError、ValueError等错误类型。到目前为止,每当解释器抛出这些错误时,我们通常的做法是修改代码来避免错误。这是一种常见的方法,因为一旦解释器引发错误,程序就会停止运行。而我们不希望脚本在完成其工作之前就结束。
有时,我们可以通过条件判断来轻松地进行验证以避免错误。例如,在我们之前重排姓名函数的例子中,我们检查正则表达式搜索的结果是否为None,并在该情况下执行不同的操作。
然而,在其他时候,可能出错的情况太多,以至于检查所有情况变得非常具有挑战性。例如,假设你有一个函数,它打开一个文件并对其进行一些处理。如果文件不存在怎么办?如果用户没有读取文件的权限怎么办?或者如果文件被另一个进程锁定而无法立即打开怎么办?我们可以检查所有这些条件,但如果还有另一个原因导致open函数引发错误呢?在这种情况下,更好的方法是使用try-except结构。
try-except结构的工作原理
让我们通过一个例子来看看它是如何工作的。下面的character_frequency函数读取文件内容,以计算其中每个字符的出现频率。为此,第一步是打开文件。
def character_frequency(filename):
try:
f = open(filename)
except OSError:
return None
# ... 后续处理文件的代码
在这个例子中,我们把调用open函数的语句放在了一个try-except代码块中。它的工作原理是:首先,尝试执行我们想要的操作,即打开文件。如果出现错误,程序就会进入与该错误匹配的except部分,并执行任何必要的清理操作。这里我们只有一个针对OSError错误类型的except块,但如果被调用的函数可能引发其他类型的错误,也可以有更多的except块。
因此,在编写try-except块时,需要记住的重要一点是:只有当try块中的某条指令引发了匹配类型的错误时,except块中的代码才会被执行。
错误处理策略


在这个例子中,在except块中,我们返回None,以向调用代码表明该函数无法完成请求的任务。当某些操作失败时返回None是一种常见的模式,但并非唯一的方法。
我们也可以决定将变量设置为某个基础值,例如数字设为0,字符串设为空字符串"",列表设为空列表[]等等。这完全取决于我们的函数做什么,以及我们需要什么来完成这项工作。
关键点是,当我们有一个可能引发错误的操作时,我们希望使用try-except块来优雅地处理这种失败。这个操作可能是打开文件、将值转换为不同的格式、执行系统命令、通过网络发送数据,或者是任何其他可能失败且不易用条件判断来检查的操作。
使用try-except的注意事项
要使用try-except块,我们需要了解我们调用的函数可能引发哪些错误。这些信息通常是函数文档的一部分。一旦我们知道了这些,我们就可以把可能引发错误的操作作为try块的一部分,而把错误引发时要采取的行动作为相应except块的一部分。
你可能会问自己:我如何引发自己的错误呢?幸运的是,这正是我们接下来要学习的内容。我们将深入探讨如何在必要时引发我们自己的错误。
总结
本节课中,我们一起学习了Python中的try-except结构。我们了解到,这是一种处理程序运行时可能发生的异常情况的强大工具。通过将可能出错的代码放在try块中,并在except块中定义错误发生时的处理逻辑,我们可以使程序更加健壮,避免因未处理的错误而意外终止。我们还讨论了不同的错误处理策略,例如返回None或默认值。最后,我们提到了了解函数可能引发的错误类型对于正确使用try-except结构至关重要。在下一课中,我们将学习如何主动引发自定义的错误。
141:引发错误 🚨

在本节课中,我们将学习如何在Python中主动引发错误。我们将探讨为什么需要这样做,以及如何使用raise和assert关键字来确保代码的健壮性。
概述
在上一节视频中,我们学习了如何处理由被调用函数引发的错误。本节中,我们将探讨在何种情况下需要我们自己主动引发错误,以及如何实现。
为何需要主动引发错误?
当函数执行所需的条件未满足,且返回None或其他基础值不足以表达问题时,我们可能需要主动引发错误。
让我们通过一个例子来理解这一点。
示例:验证用户名
假设我们有一个函数,用于验证所选用户名是否有效。该函数的一个检查是确保提供的用户名长度至少达到某个最小值,该最小值通过参数接收。
以下是该函数的初始代码:
def validate_user(username, min_len):
if len(username) < min_len:
return False
if not username.isalnum():
return False
return True
只要提供的值是合理的,这段代码就能正常工作。
参数检查的必要性
如果min_len变量是0或负数,会发生什么?我们的函数将允许空用户名通过验证,这显然不合理。
为了防止这种情况,我们可以在函数中添加额外的检查,以确保接收到的参数是合理的。
在这种情况下,返回False会产生误导,因为问题可能不是用户名无效,而是提供的min_len值不合理。
因此,我们添加一个检查,确保min_len至少为1,否则引发错误。
使用raise关键字引发错误
在Python中,引发错误的关键字是raise。我们可以引发Python内置的各种错误,如果标准错误类型不够用,也可以创建自定义错误。
在本例中,我们引发一个ValueError,这是一种我们之前遇到过的错误类型,用于指示参数值存在问题。
更新后的代码如下:
def validate_user(username, min_len):
if min_len < 1:
raise ValueError("min_len must be at least 1")
if len(username) < min_len:
return False
if not username.isalnum():
return False
return True
让我们在解释器中测试这段代码。
>>> validate_user("user", 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in validate_user
ValueError: min_len must be at least 1
成功!我们的函数按预期引发了错误。
测试有效参数
现在,让我们用有效参数调用函数,看看是否正常工作。
>>> validate_user("user", 3)
True
>>> validate_user("u", 3)
False
一切正常。
处理非字符串参数
如果我们传递的不是字符串作为用户名,会发生什么?让我们尝试几个例子。
首先,尝试传递一个数字:
>>> validate_user(123, 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in validate_user
TypeError: object of type 'int' has no len()
Python解释器引发了错误,因为我们的代码尝试使用len()函数,而整数没有长度属性。
接下来,尝试传递一个列表(列表有长度属性):
>>> validate_user([], 1)
False
>>> validate_user(["item"], 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in validate_user
AttributeError: 'list' object has no attribute 'isalnum'
我们得到了不同的错误,因为列表没有isalnum方法。
使用assert进行断言检查
assert关键字用于验证条件表达式是否为真。如果为假,它将引发一个带有指定消息的AssertionError。
我们可以在函数中添加断言,以确保接收到的参数类型正确。
更新后的代码如下:

def validate_user(username, min_len):
assert type(username) == str, "username must be a string"
if min_len < 1:
raise ValueError("min_len must be at least 1")
if len(username) < min_len:
return False
if not username.isalnum():
return False
return True
现在,如果函数被调用时username参数不是字符串,将引发一个带有我们提供消息的错误。
让我们测试一下:
>>> validate_user([], 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in validate_user
AssertionError: username must be a string
我们的函数现在会在第一个参数不是字符串时引发AssertionError。
raise与assert的使用场景
通常,我们不需要检查参数的类型。根据函数的功能,允许使用不同类型的参数调用函数可能是完全可以接受的。
断言在调试代码时非常有用,我们可以将其添加到任何我们希望确保变量包含应有值和类型的地方,或者当我们认为不应该发生的事情正在发生时。
但请注意,如果我们要求解释器优化代码以运行更快,断言将从代码中移除。
因此,作为一般规则:
- 使用
raise来检查在代码正常执行期间预期会发生的情况。 - 使用
assert来验证不应发生但可能导致代码行为异常的情况。
总结
在本节课中,我们一起学习了如何在Python中主动引发错误。我们探讨了使用raise关键字来引发内置或自定义错误,以及使用assert关键字进行断言检查。我们还讨论了这两种方法的使用场景和区别。
通过掌握这些技能,我们可以编写更健壮、更可靠的代码,确保在异常情况下能够给出清晰的错误提示。
接下来,我们将学习如何添加测试,以验证我们的函数是否按需引发错误。
142:测试预期错误 🧪

在本节课中,我们将学习如何为函数编写单元测试,特别是如何测试那些在特定情况下预期会引发错误的代码。我们将使用Python的unittest模块中的assertRaises方法来实现这一目标。
在之前的视频中,我们探讨了如何为函数创建单元测试,涵盖了基本情况和边界情况。
我们强调应尝试覆盖多种不同的可能情况,以确保函数在所有情况下都能正确运行。
对于某些边界情况,例如我们之前示例中minlen参数为负值的情况,预期函数会引发一个错误,我们也需要能够测试这种情况。
那么,我们该如何做呢?答案是使用unittest模块提供的assertRaises方法。
让我们通过为validate_user函数的测试套件添加几个测试用例来具体看看。
以下是现有的测试套件。可以看到,我们已经有一些测试用例,用于检查函数在接收有效参数时是否正常工作。
现在,我们想添加一些其他用例,用于测试函数接收无意义参数(如minlen为负值,或username是列表而非字符串)时的情况。现在就开始吧。
我们可以看到,assertRaises方法的工作方式与我们之前使用的assertEqual方法略有不同。
在这种情况下,我们需要首先传入我们预期函数会引发的错误类型,然后是函数名,以及需要传递给该函数的任何参数。
在幕后,此方法使用try-except块调用我们想要测试的函数,并检查它是否确实引发了我们所声明的错误。
好的,让我们运行这个测试套件,验证我们的代码是否正确工作。
所有测试都通过了。现在,你已经知道如何测试代码以验证其行为是否符合预期,以及如何测试它在预期情况下是否会引发正确的错误。

课程提供了一个速查表,涵盖了我们在这些视频中看到的所有错误处理语法,随后是另一个让你测试技能的机会。
总结
本节课中,我们一起学习了如何使用unittest模块中的assertRaises方法来测试函数在特定输入下是否会按预期引发错误。这是编写健壮单元测试、确保代码在边界和无效情况下也能妥善处理的重要部分。
143:Python中的测试 - 模块5总结 🎯

在本节课中,我们将一起回顾并总结Python测试模块的核心内容。我们将涵盖测试的基本概念、不同类型以及如何在Python中编写单元测试。通过本教程,你将理解自动化测试如何帮助保持代码质量,并为实际编程任务做好准备。

模块回顾与成就 🏆
恭喜你完成了本模块的学习。现在,请花一点时间回顾你在整个课程中学到的知识和完成的成就。
这并非易事。你在本地环境中设置了Python,并学会了如何管理文件、处理文本、启动系统进程、使用正则表达式以及处理日志文件。
测试方法与错误处理概述 🔍
在过去的几个视频中,我们详细介绍了在Python中可以使用的不同测试方法和错误处理策略。
我们学习了不同类型的测试,以及如何在Python中编写自己的单元测试。
自动化测试的重要性 ⚙️
现在,你可能已经开始认识到自动化测试在保持代码无错误和准备就绪方面的重要作用。
自动化测试可以显著减少代码中的错误,确保代码质量,为后续开发和使用奠定坚实基础。
分级评估与实践机会 📝
在本模块的分级评估中,你将再次有机会通过一个真实场景来练习你的技能。在这个场景中,你需要解决一些存在错误的代码问题。
但请放心,你已经掌握了必要的知识和技能。如果遇到任何困难,可以随时回顾视频内容,并通过不断练习来巩固所学。
总结与展望 🌟
本节课中,我们一起学习了Python测试模块的核心内容,包括测试的基本概念、不同类型以及如何编写单元测试。通过不断练习和实践,你将能够更好地应用这些知识解决实际问题。
期待在接下来的学习中与你再次相见。😊
144:Bash脚本编程介绍 🐚


在本节课中,我们将要学习Bash脚本编程的基础知识。Bash是Linux和Unix系统中常用的命令行解释器,也是一种强大的脚本语言。通过学习Bash,你将能够更高效地自动化系统管理任务,并与Python脚本形成互补。
概述
上一节我们介绍了Python在IT自动化中的应用。本节中,我们来看看另一种强大的工具——Bash脚本。Bash脚本特别适合处理文件操作、系统命令组合等简单任务,能够以更简洁的方式完成特定工作。
为什么学习Bash?
你可能会疑惑,为什么在刚刚熟悉Python后要学习一门新的编程语言。掌握Bash脚本编写能力,可以成为Python脚本的有力补充。例如,假设你需要将一个目录中的所有PNG格式图片转换为JPEG格式。
虽然可以使用Python的os.listdir()和subprocess.run()来实现,但代码会变得复杂。而在Bash中,只需几行代码即可完成,使脚本更易读、更易维护。
在工作中,我经常需要编写Bash脚本。当自动化任务仅需少量代码,且使用Python不会带来额外价值时,我通常会选择Bash。例如,最近我编写了一个简短的Bash脚本,用于逐个挂载多个磁盘并压缩归档其中的数据。
Bash与Python的对比
在接下来的几个视频中,我们将学习Bash中基本操作的语法,如条件判断和循环。你会发现其语法与Python有相似之处,但并非完全相同。不过,由于你已经掌握了Python编程,理解Bash将变得更加容易。
以下是Bash中一个简单条件判断的示例:
if [ -f "$file" ]; then
echo "文件存在。"
else
echo "文件不存在。"
fi
学习目标
在本模块结束时,你应该能够:
- 更自如地使用Linux上的各种系统命令。
- 使用Bash创建自己的脚本。
- 根据任务需求,明智地选择使用Python还是Bash。
总结
本节课中我们一起学习了Bash脚本编程的引入原因和基本概念。记住,如果你对即将学习的内容感到紧张,我们始终与你同在。如果遇到困难,请回顾视频、动手实践,并与其他学习者交流。坚持学习是最好的方法。
145:基本 Linux 命令 🐧

在本节课中,我们将学习一系列在 Linux 操作系统中用于操作文件和目录的基本命令。这些命令是进行系统管理和自动化任务的基础。
我们已经使用过一些 Linux 命令。希望这些命令对你来说并不陌生。
你可能记得,echo 是用于向屏幕打印消息的命令。cat 是用于显示文件内容的命令。ls 是用于列出目录内容的命令。chmod 是用于更改文件权限的命令,等等。
正如之前提到的,许多这些命令源自 Unix。在 70 年代设计这些程序的行为方式时,其理念是每个程序应专注于一件事并将其做到极致。这意味着我们拥有许多命令,每个命令都用于执行特定的任务。
我们将快速浏览这些命令,但和往常一样,之后会提供一个速查表供你参考。你有充足的时间来复习这些命令并进行自主练习。
那么,让我们开始吧。
创建和导航目录
要创建一个新目录,我们使用 mkdir 命令。
mkdir new_directory
要切换到该目录,我们使用 cd 命令。
cd new_directory
你可能会注意到,这些命令成功执行后不会向屏幕打印任何内容。这是正常且预期的。我们使用的许多命令在成功时不会打印任何内容,只有在失败时才会打印信息。
要验证 cd 命令是否成功,我们可以使用 pwd 命令来打印当前工作目录。
pwd
操作文件
现在,我们有了一个空目录。我们可以使用 cp 命令来复制文件。例如,我们可以复制父目录中的 spider.txt 文件。
cp ../spider.txt .
等等,那些点是什么?这些是我们可以用来引用一些特殊目录的快捷方式。
..快捷方式代表父目录(上一级目录)的绝对路径。.快捷方式代表当前目录。
因此,上面这个命令是将位于上一级目录的 spider.txt 文件复制到当前目录。明白了吗?
我们还可以使用 touch 命令创建一个空文件。
touch myfile.txt
至此,我们的目录中有两个文件:我们复制的 spider.txt 文件,以及我们使用 touch 命令创建的 myfile.txt 文件。
查看目录详情
让我们使用 ls -l 命令查看目录的内容。
ls -l
很好,我们现在通过使用 -l 命令行参数调用了 ls 命令。记住,命令行参数允许我们改变命令的行为,使其执行我们想要的操作。
不带任何参数时,ls 只会列出目录中包含的文件名。通过传递 -l 参数,我们获得了分布在多列中的大量额外信息。
小测验时间。这些列分别代表什么?
以下是各列的含义:
- 第一列表示文件的权限。
- 第二列是指向该文件的 inode 数量。
- 第三列和第四列表示文件的所有者和所属组。
- 接着是文件的大小、最后修改日期,最后是文件名。
在我们的例子中,我们有一个复制的文件,大小为 192 字节,以及另一个使用 touch 命令创建的文件,大小为 0 字节。
让我们通过调用 ls -la 来查看另一个 ls 命令行参数。
ls -la
-a 标志用于显示隐藏文件,即以点开头的文件。在本例中,唯一的隐藏文件就是我们之前提到的快捷方式:代表当前目录的 . 和代表父目录的 ..。这些目录的大小与其中包含的文件数量有关。
重命名、移动和删除文件
要重命名或移动文件,我们使用 mv 命令。要复制文件,我们使用之前提到的 cp 命令。
mv myfile.txt emptyfile.txt
cp spider.txt spider_copy.txt
我们现在已将 myfile.txt 重命名为 emptyfile.txt,并创建了 spider.txt 文件的一个新副本。这些命令都使用相同的格式:第一个参数是旧文件,第二个参数是新文件。
让我们现在查看目录的内容。
ls -l
我们看到现在有两个大小为 192 字节的文件副本,并且空文件现在名为 emptyfile.txt。
要删除这些文件,我们可以使用 rm 命令。我们可以逐个删除,也可以使用星号 * 一起删除。
rm spider.txt spider_copy.txt emptyfile.txt
# 或者
rm *
星号 * 是一个占位符,会被我们目录中所有文件的名称替换。所以我们的目录再次变空了。
删除目录
现在让我们删除这个目录。首先,我们需要切换到上一级目录。我们使用 cd .. 来实现。再次强调,.. 是我们用来标识上一级目录的方式。
cd ..
现在,我们可以使用 rmdir 命令删除目录。
rmdir new_directory
这个命令只对空目录有效,所以如果我们在目录中留下了任何文件,它将无法工作。

这次,在调用 ls 命令时,我们传递了我们想要列出的目录名称,并返回了一个错误,因为该目录已不存在。
ls new_directory
它真的存在过吗?这确实引人深思。
总结与后续
无论如何,这是对 Linux 中用于操作文件和目录的一些命令的快速概述。还有很多其他命令需要讨论,但没有足够的时间一一介绍。
我们将在接下来的几个视频中提及其中一些,并在速查表中提供更多相关信息。请务必自行研究和练习使用所有这些命令。
请记住,阅读任何给定系统命令的文档可以帮助你了解更多关于其功能的信息。在 Unix 类系统上,这份文档通常可以在使用 man 命令的手册页中找到。
让我们继续前进。接下来,我们将讨论命令行交互的另一个方面:如何重定向 I/O 流。下节课见。
本节课总结:在本节课中,我们一起学习了 Linux 系统下操作文件和目录的核心命令,包括 mkdir、cd、cp、mv、rm、ls(及其参数 -l 和 -a)、touch 和 rmdir。我们还了解了特殊目录快捷方式 . 和 ..,以及通配符 * 的用法。这些是进行文件系统管理和后续自动化脚本编写的基础。
146:重定向流 📡

概述
在本节课中,我们将要学习操作系统中的重定向概念。重定向允许我们改变程序输入和输出的默认目的地,例如将输出保存到文件而非屏幕显示。我们将通过具体示例演示如何使用重定向符号操作标准输入、输出和错误流。
标准IO流回顾
上一节我们介绍了几种基本的Linux命令。本节中我们来看看如何操作IO流和Bash。
在之前的视频中,我们讨论了标准IO流。默认情况下,输入由文本终端的键盘提供,输出和错误显示在屏幕上。这不仅适用于我们的Python脚本,也适用于所有系统命令。

我们可以使用称为重定向的过程来改变这个默认设置。
重定向是将流发送到不同目的地的过程。
输出重定向到文件
操作系统为我们提供了这个过程,当我们希望将命令的输出存储在文件中而不仅仅在屏幕上查看时,它非常有用。
要将程序的标准输出重定向到文件,我们使用大于符号 >。
例如,以下Python程序仅使用print函数打印一行文本:
print("Hello, World!")
如果我们运行这个程序而不进行重定向,文本将通过STDOUT正常发送到显示器。
但如果我们使用大于字符 > 来重定向输出,则会发生完全不同的事情。
当我们以这种方式运行它时,来自 script.py 的STDOUT被重定向到一个名为 newfile.txt 的文件。如果该文件不存在,它将被创建。
让我们使用 cat 命令查看 newfile.txt 的内容。你看到了吗?
我们程序的输出最终出现在大于符号后我们写入的文件中。
请注意,就像我们之前看到的 open 函数使用的 'w' 文件模式一样,每次我们重定向STDOUT时,目标文件都会被覆盖。


追加输出到文件
因此,在使用此重定向时,我们需要格外小心,以免覆盖具有有价值内容的文件。
如果我们希望将重定向的标准输出追加到文件,可以使用双大于符号 >> 而不是单大于符号。
输入重定向
类似地,我们也可以重定向标准输入。
我们可以使用小于符号 < 来读取文件的内容,而不是使用键盘将数据发送到程序中。
让我们用之前视频中看到的 stdin_example.py 文件的新版本尝试一下。
现在,让我们将 newfile.txt 的内容重定向到此脚本。在这种情况下,我们在STDIN部分的屏幕上没有看到输入。这是预期的,因为输入是从文件中读取的,所以它只出现在STDout部分,我们看到它读取了两行中的一行。
这也是预期的,因为 input() 函数只读取直到遇到换行符。
错误流重定向
重定向STDERR以捕获程序中的错误和诊断消息也很有用。
这可以通过使用字符组合 2> 来完成,类似于我们之前重定向STDOUT的方式。
让我们再次执行我们的流示例,这次将错误输出重定向到一个单独的文件。
这次我们在屏幕上没有看到错误消息,那是因为我们将其重定向到了错误文件。
让我们看看是否能在该文件的内容中找到任何有用的信息。
啊哈,我们的错误就在那里。

如果你对数字 2 感到疑惑,它代表STDERR流的文件描述符。在此上下文中,你可以将文件描述符视为一种指向IO资源的变量,在这种情况下是STDERR流。0 和 1 分别是STDIN和STDOUT的文件描述符。
重定向的通用性
需要强调的是,所有这些都不是Python独有的。我们可以以相同的方式操作所有其他命令。
例如,我们可以使用 echo 命令并通过将其输出重定向到我们想要创建的文件来创建文件。
echo "File content" > myfile.txt
像往常一样,我们可以使用我们的朋友 cat 来查看新文件的内容。
总结
本节课中我们一起学习了重定向的核心操作。我们了解了如何将标准输出(> 和 >>)、标准输入(<)和标准错误(2>)重定向到文件,并理解了文件描述符 0、1、2 的基本概念。这些技能对于自动化脚本编写和系统管理至关重要。
在下一个视频中,我们将探讨如何在程序之间进行重定向。
147:管道与管道线 🚰

在本节课中,我们将要学习一种强大的IO流重定向方法——管道(Piping)。通过管道,我们可以将多个脚本、命令或程序连接成一个数据处理管道线,从而高效地传递和处理数据。
管道的基本概念 🔄

上一节我们介绍了文件的重定向操作,本节中我们来看看另一种更强大的IO流重定向方式——管道。
管道能够将一个程序的输出连接到另一个程序的输入。这意味着我们可以在程序之间传递数据,将一个程序的输出作为下一个程序的输入。管道在命令行中用竖线字符 | 表示。
使用管道是一个非常有用的工具。它允许我们通过组合不同命令的功能来创建新的命令,而无需将中间结果存储在临时文件中。
以下是管道的一个简单示例:
ls -l | less
在这个例子中,ls -l 命令的输出被连接到 less 命令的输入。less 是一个终端分页程序。当你想查看包含大量文件的目录内容时,这个例子非常有用。ls 生成的文件列表通过管道传递给 less,后者一次显示一页。我们可以使用 Page Up、Page Down 或方向键上下滚动。查看完毕后,按 Q 键退出。
构建复杂的管道线 🛠️
管道不仅限于连接两个程序,我们可以连接更多程序来构建复杂的数据处理管道线。
让我们通过一个更详细的例子来探索这一点。以下是一个复杂的命令行:
cat spider.txt | tr ' ' '\n' | sort | uniq -c | sort -nr | head
这个命令行看起来很复杂,让我们逐步分解:
cat spider.txt:首先使用cat命令获取spider.txt文件的内容。tr ' ' '\n':然后将这些内容发送给tr命令(“translate”的缩写)。它获取第一个参数中的字符(这里是空格),并将其转换为第二个参数中的字符(这里是换行符)。基本上,我们是在将每个单词放在单独的一行上。sort:接下来,通过管道将结果传递给sort命令。该命令按字母顺序对结果进行排序。uniq -c:排序后的结果再传递给uniq命令。它显示每个匹配项一次,并通过使用-c标志,在每个唯一行前加上其出现次数。sort -nr:这个输出再次通过管道传递给sort命令,这次使用-nr标志,表示按数字从大到小反向排序。head:最终输出传递给head命令,它将前10行打印到标准输出。
虽然步骤很多,但分解后逻辑就很清晰了。重点不是记住所有这些命令,而是要知道我们可以根据需要连接任意多个命令来完成想要的任务。
在管道中使用Python脚本 🐍
你也可以在管道中使用你的Python脚本。
Python可以通过 sys 模块提供的 sys.stdin 文件对象从标准输入读取数据。这是一个文件对象,类似于我们使用 open 函数获得的对象,并且它已经处于打开状态以供读取。
假设我们想编写一个脚本,读取输入的每一行,然后打印首字母大写的行。为此,我们将利用字符串的 capitalize 方法。
脚本如下所示:
#!/usr/bin/env python3
import sys
for line in sys.stdin:
print(line.strip().capitalize())
在这个脚本中,我们遍历 sys.stdin 文件对象的内容。记住,当我们遍历一个文件对象时,我们是逐行进行的。对于文件的每一行,我们首先使用 strip 方法去除末尾的换行符,然后使用 capitalize 方法将行的首字母大写,最后将其打印到标准输出。
现在,让我们使用这个脚本来大写化我们电脑上一个名为 haiku.txt 的文件。首先,用 cat 查看其内容:
cat haiku.txt
然后,通过将 cat 命令的输出与我们的脚本结合,使用管道来大写化我们的俳句:
cat haiku.txt | ./capitalize.py
cat 命令将 haiku.txt 文件的内容发送到标准输出,我们使用管道将其重定向到我们的脚本。我们的 capitalize 脚本使用 sys.stdin 文件对象遍历标准输入的每一行,并将大写版本打印到标准输出。
我们还需要指出,我们不一定需要使用管道来将 haiku.txt 文件的内容获取到脚本的标准输入。相反,我们可以使用上一节视频中看到的输入重定向操作符,像这样:
./capitalize.py < haiku.txt

一般来说,如果你只需要将某些内容从标准输入获取到你的脚本中,使用重定向就足够了。但是,如果你希望这成为更大命令管道线的一部分,则需要使用管道将它们组合起来。
例如,如果我们只想大写化匹配特定模式的行,我们可以先调用 grep,然后通过管道将其连接到我们的脚本:
grep 'pattern' haiku.txt | ./capitalize.py
总结 📝
本节课中我们一起学习了管道和管道线的强大功能。通过少量练习,创建管道线是一种快速而强大的方式,可以执行许多系统管理任务。当系统命令不具备你所需的功能时,你可以编写一个Python脚本来填补空白,并将其包含在你的管道线中。理解如何重定向IO流在许多情况下以及编写代码时都非常有用。
接下来,我们将深入探讨向计算机上运行的进程发送信号的不同方式。
148:发送进程信号 📡

概述
在本节课中,我们将学习操作系统进程间通信的一种重要方式:信号。我们将了解信号是什么,如何通过键盘快捷键和命令行工具发送信号,以及不同信号如何影响进程的行为。掌握这些知识将帮助你更好地控制和管理运行在系统上的程序。
什么是信号?🤔

上一节我们介绍了管道,它是进程间通信的一种方式。本节中我们来看看另一种通信机制:信号。
当处理操作系统时,我们通常使用许多不同的进程来完成目标。为了使这些进程协同工作,它们需要相互通信。例如,一个程序可能启动一个后台进程,并希望在超时后终止它。除了管道,另一种通信方式就是使用信号。
信号是传递给正在运行的进程的令牌,用以指示期望的操作。
信号的作用 🎯
使用信号,我们可以告诉一个程序我们希望它暂停或终止。我们也可以让它重新加载配置或关闭所有打开的文件。了解如何发送这些信号,能让我们与进程交互,并对其行为有更多控制。
如何发送信号?⌨️
有多种方式可以发送信号。以下是几种常见的方法:
1. 使用键盘快捷键
让我们在终端中执行 ping 命令。ping 命令现在正在运行,每秒向网络上的机器发送一次ICMP数据包。它会一直运行,除非我们中断它。
使用 Ctrl + C 中断进程
要中断它,我们可以使用 Ctrl + C 组合键。请注意,当我们中断它时,程序并非突然结束。首先,它会打印一个关于其操作和结果的摘要。在这种情况下的行为非常“礼貌”。其背后的原理是,进程收到了一个表明我们希望它停止的信号。当收到该信号时,进程会执行必要的清理工作以优雅地结束。
Ctrl + C 发送的信号叫做 SIGINT。这只是我们可以发送的众多信号之一。
使用 Ctrl + Z 暂停进程
另一个可以用来发送信号的键盘组合是 Ctrl + Z。让我们试试这个。
再次运行 ping。这次我们用 Ctrl + Z 中断它。这次,进程没有正常结束。我们收到一条消息说它“已停止”。发生了什么?我们发送的信号叫做 SIGSTOP。这个信号导致程序停止运行,但并未实际终止。不过别担心,我们可以通过执行 fg 命令让它再次运行。
fg 命令使我们的程序再次运行。它会继续运行,直到我们使用 Ctrl + C、Ctrl + Z 或其他信号中断它。现在让我们用 Ctrl + C 停止它。这次按下 Ctrl + C,我们让程序干净利落地结束了。
2. 使用 kill 命令
要发送其他信号,我们可以使用一个叫做 kill 的命令。默认情况下,kill 会发送一个名为 SIGTERM 的信号,告诉程序终止。
由于 kill 是一个独立的程序,我们需要在另一个终端中运行它,并且我们需要知道要发送信号的进程的进程标识符。

查找进程标识符
要找出我们想发送信号的进程的PID,我们将使用 ps 命令,该命令列出当前正在运行的进程。根据我们传递的选项,它会显示不同子集的进程和不同详细程度的信息。对于这个例子,我们将调用 ps ax,它列出当前计算机中所有正在运行的进程。然后,我们将使用 grep 命令只保留包含我们正在寻找的进程名称的行。
听起来不错。让我们试试看。我们将在第一个终端中运行 ping,然后在第二个终端中找到它的PID并终止它。
实践示例
我们的 ps 和 grep 命令发现正在运行的 ping 命令的PID是 4619。我们现在可以使用这个标识符,通过 kill 命令发送我们想要的信号。
kill 4619
我们现在发送了 SIGTERM 信号,进程被终止了。进程消失了。请注意,在这种情况下,我们没有在最后得到漂亮的摘要。程序只是结束了。
其他信号与应用场景 🔄
正如你所料,还有更多我们可以发送的信号,它们可能导致程序做出不同的反应。例如,许多长时间运行的程序,如果我们向它们发送一个特定信号,会从磁盘重新加载其配置。这样,我们可以让程序知道配置有重要更改,并且可以在程序无需停止并重新读取的情况下应用它。
提供网络服务的程序也可能收到一个信号,告诉它们应该完成处理任何当前打开的连接,然后一旦完成就干净地终止。理解这些信号是什么以及如何发送它们,将使你能够与你负责的系统上的进程交互,并使它们按照你的意愿行事。
总结 📝
本节课中我们一起学习了进程间通信的关键工具——信号。我们了解了信号是通知进程执行特定操作的令牌,掌握了通过 Ctrl + C 发送 SIGINT、通过 Ctrl + Z 发送 SIGSTOP 以及通过 kill 命令发送 SIGTERM 等信号的方法。我们还学习了如何使用 ps 和 grep 命令查找进程的PID。理解并运用这些信号,能让你更有效地管理和控制运行在操作系统上的各种进程。
149:Google IT Automation with Python 第75课 - 创建Bash脚本 🐚

概述
在本节课中,我们将要学习什么是Bash脚本,以及如何创建和运行简单的Bash脚本。我们将通过一个实际的IT调试场景来理解脚本的用途,并学习编写包含多个命令的脚本的基本语法。
什么是Bash脚本?🤔
在之前的视频中我们提到,Bash是Linux上最常用的Shell。Bash不仅是一个运行我们命令的解释器,它本身也是一种脚本语言。
当我们需要使用大量命令时,就可以用Bash来编写简单的脚本。在接下来的几节中,我们将学习如何编写这些脚本,并了解它们为何有用。
为何需要脚本?一个IT场景
让我们从一个例子开始,看看为什么你会需要编写脚本。作为一名IT专家,你有时需要调试一台运行不正常的计算机。
有许多命令可以帮助你了解系统内部情况以进行调试。例如:
ps命令可以列出所有当前正在运行的进程。free命令可以显示可用内存量。uptime命令可以告诉你计算机已经运行了多长时间,等等。
每次需要调试计算机时,你都可以手动逐一运行这些命令,再加上你能想到的任何可能有帮助的命令。
但这听起来已经很繁琐了。如果你能运行一个命令,一次性收集所有这些信息呢?
创建你的第一个Bash脚本 ✨
好消息是,我们可以通过创建一个Bash脚本来实现这个目标,该脚本包含我们想要调用的所有命令,一个接一个地执行。
让我们从一个简单的脚本版本开始。
以下是我们将看到的脚本,它调用了三个主要命令:uptime、free和who(who命令列出当前登录到计算机的用户)。
它使用 echo 命令来打印一些其他信息,并通过在命令之间留空行使输出更具可读性。
我们还调用了 date 命令来打印当前日期。为了调用这个命令,我们使用了一种特殊的表示法:将命令放在美元符号和括号内 $(command)。
这表示命令的输出应该传递给 echo 命令并打印到屏幕上。
脚本示例:
#!/bin/bash
echo "Starting diagnostics at $(date)"
echo
echo "Uptime:"
uptime
echo
echo "Free memory:"
free
echo
echo "Logged-in users:"
who
echo
echo "Diagnostics complete at $(date)"
运行脚本并查看结果 🚀
现在让我们执行我们的Bash脚本,看看会发生什么。
要运行脚本,首先需要确保它具有可执行权限,然后通过 ./ 来调用它(假设脚本文件名为 diagnostics.sh):
chmod +x diagnostics.sh
./diagnostics.sh
运行成功!我们的脚本按预期工作。开始和结束时间是相同的,因为我们执行的操作非常少,计算机完成它们所需的时间不到一秒。
这还不错。一旦我们添加更多操作来收集其他信息,可能需要更长一点时间。
脚本的格式:一行或多行 📝
这是一个简单的脚本。我们可以不断向其中添加更多命令,使我们的信息收集命令获取所有与调试相关的信息。
请注意,在目前编写的脚本中,每行有一个命令。这是一种常见的做法,但并不是唯一的方式。
我们也可以使用分号 ; 将命令分隔开,将它们写在同一行上。
让我们看看那是什么样子。
单行格式示例:
#!/bin/bash
echo "Starting at $(date)"; echo; echo "Uptime:"; uptime; echo; echo "Free:"; free; echo; echo "Users:"; who; echo; echo "Ending at $(date)"
现在让我们执行它以检查它是否仍然像以前一样工作。
是的,仍然按预期工作。

总结 🎯
本节课中我们一起学习了Bash脚本的基础知识。我们了解到Bash脚本可以自动化执行一系列命令,这在IT调试等场景中非常有用。
我们创建了一个简单的诊断脚本,学习了如何将命令组合在一起,并使用 $(command) 语法来捕获命令的输出。我们还看到了脚本命令可以分行编写,也可以用分号在同一行内分隔。
难以置信,你现在已经学会了用两种不同的编程语言(Python和Bash)编写脚本。这很酷,对吧?我们才刚刚开始,在接下来的视频中还有更多内容。
150:Google IT Automation with Python 第76课 - 使用变量和通配符 🐚

在本节课中,我们将要学习Bash脚本语言的两个核心概念:变量和通配符。我们将了解如何在脚本中定义和使用变量来存储数据,以及如何使用通配符来匹配和操作文件列表。
变量基础 📦
正如我们在之前的视频中所说,Bash是一个功能齐全的脚本语言,而不仅仅是按顺序执行命令的工具。我们可以为变量赋值、进行条件操作、执行循环、定义函数等等。由于内容非常丰富,在接下来的几个视频中,我们只涵盖最基础的部分。
让我们从变量开始。与Python类似,Bash允许我们使用变量来存储和检索值。
在之前的视频中,我们了解了环境变量。这些变量是在命令执行的环境中设置的。我们提到过,我们使用等号来设置这些变量。当我们在Bash中想要访问变量的值时,我们需要在变量名前加上美元符号。
除了预定义的环境变量,我们还可以为自己的脚本定义变量。要做到这一点,我们只需为我们想要定义的变量名分配一个值。
注意:变量名和等号之间,或者等号和值之间,不能有空格。如果我们尝试在任一侧留空格来定义变量,Shell会抱怨找不到我们正在赋值的命令。
另外,请记住,你在脚本或命令行中定义的任何变量都只在你定义它的环境中是局部的。如果你希望该环境中的命令也能看到这个变量,你需要使用export关键字来导出它。
在脚本中应用变量 ✨
上一节我们介绍了变量的基本概念,本节中我们来看看如何在实际脚本中使用变量。
现在,让我们修改我们的信息收集脚本,并向其中添加一个变量。我们将使用它来美化脚本,在每个命令之间添加分隔线。
为此,我们将定义一个名为line的变量,并在其中放入一串破折号。现在,我们将打印这个变量来分隔我们的命令,而不是留空行。
以下是修改后的脚本代码示例:
#!/bin/bash
line="----------------------------------------"
echo "Starting system information report."
echo $line
uname -a
echo $line
df -h
echo $line
现在让我们尝试执行修改后的脚本。完美,你看到了。我们在Bash脚本中设置并使用了变量。
通配符(Globs)介绍 🌟
让我们继续学习Bash中另一个有趣的功能,称为通配符。通配符是允许我们创建文件列表的字符。
星号(*)和问号(?)是最常见的通配符。除了说起来很有趣之外,使用这些通配符可以让我们创建文件名序列,我们可以将其用作脚本中调用命令的参数。
你可能以前遇到过它们,但让我们快速回顾一下如何使用它们。
在Bash中,在命令行中使用星号将匹配我们指定格式的所有文件名。
让我们看几个例子。我们可以看到,当我们写*.py时,Shell会将其转换为一个列表,其中包含当前目录中所有以.py结尾的文件名。
我们也可以将星号放在表达式的末尾,以获取所有以特定前缀开头的文件列表。在这种情况下,我们获取当前目录中所有以字母c开头的文件。
我们也可以使用不带前缀或后缀的星号,这将匹配当前目录中的所有文件。

或者,问号符号可用于匹配恰好一个字符,而不是任意数量的字符。我们可以根据需要重复多次。例如,我们可以通过使用五个问号来获取名称中有五个字符的Python文件。
像这样使用通配符可以让我们创建一个可能要操作的文件列表,例如调用其他命令并传递此列表。如果你想在Python中使用此功能,可以通过glob模块实现。这听起来可能像外星人说的话,但它实际上非常强大。
总结 📝
本节课中我们一起学习了Bash脚本中的两个重要工具:变量和通配符。
我们学会了如何定义和使用变量来存储数据,并通过export关键字使其在环境中可用。我们还探索了如何使用星号和问号通配符来灵活地匹配和生成文件列表,从而简化文件操作任务。
当然,关于Bash脚本,我们还能做更多事情。在下一个视频中,我们将讨论条件执行。
151:Bash脚本编程 - 条件执行 🧠

概述
在本节课中,我们将学习Bash脚本编程中的一个核心概念:条件执行。我们将了解如何根据命令的退出状态或特定条件,让脚本执行不同的分支路径。这类似于Python中的if/else语句,但在Bash中,其实现方式和语法有所不同。
编程的核心概念:条件分支
编程的一个主要概念是能够根据条件分支执行。换句话说,就是让我们的程序根据一个或多个值的不同,表现出不同的行为。
在Python中,我们使用if代码块,条件是一个必须求值为True或False的表达式。
在Bash脚本中,使用的条件基于命令的退出状态。

你还记得我们之前讨论过的命令退出状态吗?我们提到过,可以使用$?来检查命令的退出状态。并且我们指出,在Bash脚本中,退出值为0表示成功。
Bash中的if运算符逻辑
Bash中的if运算符正是利用了这个逻辑来创建条件表达式。
我们将调用一个命令,如果该命令的退出状态是0,那么条件就被视为True。
假设我们想验证/etc/hosts文件是否包含127.0.0.1的条目(它应该包含)。我们知道grep命令在找到至少一个匹配项时会返回退出状态0,如果没找到匹配项则返回非零值。我们可以利用它来进行验证。
看看下面的脚本,让我们分析一下if代码块的语法。
if grep -q "127.0.0.1" /etc/hosts; then
echo "Everything is okay"
else
echo "ERROR! 127.0.0.1 is not in /etc/hosts"
fi
我们以if关键字开始,后面跟着用于检查成功与否的grep命令。在命令的末尾,有一个分号,然后是then关键字。之后是条件语句的主体。
我们像在Python中一样使用了缩进。这是一个良好的风格选择,使代码更具可读性,但在Bash中并非强制要求。有时,当代码量足够小时,我们可能会将其写在一行。
不过,通常最好将命令放在单独的行中,并使用缩进来清晰地显示条件语句的主体。
我们还为命令未成功完成的情况准备了一个else块。最后,使用fi关键字结束我们的条件块。
你可以看到,有些东西和Python是一样的:它使用if和else关键字,检查条件并根据条件的值分支执行。
但也有一些不同:我们需要在开始主体之前写上; then,并且需要用fi来结束代码块。注意这些异同点,将有助于你更快地熟悉新的编程语言。
运行脚本并观察结果
好了,让我们运行我们的脚本,看看它会做什么。
$ ./check_hosts.sh
Everything is okay
输出的第一行是我们的grep命令生成的,因为默认情况下,grep会打印与我们给出的表达式匹配的行。
输出的第二行是我们的脚本生成的。在这个例子中,脚本调用的grep命令在文件中找到了该行,并以0值退出,所以我们的脚本说一切正常。
如果grep没有找到那行,它会以一个非零值退出,我们就会收到不同的消息。

使用test命令评估更多条件
在我们的脚本中,可能还需要检查许多其他条件:一个文件是否存在、两个字符串是否相等、一个数字是否小于另一个数字等等。
为了帮助我们评估这些条件,有一个叫做test的命令。test是一个评估接收到的条件的命令,当条件为真时以0退出,为假时以1退出。
让我们看一个例子。在这个例子中,它足够短,我们可以把所有内容写在一行。
test -n "$PATH" && echo "Your path is not empty"

我们为test命令使用了-n选项,它检查一个字符串变量是否非空。在这个例子中,PATH变量非空,所以我们得到了消息。
像这样使用test命令非常普遍,还有另一种写法,看起来更像其他编程语言:
[ -n "$PATH" ] && echo "Your path is not empty"
在这种情况下,我们调用的命令是开方括号[。这是test命令的一个别名。但要成功调用它,我们还需要包含一个闭方括号]。
重要提示:使用这种语法时,请记住闭方括号]前必须有一个空格。
我们可以用test检查很多东西,但我们不会在这些视频中全部涵盖。我们会在接下来的速查表中包含其中一些,你也可以通过查看test的手册页来查看所有内容。

当前进展与后续展望
到目前为止,你对Bash脚本的样子有了一个粗略的了解。你做得真的很好。记住,如果有不清楚的地方,你随时可以复习内容。

还有很多我们尚未涉及的主题,比如使用循环或管理命令行参数。但在我们深入这些之前,让我们先做一个快速测验。
总结
在本节课中,我们一起学习了Bash脚本中的条件执行。我们了解到:
- Bash中的条件基于命令的退出状态(
0表示成功)。 - 使用
if command; then ... else ... fi结构来创建条件分支。 - 可以使用缩进来提高代码可读性,但这在Bash中是可选的。
- 介绍了
test命令(及其别名[ ])来评估更复杂的条件(如检查变量、文件等)。 - 通过比较Bash和Python的条件语句,我们注意到了语法上的异同,这有助于学习新的编程语言。
你已经掌握了让脚本做出智能决策的基础。在接下来的课程中,我们将探索更多控制脚本流程的工具。
152:Bash脚本中的while循环 🌀

概述
在本节课中,我们将学习Bash脚本中的while循环结构。我们将回顾已学知识,深入探讨while循环的语法和应用,并通过实际示例展示如何使用while循环重试可能失败的命令。课程内容旨在帮助初学者理解循环在自动化任务中的重要性,并掌握在Bash中实现循环的基本方法。
回顾与引入
上一节我们介绍了Bash脚本的基础知识,包括变量使用和条件执行。本节中,我们来看看Bash中的循环结构,特别是while循环。
Bash提供了与Python类似的循环结构。我们可以使用while循环在条件为真时迭代,也可以使用for循环遍历元素列表。当然,这些循环的语法略有不同。
循环使计算机能够为我们执行重复性任务。无论是处理一系列数字还是逐行处理文件内容,计算机都会不厌其烦地执行,直到任务完成。
简单的while循环示例
让我们查看一个Bash中的简单while循环示例。
在这个脚本中,我们使用变量N打印消息,从1计数到5。while循环的条件使用与if块相同的格式。在本例中,我们使用-le运算符检查变量n是否小于或等于5。
循环本身以do关键字开始,以done关键字结束。为了增加变量n的值,我们使用双括号的Bash结构,允许我们对变量进行算术运算。
n=1
while [ $n -le 5 ]
do
echo "Iteration number $n"
n=$((n+1))
done
虽然看起来复杂,但退一步看,所有部分都组合在一起。执行此脚本,我们可以看到它按预期工作。
实际应用:重试失败的命令
现在,让我们让循环更有趣一些。在Bash脚本中使用while循环时,常见的一种模式是循环重试命令多次,直到成功为止。这对于使用网络连接或访问可能被锁定的资源的命令非常有用。这些命令可能因外部原因失败,重试一两次后很可能成功。
为了模拟一个有时成功有时失败的命令,我们有一个小的Python脚本,它会从我们给定的范围内随机返回一个退出值。
import random
import sys
value = random.randint(0, 3)
print("Returning:", value)
sys.exit(value)
该脚本使用random.randint生成一个0到3之间的值,然后打印所选值并以该值退出。每次调用得到哪个值取决于随机生成,这正好符合我们模拟有时失败有时成功命令的需求。
重试脚本详解
现在,让我们看看用于重试命令的Bash脚本。
这个脚本比之前的示例稍复杂,但复杂程度有限。一个有趣的差异是我们使用$1获取命令行参数的值。在Bash中,我们使用这种方式访问第一个命令行参数。在Python中,我们使用sys.argv[1]获取相同的信息。
我们将参数存储在名为command的变量中,然后执行while循环,直到命令成功或变量n达到值5。换句话说,如果接收到的命令失败,我们将最多重试五次。
在while循环的主体中,我们首先睡眠几秒钟,然后递增变量并打印重试尝试的次数。
#!/bin/bash
n=0
command=$1
while ! $command && [ $n -le 5 ]; do
sleep $n
((n=n+1))
echo "Retry #$n"
done
我们调用sleep命令的原因是,如果由于CPU使用率、网络或资源耗尽导致命令失败,等待一段时间再重试可能有意义。因此,我们尝试的次数越多,等待的时间就越长,需要让计算机稍作喘息,从导致命令失败的状态中恢复过来。
在我们的模拟中,命令随机失败,但这个重试脚本适用于任何可能因各种原因失败的其他命令。
要尝试此脚本,我们需要使用随机退出命令作为参数调用重试脚本,如下所示:
./retry.sh python3 random_exit.py
我们可以看到脚本持续执行,直到我们传递的命令返回零,这正是我们想要的——零问题。

总结
本节课中我们一起学习了Bash脚本中的while循环。我们回顾了循环的基本概念,探讨了while循环的语法,并通过实际示例展示了如何使用while循环重试可能失败的命令。这个最后的示例是Bash中while循环的一个实际应用案例,包含了一些更高级的主题,因此可能感觉复杂。但不要因此止步,可以多次重看本视频,并练习我们介绍的脚本。
准备好后,我们可以在下一个视频中见面,届时我们将探讨Bash中的for循环。
153:Bash脚本中的for循环 🚀

在本节课中,我们将学习如何在Bash脚本中使用for循环。for循环是一种强大的工具,它允许我们对一系列元素执行重复操作。我们将通过一个实际的文件重命名示例,来理解其工作原理和应用场景。
概述 📋
在Python和Bash中,for循环都用于遍历一系列元素。for循环的关键在于,它允许我们对序列中的每个元素执行操作。在Python中,序列可以是列表、元组或字符串等数据结构。而在Bash中,我们只需用空格分隔元素来构建序列。
Bash中的for循环基础
让我们通过一个简单的例子来理解Bash中的for循环。在这个例子中,我们将遍历三个不同的水果名称元素。

for fruit in apple banana orange
do
echo "I like $fruit"
done
注意,for循环使用了与之前while循环相同的do...done结构。现在,让我们执行这个脚本,看看它是否按预期工作。
./fruit_script.sh
输出结果应该是:
I like apple
I like banana
I like orange
这看起来很简单,但它只是一个基础示例。
使用通配符遍历文件列表 🌟
在之前的视频中,我们提到在Bash中可以使用通配符(如*和?)来创建文件列表。这些列表由空格分隔,因此我们可以在循环中使用它们来遍历符合特定条件的文件列表,例如所有以.pdf结尾的文件,或以IMG开头的文件等。
让我们通过一个实际例子来看看如何应用。假设您正在将公司的网站从一个Web服务器或软件迁移到另一个。您的网页内容存储在一系列以大写.HTML结尾的文件中,而新软件要求它们全部以小写.html结尾。手动使用mv命令逐个重命名文件可能会非常繁琐且容易出错。相反,我们可以编写一个简短的Bash脚本来完成这个任务。
首先,让我们查看一下当前目录中的文件:

ls -l *.HTML
假设输出如下:
-rw-r--r-- 1 user group 1024 Jan 1 00:00 index.HTML
-rw-r--r-- 1 user group 2048 Jan 1 00:00 about.HTML
-rw-r--r-- 1 user group 3072 Jan 1 00:00 contact.HTML
-rw-r--r-- 1 user group 4096 Jan 1 00:00 services.HTML
-rw-r--r-- 1 user group 5120 Jan 1 00:00 products.HTML
看起来我们有五个文件需要重命名。那么,如何提取扩展名之前的部分呢?有一个叫做basename的命令可以帮助我们。这个命令接受一个文件名和一个扩展名,然后返回不带扩展名的文件名。
例如:
basename index.HTML .HTML
输出:
index
现在,我们准备好编写脚本来重命名文件了。我们将从包含Bash shebang行开始:
#!/bin/bash
我们的脚本将使用for循环遍历所有以.HTML结尾的文件:
for file in *.HTML
do
name=$(basename "$file" .HTML)
mv "$file" "$name.html"
done
在这个脚本中:
for file in *.HTML:遍历所有以.HTML结尾的文件。name=$(basename "$file" .HTML):使用basename命令提取不带扩展名的文件名,并将其存储在变量name中。mv "$file" "$name.html":将文件重命名为小写.html扩展名。
注意,我们使用双引号包围文件名变量,以确保即使文件名中包含空格,命令也能正常工作。在处理文件名或任何可能包含空格的变量时,这是一个很好的做法。
测试脚本 🧪
在运行修改文件系统的脚本之前,最好先在不实际修改文件系统的情况下运行它,以捕获脚本中可能存在的错误。我们可以通过在mv命令前添加echo来实现这一点:
for file in *.HTML
do
name=$(basename "$file" .HTML)
echo mv "$file" "$name.html"
done
保存脚本,使其可执行,并运行它:
chmod +x rename_script.sh
./rename_script.sh
脚本将打印出计划执行的重命名操作。如果一切看起来正确,我们可以移除echo,让脚本实际重命名文件:
for file in *.HTML
do
name=$(basename "$file" .HTML)
mv "$file" "$name.html"
done
再次运行脚本,这次不会打印任何内容,因为mv命令在成功时不会输出任何信息。我们可以通过列出目录内容来检查重命名是否成功:
ls -l *.html
输出应该显示所有文件都已成功重命名为小写.html扩展名。

总结 🎯
在本节课中,我们一起学习了如何在Bash脚本中使用for循环。我们首先介绍了for循环的基础语法,然后通过一个实际的文件重命名示例,展示了如何使用通配符遍历文件列表,并利用basename命令和mv命令完成批量重命名任务。我们还强调了在运行修改文件系统的脚本之前,先通过echo命令测试脚本的重要性。
通过掌握这些知识,您可以更高效地处理文件和系统命令,尤其是在与Python脚本结合使用时。接下来,我们将利用这些Bash脚本知识来解决一个有趣的系统管理挑战。敬请期待!
154:高级命令交互 🛠️

在本节课中,我们将学习如何利用已掌握的Linux命令行和bash脚本知识,处理系统日志文件,提取关键信息,并通过脚本自动化分析多个日志文件。
概述
在之前的课程中,我们学习了如何在Linux命令行和bash脚本中执行各种操作。本节中,我们将把这些新知识付诸实践,探索几个有趣的应用场景。我们将重点关注系统日志文件的分析,学习如何从中提取有用信息。
分析系统日志文件
首先,让我们回顾一下老朋友——位于/var/log/syslog的系统日志文件。这个文件包含了系统运行的大量信息,因此学会从中获取信息非常重要。
现在,我们使用命令查看该文件的最后10行:
tail -10 /var/log/syslog
我们看到的日志行遵循一个类似的模式。首先,它们包含条目添加到文件的日期和时间,然后是计算机的名称,接着是触发事件的进程名称和PID,最后是实际记录的事件。
提取日志事件信息
假设我们有一台计算机负载很高,但不知道原因。为了找出原因,我们需要检查syslog中记录最多的事件。为此,我们需要提取不含日期和时间的事件部分。
我们可以使用一个名为cut的命令来帮助我们。这个命令允许我们使用字段分隔符只获取每行的部分内容。在这个例子中,我们可以使用空格来分割行。具体操作如下:
cut -d' ' -f5-
在这个例子中,我们传递-d' '给cut,告诉它我们想使用空格作为分隔符,传递-f5-告诉它我们想打印第5个字段及之后的所有内容。这样,我们移除了日期和计算机名称,只保留了进程和事件消息。
统计最常见的事件
现在,我们有了关心的信息,可以将其通过管道传递给之前视频中看到的相同命令管道,以找出重复最多的行。如下所示:
cut -d' ' -f5- /var/log/syslog | sort | uniq -c | sort -nr | head -5
如你所见,我们将一系列命令链接在一起,从而获得了syslog文件中重复最多的行。
自动化分析多个日志文件
/var/log目录中还有更多我们可能感兴趣的文件,因此我们可以使用for循环遍历/var/log中的每个日志文件,并获取每个文件中最重复的行。
我知道你在想什么。对于一行命令链来说,这听起来有点太复杂了。我们最好将其放入一个bash脚本中,类似这样:
#!/bin/bash
for logfile in /var/log/*.log; do
echo "Processing: $logfile"
cut -d' ' -f5- "$logfile" | sort | uniq -c | sort -nr | head -5
done
在这个脚本中,我们处理/var/log目录中所有以.log结尾的文件。然后,我们打印正在处理的文件名,接着使用之前相同的命令组来打印每个文件中的前五行。
让我们执行它,看看实际效果:

bash analyze_logs.sh
很好。我们的脚本显示了/var/log中每个文件最常见的行。那里有很多文件。
总结
通过本节课程,我们一起完成了bash脚本编写的入门介绍,做得非常出色。现在,你同时掌握了Python和Bash的脚本编写技能,可能会想知道何时使用哪一种。我们将在下一个视频中讨论这个问题。到时见。
155:选择 Bash 还是 Python?🤔

在本节课中,我们将探讨在自动化任务时,如何根据具体情况在 Bash 脚本和 Python 脚本之间做出明智的选择。我们将分析各自的优缺点,并通过实例说明何时使用哪种工具更为合适。
通过前面的学习,我们已经了解到,使用系统命令可以完成许多有趣的任务。
我们接触了大量不同的命令,它们能帮助我们操作文件、管理进程、获取计算机信息、处理文件内容以及完成其他各种工作。
何时选择 Bash 脚本?⚙️
上一节我们介绍了系统命令的强大功能,本节中我们来看看如何利用 Bash 脚本将它们自动化。
通过使用 Bash 脚本,我们可以快速地将一个仅操作单个文件的命令,转变为一个能自动处理上千个文件的脚本。
这非常强大,对吗?正如我们在日志文件处理的例子中所见,有许多终端命令提供了文本处理功能。
其中很多命令还支持正则表达式,这允许我们对文件中的数据执行一些非常高级的处理。
当这些命令在一个数据处理管道中被串联起来时,它们就成为了处理文本数据的强大工具。
它们可以快速提供我们所需的信息,而无需编写完整的脚本。但正如常言道,能力越大,责任越大。
我们需要小心,不要滥用这种能力,因为它很快就会变得难以阅读。
请看以下这个例子:
echo "hello world from bash" | sed 's/\b\(.\)/\u\1/g'
这个命令行使用了一些我们见过的技巧,以及一些我们尚未深入探讨的内容,例如如何在 Bash 字符串上进行索引操作,以将每个单词的首字母大写。
我们大概都会同意,这个命令行相当难以阅读。如果其中恰好存在一个错误,要找出修复方法将非常困难。
转向 Python 的时机 🐍
当一个 Bash 命令行开始变得如此复杂时,更好的主意是编写一个 Python 脚本来处理数据,这种方式更具可读性和可测试性。
一个简单的 Python 脚本可能如下所示:
import sys
for line in sys.stdin:
words = line.strip().split()
capitalized_words = [word.capitalize() for word in words]
print(' '.join(capitalized_words))

在这个例子中,我们读取标准输入的每一行,去除空白字符,并将其分割成独立的单词。然后,我们使用列表推导式将每个单词首字母大写,最后用空格将它们重新连接起来并打印输出。
一旦我们有了这个脚本,就可以像下面这样将其作为管道的一部分来执行:
echo "hello world from bash" | python3 capitalize.py
因此,当我们的操作涉及文件和系统命令,并且任务足够简单、脚本能够自我解释时,选择 Bash 是一个好主意。
一旦脚本变得难以理解其意图,最好使用像 Python 这样更通用的脚本语言来编写。
Bash 与 Python 的权衡 ⚖️
Bash 脚本不如拥有完整 Python 语言及其众多操作字符串、列表和字典的函数那样灵活或健壮。
在使用 Bash 和 Linux 命令时,还有另一个需要注意的问题,我们之前也提到过:它们的可用性取决于我们使用的平台。

某些命令可能在某些操作系统上不存在。在 Linux 机器上编写 Bash 脚本可以非常快速地完成任务,但在 Windows 机器上它将无法工作,在那里我们需要用 PowerShell 编写相同的脚本。
因此,如果你试图完成的任务仅限于当前服务器或运行相同操作系统的服务器群,一个简单的 Bash 脚本就能胜任。
但如果你的代码很复杂,或者需要跨平台工作,那么使用 Python 标准库或其他提供相同功能的外部模块可能会是更好的选择。
总结与选择 🎯
本节课中我们一起学习了在自动化任务时如何权衡 Bash 和 Python。
最后一点:在很多情况下,无论是 Bash 脚本还是 Python 脚本,都能很好地解决问题。
在这些情况下,你可以选择你更熟悉、更得心应手的那一个。选择适合你的工具。
希望这一切开始变得清晰明了。无论你选择编写 Bash 脚本还是 Python 脚本,这两种技能在 IT 环境中都将对你大有裨益。
156:Bash脚本编程总结 🎉

在本节课中,我们将对模块六“Bash脚本编程”的核心内容进行总结。我们将回顾已学习的关键概念,并探讨如何在实际工作中应用这些技能。

概述
恭喜你坚持学习到这里,课程已接近尾声。现在,你可能开始理解为何Linux会成为我最喜爱的操作系统。
正如我在第一个模块中提到的,Linux是我作为系统管理员日常工作中使用的主要操作系统。尽管我个人成长过程中使用的是Windows电脑,但Linux为我打开了一个在Windows上无法实现的定制与配置的全新世界。我发现其中的挑战充满趣味,希望你也如此认为。
在模块六中,我们深入探讨了Linux命令行提供的诸多优势。
核心概念回顾
上一节我们概述了本模块的学习旅程,本节中我们来具体回顾学到的核心技能。
以下是我们在本模块中掌握的主要内容:
- 流重定向:我们学习了如何将输出和错误流重定向到文件或其他进程。例如,使用
>将命令输出保存到文件。ls > file_list.txt - 进程信号管理:我们学习了如何向进程发送信号以控制其行为,例如停止或继续执行。
- Bash脚本编程:我们探索了一门全新的编程语言——Bash脚本。这使我们能够将系统命令组合起来,实现自动化。
- 脚本元素应用:我们深入研究了如何在Bash脚本中使用变量、条件判断和循环,从而构建更强大、更灵活的逻辑。
# 示例:一个简单的带循环的脚本 for file in *.txt; do echo "Processing $file" done - 脚本语言选择:最后,我们分析了何时应选择Bash,何时又应选择Python来编写脚本,以便根据任务需求做出最佳决策。
自动化实践与价值
掌握了编写简单Bash脚本的能力,系统管理员可以快速自动化许多手动任务。
以下是自动化可以高效处理的一些典型任务:
- 批量重命名文件
- 实现命令失败后的自动重试
- 在日志文件中查找特定信息
一旦你熟悉了编写此类脚本,就能迅速完成测试工作,从而将时间集中在更需要专业知识的复杂事务上。我热爱在工作中发挥创造力和进行宏观思考,而自动化让我得以解放出来,专注于这些方面。
以我在谷歌工作的实验室为例,那里有大量机器需要配置。如果我和我的团队逐台手动配置,将耗费无穷无尽的时间。通过自动化部分任务,我不仅能快速完成工作,还能腾出时间投身于更新、更有趣的项目。
总结与展望
本节课中,我们一起回顾了Bash脚本编程的核心要点,包括流重定向、进程控制和脚本编写。我们看到了自动化如何显著提升系统管理工作的效率。
在即将到来的最终评估中,你将有机会综合运用Bash和Python脚本,来解决一个现实世界的问题。请记住,你可以利用截至目前我们所学的所有材料来帮助你完成挑战。
祝你好运。我相信你能成功。
157:最终项目介绍 🎯
在本节课中,我们将学习如何将本课程所学的所有知识整合起来,完成一个综合性的最终项目。这个项目旨在模拟一个真实的IT自动化场景,让你有机会运用Python解决实际问题。


经过漫长的学习旅程,我们终于来到了本课程的最后一个模块。恭喜你一路坚持到这里。这是一条充满挑战的道路,希望你现在对使用Python自动化系统任务充满信心。做得非常出色。
在我们的学习过程中,我们已经更加熟悉了Python提供的众多工具。我们学习了如何管理文件和目录、读写文本文件和CSV文件、使用正则表达式、理解系统如何与我们的程序交互、执行系统命令以及编写自动化测试等。我们甚至还学习了一点名为bash的不同脚本语言。这确实是一门内容丰富的课程,而你像冠军一样完成了它。
你应该为自己能走到这一步而感到自豪。现在,是时候迎来本课程的巅峰之作了。
这个项目将让你把所有知识结合起来,去解决一个在IT工作中可能遇到的现实世界问题。
作为复习,我们将从回顾处理自动化项目的流程开始。之后,我们将准备好全身心投入到项目中。你准备好了吗?是的,你当然准备好了。让我们开始吧。
回顾自动化项目流程 🔄
上一节我们概述了最终项目的目标,本节中我们来看看处理一个自动化项目通常需要遵循的步骤。理解这个过程将帮助我们更系统、更高效地完成最终挑战。
一个典型的自动化项目流程包含以下几个关键阶段:
- 理解问题:清晰定义需要自动化的任务和目标。
- 分解任务:将复杂问题拆解成更小、更易管理的子任务。
- 研究与规划:确定需要使用的工具、库和方法。
- 逐步实施:编写代码,通常从一个简单的原型开始。
- 测试与调试:确保代码在各种情况下都能正确运行。
- 优化与文档:改进代码效率,并编写清晰的说明。
项目目标与技能整合 ⚙️
在回顾了基本流程后,我们来看看本次最终项目如何整合我们学过的技能。本项目旨在模拟一个真实的IT运维场景,要求你综合运用文件操作、系统交互、数据处理和自动化测试等多方面知识。
你需要完成的核心任务可能涉及以下一个或多个方面,具体取决于项目设定:
- 文件系统操作:使用
os或pathlib模块遍历目录、创建、移动或删除文件。 - 数据处理:读取
CSV或日志文件,使用正则表达式提取关键信息。 - 系统命令执行:通过
subprocess模块调用外部命令或脚本。 - 错误处理:使用
try-except块确保脚本的健壮性。 - 生成报告:将处理结果汇总并输出到新的文件(如
report.txt或summary.csv)。
准备开始 🚀
我们已经明确了项目和所需技能,接下来就是动手的时候了。在开始编码前,请确保你已准备好开发环境,并仔细阅读项目提供的详细需求说明。
以下是一些启动建议:
- 重读相关课程:如果不确定某个知识点,可以回顾关于文件处理、
subprocess或正则表达式的课程。 - 先写伪代码:用简单的语言描述每一步要做什么,这能理清思路。
- 分模块测试:不要试图一次性写完所有功能。完成一个小功能就测试一下。
- 善用搜索:官方文档和编程社区是你强大的后援。
本节课中我们一起学习了最终项目的引入,回顾了自动化项目的标准流程,并梳理了完成项目所需整合的关键Python技能。你已装备好所有必要的工具,接下来的舞台交给你了。运用所学,构建出你的自动化解决方案吧。祝你成功!
158:Python脚本编写流程详解 🐍


在本节课中,我们将学习如何系统性地从头开始编写一个Python脚本。我们将介绍一个经过验证的流程,帮助你更高效、更可靠地完成编码项目,无论是自动化小任务还是处理复杂信息的大型项目。
第一步:理解问题 📖
上一节我们介绍了课程目标,本节中我们来看看流程的第一步。

首先,必须完全理解问题陈述。这包括明确需要完成的任务,并识别出我们需要编写的程序的给定输入和期望输出。
公式表示:
问题理解 = 明确任务 + 识别输入 + 定义期望输出

第二步:进行研究 🔍
理解了问题之后,下一步是进行研究。
这意味着要弄清楚如何利用Python标准库或外部模块提供的工具来解决问题。我们的目标是避免重复造轮子。无论挑战看起来多么棘手和复杂,很可能已经有人解决过类似的问题。花时间研究现有的资源非常有价值。
以下是研究阶段的关键活动:
- 查阅可能用到的模块、类和函数的文档。
- 理解这些工具应如何应用。
- 学习文档中的示例,并思考它们与我们所需代码的关联。
第三步:制定计划 📝

知道了要写什么以及可用的工具后,我们应该进行一些规划。
这意味着思考哪些数据类型对我们的解决方案有用,需要执行的操作顺序,以及所有部分如何协同工作以形成我们的解决方案。如果问题复杂,将计划写在纸上或数字文档中会很有帮助。
在许多公司,在此阶段编写设计文档是常见做法,其中详细说明了问题陈述、将用于解决问题的工具以及解决方案的实施计划。让他人评论你的设计有助于确保所有细节都已被理清。
代码示例(计划伪代码):
# 1. 读取输入文件
# 2. 使用正则表达式解析数据
# 3. 将数据转换为字典列表
# 4. 计算统计信息
# 5. 将结果写入输出文件
第四步:编写与测试 ✍️
一旦有了清晰的计划,我们就可以开始实际编写脚本了。

这一步不仅包括编写代码,还包括检查代码是否按预期工作。我们通过手动测试代码和添加一些自动测试来实现这一点。
有时,人们会忍不住跳过充分理解问题、研究工具或规划解决方案的必要时间,直接进入编码阶段。但经验表明,花时间熟悉我们要做的事情以及可用的工具,会在实际实现所需的时间和最终解决方案的质量上产生巨大差异。
总结与展望 🎯
本节课中我们一起学习了编写Python脚本的四个关键步骤:理解问题、进行研究、制定计划以及编写与测试。遵循这个流程可以帮助你更系统、更高效地完成任何编码项目。
在接下来的课程中,我们将揭晓期待已久的最终项目。它究竟是什么呢?我们将在下一个视频中揭晓答案。
159:Python自动化运维项目实战 - 项目问题陈述 🎯
概述
在本节课中,我们将学习一个来自谷歌IT自动化课程的实战项目。该项目要求我们编写自动化脚本,处理系统日志文件,并生成两种报告。我们将理解项目背景、日志格式、具体需求以及最终目标。
项目背景介绍
想象一个场景。您公司的一台服务器运行着一个名为“Ty”的服务。该服务是一个内部工单系统,被公司内许多不同团队用来管理工作。

该服务在成功运行或遇到错误时,会将大量事件记录到Cislog日志中。该服务的开发人员请求您帮助从这些日志中提取一些信息,以便更好地了解软件的使用情况并改进它。
这并不难。作为一名崭露头角的IT专业人士,您热情地接受了这个任务。
因此,作为本课程的最终项目,您将编写一些自动化脚本来处理系统日志,并根据从日志文件中提取的信息生成一系列报告。
日志格式说明

日志行的格式与我们之前见过的类似。格式如下:

当服务正确运行时,它会向Cislog记录一条信息(info)消息,说明它做了什么、相关用户名以及事件关联的工单号。
如果服务遇到问题,它会向Cislog记录一条错误(error)消息,指出问题所在以及触发该问题操作的用户名。
报告需求分析
该服务的开发人员希望从这些数据中得到两种不同的报告。
以下是两种报告的具体要求:
-
系统生成的错误排名
- 这意味着需要列出所有记录的错误消息,以及每条错误消息出现的次数(不考虑涉及的用户)。
- 它们应该按从最常见到最不常见的错误进行排序。
-
服务使用情况统计
- 这意味着需要列出所有使用过系统的用户,包括他们生成了多少条信息消息和多少条错误消息。
- 此报告应按用户名排序。
报告可视化方案
为了可视化这些报告中的数据,您需要生成几个网页,这些网页将由运行在该机器上的Web服务器提供服务。
为此,您可以利用系统中已有的一个名为 csv_to_html.py 的脚本。该脚本将CSV文件中的数据转换为包含数据表格的HTML文件。
然后将这些文件放入Web服务器用于显示网页的目录中。
项目最终目标
目标是拥有一个脚本,可以每天自动完成所有必要的工作,无需任何用户交互。
这个脚本不需要自己完成所有工作。它可以调用其他脚本来执行单个任务,然后将结果组合在一起。事实上,我们建议拆分任务,以便每个部分都可以单独编写和测试。
总结与鼓励
我想您现在思绪万千。您的脉搏可能加快了一点,手心可能已经在键盘上出汗了。别担心,这听起来可能工作量很大,但一旦您理解了问题并做了一些研究和规划,一切都会开始步入正轨。
在下一个视频中,我们将为您提供一些关于如何开始分解此任务的提示。我们开始吧。
160:研究与计划指导 🧭

在本节课中,我们将学习如何将最终项目的复杂问题分解为可管理的小任务,并规划具体的研究与实施步骤。
上一节我们介绍了最终项目的问题陈述。本节中,我们来看看如何将其分解并制定行动计划。
分解问题与研究方法
我们已经明确,目标是在系统日志文件中查找特定的日志行。
强烈建议使用正则表达式来完成此任务。这种方式能更轻松地提取所需信息。
为了确定正确的正则表达式,可以使用如 Regex101.com 这类网站。它可以帮助你测试表达式并理解其匹配逻辑。
确定一个可能有效的模式后,请在Python解释器中尝试,以验证其能否匹配正确的行并捕获正确的信息。
数据处理与结构设计
提取信息后,你需要统计同类错误的数量,以及特定用户的信息和错误消息数量。
你能想到哪种数据结构对此有帮助吗?如果想到了字典,那么你的思路是正确的。
你将需要使用几个不同的字典:一个用于统计错误消息,另一个用于统计每个用户的使用情况。
随后,你需要根据不同的条件对字典中的数据进行排序。我们在Python入门课程中学习过排序。
可以随时回看相关视频,并重新阅读Python官方文档中关于排序的部分。
输出格式与文件生成

你的Python脚本输出应该是几个CSV文件。每个文件都需包含列名,并按要求的顺序排列数据。
生成这些文件后,你需要调用 csv_to_html.py 脚本来基于CSV数据创建HTML文件。
你可以查看该脚本的工作原理,关键在于向其传递两个参数:要读取的CSV文件名,以及要生成的HTML文件名。

最后这一步,你可以选择通过Python脚本或批处理/Bash脚本来完成。由于此步骤仅涉及调用命令和移动文件,我们建议使用Bash脚本来实现,保持简洁明了。
实施建议
我们建议你在开始实际实验之前,先进行研究、规划,甚至编写好代码片段。
以下是关键步骤的简要清单:
- 模式匹配:使用正则表达式网站设计并测试匹配模式,后在Python中验证。
- 数据存储:使用字典来分别统计错误类型和用户活动。
- 数据排序:对字典中的数据按需进行排序。
- 文件生成:将结果输出为格式正确的CSV文件。
- 格式转换:通过调用现有脚本,将CSV文件转换为HTML报告。
总结
本节课中,我们一起学习了如何将复杂的日志分析项目分解为清晰的步骤:从使用正则表达式进行模式匹配,到利用字典进行数据统计与排序,最后生成CSV文件并转换为HTML报告。关键在于先研究规划,再动手编码。祝你好运,你能成功完成。
161:职业身份探索指南 🧭

在本节课中,我们将学习如何构建和定义你的职业身份。职业身份是你专业旅程的指南针,它基于你的技能、动机和价值观,帮助你明确方向并朝着目标前进。
什么是职业身份?✨
职业身份是你基于个人特质、现有及未来能提供的专业价值,为职场带来的独特贡献。它由你全部的生活和工作经历塑造,并受到你的优势、动机和价值观的影响。同时,它也是你根据自身方向和目标主动培养的结果。
为何职业身份至关重要?💡
你越了解自己、清楚什么能让你成长以及你想去往何方,你就越能选择一条与你的优势、价值观和目标相符的道路。此外,雇主和同事也能更好地理解你能提供什么。这对你自身也有益:研究表明,拥有强大的职业身份能带来积极成果,例如提升工作表现、增强对有意义职业的承诺,甚至改善健康和幸福感。请记住,无论你的生活和工作经历如何,每个人都有可提供的价值。
探索职业身份的三大基石 🧱
探索职业身份的最佳方式之一是撰写你自己的职业身份陈述。我们将从分解其三个关键组成部分开始,这些部分将作为构建你个人职业身份陈述的基础模块:你的优势、你的动机和你的价值观。
接下来,让我们更详细地探讨这三个组成部分。
1. 你的优势
你的优势是你擅长完成的任务和活动。它们是你通过生活和工作经验获得的技能、知识和才能。
例如,你可能非常注重细节,或者擅长建立人际关系。也许你精通修理汽车,或者由于照顾家人而培养了耐心、同理心和解决问题的能力。
根据职场优势与领导力专家马库斯·白金汉的观点,优势是一种能增强你自身能力的活动。要成为优势,你必须擅长它,但它也应该让你感觉更强大、更有能力、更有活力。
对我而言,写作一直是一项优势。我在9岁时读了夏洛蒂·勃朗特的小说《简·爱》,从此爱上了写作。我心想:“那个女孩就是我。我也想写出这样的书。”随后,我在一生中投入了大量时间来发展这项技能,它总能让我充满活力,使其成为我职业身份的核心支柱。
2. 你的动机
从优势出发,我们转向下一个关键组成部分:你的动机。
你的动机源于你的热情和目的。了解什么能激励你非常重要,因为这是让你持续前进的动力。
正如我提到的,我热衷于用英语讲故事。我可以沉浸在写作中数小时。但我不仅仅享受讲故事,我还受到激励去帮助他人通过真实的故事讲述来表达他们自己的真相。这是我身份的一个决定性方面,因此也是我职业身份的一部分。
3. 你的价值观
我们已经讨论了优势和动机。最后,让我们探讨第三个关键组成部分:你的价值观。
你的价值观反映了对你最重要的事物。它们指导你如何应对决策、发展人际关系和克服挑战。
你可能并不总是意识到自己的价值观,但它们始终伴随着你,即使它们会随时间而变化。这些价值观包括正直、责任和善良等。
我的一些核心价值观是效率和服务他人。我不喜欢混乱。当我看到混乱时,我看到人们在受苦。我的想法会转向:“我如何帮助清理这个?我如何让这更高效?”在我的第一份工作中,我意识到没有人记录如何使用谷歌正在开发的产品。因此,我决定建立一个常见问题和答案的知识库,供我的团队使用,这样每次就不必从头开始。
如何构建你的职业身份?🔍
现在我们已经理解了关键组成部分,让我们着手构建你自己的职业身份。
首先,你需要做的就是保持好奇心。从问自己以下三个关于你的优势、动机和价值观的问题开始:

- 什么技能、知识和才能让我与众不同?
- 什么最能激励和驱动我?
- 什么价值观在指引我?
在此处暂停视频可能会有所帮助。拿一张纸或日记本,花10分钟思考这些问题。无需过度思考,只需写下脑海中浮现的内容。你以后随时可以完善或扩展你的答案。
深入挖掘职业身份的方法 📝

一旦你回答了这些问题,你还可以做更多事情来深入挖掘你的职业身份。
例如,评估可以帮助你更多地了解自己独特的技能、优势、偏好和价值观。其中许多评估可以在线获取,由一系列关于你的简短选择题组成,并能立即生成个性化的结果。
如果在此之后,你仍想进一步探索,你可以采访几位你的同伴。他们可以是现任或前任同事、同学,甚至是家人和朋友。选择那些非常了解你、并且你信任其诚实和深思熟虑的人。
向他们提问,例如:
- 你会如何向别人描述我?
- 我身上最突出的是什么?
- 我是如何激励你的?
请记住,了解自己的方法还有很多。但一旦你达到了一个阶段,对自己理解自身的优势、动机和价值观感到舒适和自信,你就可以将它们整合到一个职业身份陈述中。

撰写你的职业身份陈述 ✍️
职业身份陈述应该有三到四句话,不仅仅是列出你的资历。你还需要揭示你的热情和目的。
以下是一个基本的模板,帮助你开始:
我是一名 [角色],拥有 [年数] 年经验,从事 [成就]。
我最大的优势是 [优势],并且我擅长 [优势]。
我热衷于 [动机],并且我重视 [价值观]。
以下是我的陈述作为示例:
我是一名拥有超过10年经验的内容策略师和产品营销人员,致力于帮助企业利用新技术推动成功。我最大的优势是跨团队协作和提升效率,并且我擅长构思故事和创建营销计划以成功推出技术产品。我热衷于赋能品牌寻找并使用适合他们的解决方案,并帮助新技术的开发者开发出更好、更有效的产品。最重要的是,我重视在工作中保持乐趣、协作、包容和真实。
现在是另一个暂停视频的好时机。拿起那张纸或日记本,开始撰写你的职业身份陈述。

持续迭代与应用 🚀
请记住,你的陈述是一个持续完善的过程。随着你获得新的经验和自我认知,你应该重新审视并完善它。例如,在你完成谷歌职业证书之后。
那么,既然你已经写好了职业身份陈述,你应该用它做什么呢?
你的职业身份陈述是一种强大的方式,可以为你携带的所有其他职业发展工具增添清晰度和活力。你可以将其部分内容融入你的简历、领英个人资料、求职信和电梯演讲中。这将帮助你清晰、一致地传达对你重要的事物,并帮助你在同一领域中脱颖而出。它还可以指导你在求职或选择职业道路时更加有意识和有目的性。
总结 📚
在本节课中,我们一起学习了职业身份的概念及其重要性。我们探讨了构成职业身份的三大基石:优势、动机和价值观。通过自我提问、评估和他人反馈,你可以深入挖掘这些方面。最后,我们学习了如何将这些元素整合成一份有力的职业身份陈述,并了解如何将其应用于实际的职业发展工具中。
为自己探索和建立一个强大的职业身份是一段需要时间和努力的旅程。但请相信,这是值得的。你越了解自己和你的所求,你为职业生涯做出的选择就会越好。随着你不断成长并强化你的职业身份,你的北极星将更加明亮,指引你朝着目标前进。祝你迈向精彩旅程的下一步。
162:祝贺与总结 🎉

在本节课中,我们将回顾整个课程的核心内容,并祝贺你完成学习。我们将总结你已掌握的技能,并分享一些关于自动化脚本实践的经验与感悟。
概述
你已成功完成本课程。祝贺你。
这是一段漫长的旅程,你应该为能坚持到这里而感到兴奋。
现在,你对操作系统以及使用Python能完成的多种任务更加熟悉了。
已掌握的技能回顾
上一节我们概述了课程完成的意义,本节中我们来具体回顾你已学会的核心技能。
以下是你在本课程中获得的关键能力:
- 你知道如何创建、修改和删除文件及目录。
- 你了解如何使用正则表达式处理文本,无论是在Python中还是使用系统工具。
- 你学会了如何通过启动进程和向它们发送信号来与系统进程交互。
- 你获得了一些自动测试代码的经验,以确保其按预期工作。
- 你初步涉足了一些Bash脚本编写,并通过解决一个复杂的现实世界问题(代码重构)巩固了所有知识。
自动化实践的乐趣与挑战
在掌握了这些具体技能之后,我们来看看将知识付诸实践的体验。
作为一名系统管理员,我工作中最有趣和最有成就感的部分就是让代码运行起来。
有时,实现目标的路径并非一帆风顺,你不可避免地会犯一些错误。
但是,当你发现需要做出的那个改变,让一切像魔法般正常工作时,那种豁然开朗的时刻是无与伦比的。
巨大的胜利。
个人经验分享:第一个自动化脚本
了解了自动化带来的成就感,让我通过一个亲身经历的例子来具体说明。
我编写的第一个自动化脚本是为了我之前的一份工作。
我们当时有几台服务器,每月都需要手动归档一些文件、检查更新并在有更新时安装它们。
这是一项相当重复的任务,不是对我们时间的最佳利用。在第二轮执行这个过程后,我编写了一个脚本,按照相同的顺序自动执行所有这些步骤。
我还创建了一个记录脚本执行内容的日志文件。
执行代码并看到它正常工作,这种感觉非常令人满足。
我希望你也有许多机会分享同样的感受。
结语与祝福
好了,我非常享受与你共度的这段时光,分享我的一点故事以及我对IT和系统管理的热情。
学习这些概念并不容易,所以感谢你的坚持。
代表你在本课程中遇到或将在其他课程中遇到的同事们,我们想说:祝你好运。
我们希望在现实世界中看到你运用新技能付诸行动。
总结
本节课中我们一起回顾了整个课程的旅程。我们总结了你学到的关于文件操作、文本处理、进程管理、代码测试和脚本编写的关键技能,并分享了自动化实践中的挑战与巨大满足感。恭喜你完成学习,期待你将新技能应用于实际,开启高效的IT自动化之旅。
163:版本控制与Git入门 🚀

在本节课程中,我们将简要回顾已学内容,并预览下一门课程的核心主题:版本控制工具Git及其应用。
在之前的课程中,我们开始编写一些较为复杂的代码。随着学习的深入,你可能会意识到,在添加或删除功能时,拥有一个工具来保存代码的副本会非常有帮助。
这正是下一门课程将要学习的内容。为了让你了解更多信息,下面由我的同事Kenny为你介绍,他将担任你的下一门课程讲师。
以下是Kenny对下一门课程的介绍:
大家好,我是Kenny。下一门课程将学习版本控制,这是记录代码变更历史的过程。
我们将重点学习一个名为Git的工具,它是目前最流行的版本控制工具。
我们将学习如何使用Git,不仅用于个人项目,还通过一个名为GitHub的流行平台与他人协作。
我迫不及待要开始这门课程。这个工具非常有用,掌握它将对你IT职业生涯产生重大影响。
下一门课程的一个优点是,我们将学习如何使用Git跟踪个人代码,以及如何用它与他人协作。
我很高兴能与大家分享这些知识,期待在下一门课程中见到你们。
感谢Kenny的介绍,也感谢大家在本课程中的参与和学习。我们下一门课程再见。

浙公网安备 33010602011771号