查看全课大纲(第 35 / 51 节)
  1. 1.为什么人人都该学点编程?
  2. 2.计算机与程序设计:你的电脑到底在“想”什么?
  3. 3.Python 这门语言,到底有什么魔力?
  4. 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
  5. 5.如何安装一个更强大的代码编辑器?
  6. 6.汇率兑换1.0:你的第一个“钱生钱”小程序
  7. 7.你的第一行代码,藏着哪些秘密?
  8. 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
  9. 9.汇率兑换程序,如何让它“聪明”地判断币种?
  10. 10.汇率兑换程序能一直运行,直到我喊停吗?
  11. 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
  12. 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
  13. 13.怎么用 Python 画一个会动的五角星?
  14. 14.如何让程序自动画出不同大小的五角星?
  15. 15.函数自己调用自己,会发生什么?
  16. 16.用递归画出神奇的分形树
  17. 17.Python 怎么计算你一天躺着不动能消耗多少热量?
  18. 18.如何让程序“活”起来,持续为你服务?
  19. 19.如何让 BMR 计算器更“聪明”?
  20. 20.当程序遇到“不按套路出牌”的用户怎么办?
  21. 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
  22. 22.如何用列表记录每一周的存款?
  23. 23.如何让程序自己数数?—— 用 for 循环解放你的双手
  24. 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
  25. 25.52周存钱挑战:怎么根据日期自动查存款?
  26. 26.Python 怎么判断一年中的第几天?
  27. 27.列表 vs 元组:哪个更适合存储月份天数?
  28. 28.用集合给月份分个队,换个思路算天数
  29. 29.把月份和天数“锁”在一起:用字典给数据配个对
  30. 30.Python 怎么判断密码强弱?
  31. 31.Python 怎么给密码设置“防沉迷”系统?
  32. 32.Python 怎么把密码保存到文件里?
  33. 33.Python 怎么读取文件里的密码?
  34. 34.Python 怎么把密码检查工具“打包”起来?
  35. 35.Python 怎么把文件操作也“打包”起来?
  36. 36.计算机怎么“扔骰子”?——用Python模拟随机事件
  37. 37.如何用 Python 模拟掷两个骰子?
  38. 38.怎么用 Python 把骰子轨迹画出来?
  39. 39.骰子点数分布长啥样?用直方图一眼看穿!
  40. 40.用科学计算库让骰子程序“起飞”
  41. 41.空气质量指数怎么算?手把手教你写一个AQI计算器
  42. 42.空气质量指数计算:从零开始,让程序看懂空气
  43. 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
  44. 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
  45. 45.Python 怎么让程序自己判断文件类型?
  46. 46.如何让程序自己上网查空气质量?
  47. 47.用美味的汤来解析网页:Beautiful Soup 入门
  48. 48.如何让爬虫自动抓取全国所有城市的空气质量?
  49. 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
  50. 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
  51. 51.空气质量数据怎么“洗”干净,还能画成图?

Python 怎么把文件操作也“打包”起来?

约 15 分钟

小象实战讲义 · Python 入门:8 个小项目边玩边学

欢迎来到密码强度判断项目的最终章!经过前面五节课的“修炼”,我们已经把密码相关的逻辑都封装成了一个帅气的 PasswordTool 类。这节课,我们要完成最后一块拼图:把文件读写操作也“打包”成一个工具类。这样,你的主程序就会变得超级清爽,一眼就能看懂它在干什么。准备好迎接“封装”思想的毕业典礼了吗?

💡 核心导读

  • 本节新增:创建一个专门处理文件读写的 FileTool 类。
  • 温故知新:巩固上节课学的面向对象编程思想,特别是“封装”的好处。
  • 项目收官:完成密码强度判断项目的最终形态,主程序逻辑清晰、易于维护。
  • 知识扩展:了解面向对象的三大特点:封装、继承、多态(咱们先掌握封装就够啦)。

1. 回顾与目标:让程序更“干练”

还记得我们上节课的成果吗?我们把所有和密码判断相关的代码都塞进了一个叫 PasswordTool 的“工具箱”里。用的时候,只需要 password_tool = PasswordTool(你的密码),然后调用它的方法就行了,根本不用管里面是怎么实现的。

这感觉是不是很棒?代码一下子变整洁了。这节课,我们要对文件操作做同样的事情。现在,每次读写文件,我们都要写 open、write/readlines、close 这三步。能不能也把它们打包成一个“文件工具箱”呢?

当然可以!这就是我们 6.0 版本要做的唯一一件事:创建一个 FileTool 类。

2. 打造你的“文件工具箱”:FileTool 类

我们来一步步打造这个工具箱。它的核心功能就两个:写一行内容到文件,以及从文件读取所有行。

# 文件工具类 FileTool
class FileTool:
    """
    文件工具箱
    职责:专门负责文件的读写操作
    """
    def __init__(self, filepath):
        """初始化工具箱,告诉它要操作哪个文件"""
        self.filepath = filepath  # 把文件路径保存起来,方便后续使用

    def write_to_file(self, line):
        """写操作:把一行文本追加到文件末尾"""
        f = open(self.filepath, 'a')  # 以追加模式打开文件
        f.write(line)                 # 写入传入的这一行内容
        f.close()                     # 关闭文件,好习惯!

    def read_from_file(self):
        """读操作:从文件中读取所有行,并返回一个列表"""
        f = open(self.filepath, 'r')  # 以只读模式打开文件
        lines = f.readlines()         # 读取所有行,得到一个字符串列表
        f.close()                     # 关闭文件
        return lines                  # 把读取到的内容列表返回给调用者

看,这个类多清晰!__init__ 是它的“入职登记”,告诉它要操作哪个文件。write_to_file 和 read_from_file 是它的两个“技能”。以后任何想读写这个文件的地方,直接找这个工具箱就行了。

3. 使用工具箱:让主程序焕然一新

工具箱造好了,现在来看看怎么在咱们的主程序里用它,效果立竿见影!

def main():
    """
    主函数
    """
    try_times = 5
    filepath = 'password_6.0.txt'  # 定义要操作的文件名

    # 🎯 关键一步:实例化文件工具对象
    # 告诉文件工具箱:"你以后就专门操作 'password_6.0.txt' 这个文件"
    file_tool = FileTool(filepath)

    while try_times > 0:
        password = 'Hello123'  # 原程序用 input() 让用户输入,这里用固定值代替(对齐本节完整程序的示例),你可以改成自己的值试

        # 实例化密码工具对象(上节课的内容)
        password_tool = PasswordTool(password)
        password_tool.process_password()

        line = '密码:{}, 强度:{}\n'.format(password, password_tool.strength_level)

        # ✨ 使用文件工具箱进行写操作
        # 就这么简单一句话!背后的 open, write, close 工具箱都帮你搞定了
        file_tool.write_to_file(line)

        if password_tool.strength_level == 3:
            print('恭喜!密码强度合格!')
            break
        else:
            print('密码强度不合格!')
            try_times -= 1
        print()

    if try_times <= 0:
        print('尝试次数过多,密码设置失败!')

    # ✨ 使用文件工具箱进行读操作
    # 同样简单,调用方法,拿到结果
    lines = file_tool.read_from_file()
    print('文件中保存的所有记录:')
    for line in lines:
        print(line.strip())  # .strip() 去掉每行末尾的换行符

为了让这段代码能直接运行,我们需要把之前定义的 PasswordTool 类和 FileTool 类都放在前面。同时,我们用固定值模拟 input() 输入。

# 完整的、可运行的 6.0 版本程序
class PasswordTool:
    """密码工具类"""
    def __init__(self, password):
        self.password = password
        self.strength_level = 0

    def process_password(self):
        if len(self.password) >= 8:
            self.strength_level += 1
        else:
            print('密码长度要求至少8位!')
        if self.check_number_exist():
            self.strength_level += 1
        else:
            print('密码要求包含数字!')
        if self.check_letter_exist():
            self.strength_level += 1
        else:
            print('密码要求包含字母!')

    def check_number_exist(self):
        has_number = False
        for c in self.password:
            if c.isnumeric():
                has_number = True
                break
        return has_number

    def check_letter_exist(self):
        has_letter = False
        for c in self.password:
            if c.isalpha():
                has_letter = True
                break
        return has_letter


class FileTool:
    """文件工具类"""
    def __init__(self, filepath):
        self.filepath = filepath

    def write_to_file(self, line):
        f = open(self.filepath, 'a')
        f.write(line)
        f.close()

    def read_from_file(self):
        f = open(self.filepath, 'r')
        lines = f.readlines()
        f.close()
        return lines


# 主程序开始
try_times = 5
filepath = 'password_6.0.txt'
# 本节需要 password_6.0.txt(课程 resources 附件提供);为便于单独运行,
# 先用空文件重建一次,保证每次运行都从"空日志"开始(write_to_file 是追加模式,
# 若沿用上次的旧文件,读出来的记录会一次比一次多)
with open(filepath, 'w', encoding='utf-8') as f:   # 示例数据:每次运行都重建,保证输出一致
    f.write('')
file_tool = FileTool(filepath)

# 模拟用户输入,这里固定为'Hello123',你可以改成其他密码测试
password = 'Hello123'  # 原程序这里是 input('请输入密码:')

password_tool = PasswordTool(password)
password_tool.process_password()

line = '密码:{}, 强度:{}\n'.format(password, password_tool.strength_level)
file_tool.write_to_file(line)

if password_tool.strength_level == 3:
    print('恭喜!密码强度合格!')
else:
    print('密码强度不合格!')

# 读操作演示
print('\n--- 读取文件内容 ---')
lines = file_tool.read_from_file()
for line in lines:
    print(line.strip())

运行上面的代码,你会看到类似下面的输出:

恭喜!密码强度合格!

--- 读取文件内容 ---
密码:Hello123, 强度:3

是不是非常清晰?主程序里再也没有乱七八糟的 open 和 close 了,只有清晰的业务逻辑:“写日志”、“读日志”。这就是封装的魅力:隐藏复杂细节,提供简单接口。

4. 面向对象“三剑客”:封装、继承、多态

我们这两节课都在干一件事:封装。这是面向对象编程最核心、也是你现阶段最需要掌握的思想。简单说,封装就是“打包”,把相关的数据(属性)和操作(方法)塞进一个类里,用的时候整个拿来,不用关心内部细节。

面向对象还有两个著名的特点,我们简单了解一下,就像认识新朋友先知道名字:

  1. 继承:就像“子承父业”。可以创建一个新的类(子类),直接拥有另一个类(父类)的所有属性和方法,然后还可以添加自己特有的东西。
class Human:  # 父类:人类
    def speak(self):
        print("人类会说话")

class Chinese(Human):  # 子类:中国人,继承自Human
    # Chinese 自动拥有了 speak 方法
    def speak_chinese(self):  # 自己特有的方法
        print("你好!")
  1. 多态:字面意思是“多种形态”。指的是同一个方法名,在不同的类里可以有不同的实现。比如,Human 和 Dog 类都可以有 speak() 方法,但人说话和狗叫的实现完全不同。程序会根据对象的实际类型来调用正确的方法。

对于零基础入门的你,牢牢掌握“封装”就足够了。它能立刻让你的代码变得更有条理、更好维护。继承和多态是更高级的武器,等你在编程世界里继续探险时自然会用上。

5. 项目大总结:我们这六节课都学了啥?

恭喜你!完成了“判断密码强弱”这个完整的小项目。让我们回顾一下这趟旅程:

  • 1.0:巩固基础。用字符串方法(isnumeric(), isalpha())和分支结构实现核心判断逻辑。
  • 2.0:流程控制。引入循环和 break,让用户可以多次尝试,并学会何时跳出循环。
  • 3.0:数据持久化。学习文件写操作(open, write, close),把密码和强度保存到硬盘,让程序有了“记忆”。
  • 4.0:读取历史。学习文件读操作(readlines),能把保存的记录再读出来看看。
  • 5.0:第一次封装。创建 PasswordTool 类,把散落的密码判断逻辑打包成一个整洁的工具箱。这是面向对象编程的初体验。
  • 6.0:第二次封装。创建 FileTool 类,把文件操作也打包。至此,主程序变得非常简洁优雅,真正体现了封装的价值。

从一行行散乱的代码,到组织成两个职责分明的类,你的编程思维完成了一次重要的升级!

📝 动手练一练

  1. 增强密码规则:我们目前的规则只检查是否有字母,不区分大小写。请修改 PasswordTool 类,增加一条规则:密码必须同时包含大写字母和小写字母。(提示:使用字符串的 .isupper() 和 .islower() 方法遍历判断)
  2. 增加特殊符号:让密码强度要求更高,增加一条规则:密码必须至少包含一个特殊符号(如 +, -, *, $, @ 等)。思考一下,如何判断一个字符是不是特殊符号呢?(提示:可以定义一个包含所有允许的特殊符号的字符串,然后检查密码中是否有字符在这个字符串里)。
👉 点击查看第1题参考答案

思路:

  1. 在 process_password 方法中增加第四个判断规则。
  2. 需要两个布尔标记:has_upper 和 has_lower,初始都为 False。
  3. 遍历密码字符串,如果发现大写字母,has_upper 设为 True;发现小写字母,has_lower 设为 True。
  4. 如果最后 has_upper 和 has_lower 都为 True,则强度加1,否则提示用户。

关键代码片段:

# 在 PasswordTool 类的 process_password 方法中增加:
has_upper = False
has_lower = False

for c in self.password:
    if c.isupper():
        has_upper = True
    if c.islower():
        has_lower = True

if has_upper and has_lower:
    self.strength_level += 1
else:
    print('密码要求同时包含大写和小写字母!')

记得把合格的标准从3改为4哦(if password_tool.strength_level == 4:)。

👉 点击查看第2题参考答案

思路:

  1. 定义一个字符串,包含所有你认可的特殊符号,例如 special_chars = "+-*$@#!&"。
  2. 在 process_password 方法中增加判断。
  3. 遍历密码字符串,检查每个字符是否在 special_chars 字符串中(使用 in 关键字)。
  4. 如果找到任何一个,则强度加1,否则提示用户。

关键代码片段:

# 在 PasswordTool 类的 process_password 方法中增加:
special_chars = "+-*$@#!&"  # 你可以自己增减特殊符号
has_special = False

for c in self.password:
    if c in special_chars:
        has_special = True
        break  # 找到一个就够了,可以提前结束循环

if has_special:
    self.strength_level += 1
else:
    print('密码要求包含特殊符号(如 +, -, *, $, @ 等)!')

同样,合格的标准需要相应提高。

本章小结

了不起!你不仅完成了一个实用的密码强度判断工具,更重要的是,你亲身体验了如何将一个想法,从简单的脚本(1.0),一步步迭代、完善,最终构建成一个结构清晰、易于理解和扩展的“专业范儿”程序(6.0)。这个“螺旋式迭代”的过程,正是本课程希望你掌握的核心学习方式。

📋 行动清单

学完本章,你可以立刻:

  • 运行最终的 6.0 版本程序,体验一下封装后主程序的简洁。
  • 动手完成上面的练习,为你自己的密码判断工具增加更强大的规则。
  • 思考:在你的生活或工作中,有没有什么重复性的、可以“打包”成工具的任务?(比如整理文件、计算开销等)用编程思维想一想。

面向对象编程的大门已经为你打开,封装的思想将伴随你整个编程生涯。接下来,我们将进入一个全新的、充满随机性的项目,一起用 Python 来“模拟掷骰子”,探索概率的奥秘!

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第7章代码包:判断密码强弱(含全部版本 6 个 .py)
    ZIP · 5KB
    下载
看图文没弄懂?展开看本节视频讲解(约 15 分钟)
📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)