查看全课大纲(第 34 / 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 怎么把密码检查工具“打包”起来?

约 22 分钟

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

欢迎回来!经过前面几个版本的迭代,我们的密码强度检查程序已经相当能干了:能检查、能循环、能存文件、能读文件。但你不觉得主程序越来越像一个“大杂烩”吗?各种功能混在一起,想改个规则都得在代码里翻半天。

这一节,我们要做一件很酷的事:把跟密码相关的所有“零件”(检查数字、检查字母、计算强度)都装进一个“工具箱”里。以后你想检查密码,直接打开这个工具箱用就行,不用再关心里面螺丝刀是怎么转的。这个“打包”的过程,在编程世界里有一个响亮的名字——面向对象编程。

学完这一节,你的程序会变得结构清晰、主次分明,主程序可能只剩下短短几行,但功能一点没少!这就像从“手工组装电脑”升级到了“买品牌整机”,省心又专业。

💡 核心导读

  • 认识编程的“两大门派”:面向过程 vs. 面向对象,它们看待问题的角度有何不同?
  • 什么是“对象”和“类”:用生活中的猫和车来理解这两个核心概念。
  • 打造专属“密码工具箱”:我们将创建一个 PasswordTool 类,把所有密码检查逻辑都封装进去。
  • 体验“封装”的魔力:主程序变得异常简洁,你只需要知道“怎么用”,不用管“怎么实现”。

编程的“两大门派”:过程派 vs. 对象派

在编程江湖里,主要有两大思想流派,它们看待和解决问题的方式很不一样。

第一派:面向过程 (Procedure-Oriented Programming, POP)

  • 核心思想:以程序的执行过程为中心。就像我们之前写的代码,先输入密码,然后检查长度,再检查数字,最后检查字母,一步接一步,画出流程图就能直接转换成代码。
  • 优点:思路直接,符合我们一步一步解决问题的习惯。
  • 我们之前写的所有版本,都属于面向过程。

第二派:面向对象 (Object-Oriented Programming, OOP)

  • 核心思想:以事物为中心。我们把要处理的东西(比如“密码”)看作一个独立的“对象”,然后思考这个对象有什么特征(属性),能做什么动作(方法)。
  • 优点:更贴近现实世界的思维方式,代码结构清晰,易于维护和复用。
  • 本节,我们就要迈入面向对象的大门!

从现实世界理解“对象”和“类”

什么是对象 (Object)? 对象就是现实世界中的任何具体事物。每个对象通常包含两样东西:

  1. 属性 (Attribute):描述对象静态特征的。比如一只波斯猫,它的品种、颜色、大小就是属性。
  2. 行为 (Behavior):描述对象动态动作的。比如这只猫会叫、会跑、会捉老鼠,这些就是它的行为。

再比如一辆吉普车,它的类型、用途、马力是属性;发动、停车、拐弯是行为。

什么是类 (Class)? 类是对象的抽象和模板,是“一类”事物的总称。对象是类的具体实例。

它们的关系就像“汽车设计图”和“真正的汽车”:

  • 类 (Car):是设计图,定义了汽车应该有轮子、发动机、能跑等共性。
  • 对象 (你的 Polo 车,朋友的 Mini Cooper):是根据设计图制造出来的、实实在在的、各不相同的汽车。

从对象归纳出类的过程叫抽象;用类创造出具体对象的过程叫实例化。

打造我们的“密码工具箱”:PasswordTool 类

理解了概念,我们动手把之前散落的密码检查功能,封装成一个 PasswordTool(密码工具)类。

class PasswordTool:
    """
    密码工具类
    负责封装所有与密码强度检查相关的逻辑
    """
    def __init__(self, password):
        # 类的属性(静态特征)
        self.password = password       # 要检查的密码字符串
        self.strength_level = 0        # 密码强度等级,初始为0

    def process_password(self):
        """
        处理密码,应用所有规则并计算最终强度等级
        """
        # 规则1:密码长度大于8
        if len(self.password) >= 8:
            self.strength_level += 1
        else:
            print('密码长度要求至少8位!')

        # 规则2:包含数字
        if self.check_number_exist():
            self.strength_level += 1
        else:
            print('密码要求包含数字!')

        # 规则3:包含字母
        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():  # isnumeric() 判断字符是否为数字
                has_number = True
                break
        return has_number

    def check_letter_exist(self):
        """
        判断字符串中是否含有字母
        """
        has_letter = False
        for c in self.password:
            if c.isalpha():   # isalpha() 判断字符是否为字母
                has_letter = True
                break
        return has_letter

代码解读:

  1. class PasswordTool::用 class 关键字定义一个类,类名通常首字母大写。
  2. __init__(self, password)::这是一个特殊的初始化方法(构造函数)。当你创建一个 PasswordTool 对象时,它会自动被调用。
    • self:代表类实例自身,通过 self.属性名 来定义或访问属于这个对象的属性。
    • 我们在这里初始化了两个属性:self.password(传入的密码)和 self.strength_level(强度等级,初始为0)。
  3. process_password(self)::这是我们新增的核心方法。它把三条检查规则的组织逻辑放在了一起,并更新 strength_level。
  4. check_number_exist(self) 和 check_letter_exist(self):这两个是具体的检查方法。注意,因为它们也是类的方法,所以第一个参数也是 self。在方法内部,我们通过 self.password 来访问当前对象要检查的密码。
  5. 关键变化:所有方法内部需要用到密码时,不再从参数传入,而是直接使用 self.password。需要修改强度等级时,就操作 self.strength_level。

如何使用“工具箱”?主程序大变身!

定义了强大的工具箱后,我们的主程序就变得超级简洁和清晰。下面是包含 PasswordTool 类与主程序的完整 5.0 代码:

class PasswordTool:
    """
    密码工具类
    负责封装所有与密码强度检查相关的逻辑
    """
    def __init__(self, password):
        # 类的属性(静态特征)
        self.password = password       # 要检查的密码字符串
        self.strength_level = 0        # 密码强度等级,初始为0

    def process_password(self):
        """
        处理密码,应用所有规则并计算最终强度等级
        """
        # 规则1:密码长度大于8
        if len(self.password) >= 8:
            self.strength_level += 1
        else:
            print('密码长度要求至少8位!')

        # 规则2:包含数字
        if self.check_number_exist():
            self.strength_level += 1
        else:
            print('密码要求包含数字!')

        # 规则3:包含字母
        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():  # isnumeric() 判断字符是否为数字
                has_number = True
                break
        return has_number

    def check_letter_exist(self):
        """
        判断字符串中是否含有字母
        """
        has_letter = False
        for c in self.password:
            if c.isalpha():   # isalpha() 判断字符是否为字母
                has_letter = True
                break
        return has_letter

class PasswordTool:
    """
    密码工具类
    负责封装所有与密码强度检查相关的逻辑
    """
    def __init__(self, password):
        # 类的属性(静态特征)
        self.password = password       # 要检查的密码字符串
        self.strength_level = 0        # 密码强度等级,初始为0

    def process_password(self):
        """
        处理密码,应用所有规则并计算最终强度等级
        """
        # 规则1:密码长度大于8
        if len(self.password) >= 8:
            self.strength_level += 1
        else:
            print('密码长度要求至少8位!')

        # 规则2:包含数字
        if self.check_number_exist():
            self.strength_level += 1
        else:
            print('密码要求包含数字!')

        # 规则3:包含字母
        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():  # isnumeric() 判断字符是否为数字
                has_number = True
                break
        return has_number

    def check_letter_exist(self):
        """
        判断字符串中是否含有字母
        """
        has_letter = False
        for c in self.password:
            if c.isalpha():   # isalpha() 判断字符是否为字母
                has_letter = True
                break
        return has_letter


def main():
    """
    主函数
    """
    try_times = 5

    while try_times > 0:
        # 原程序用 input() 让用户输入密码,这里用固定值代替
        password = 'MyPass123'  # 你可以改成 '123'、'abc'、'short' 等测试

        # 1. 实例化密码工具对象:创建我们的"工具箱"
        password_tool = PasswordTool(password)

        # 2. 使用工具箱:调用处理方法
        password_tool.process_password()

        # 3. 获取结果并判断
        if password_tool.strength_level == 3:
            print('恭喜!密码强度合格!')
            break
        else:
            print('密码强度不合格!')
            try_times -= 1
            print()  # 打印空行

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

# 运行主程序
main()
恭喜!密码强度合格!

运行过程解析:

  1. password_tool = PasswordTool(password):这行代码就是实例化。它根据 PasswordTool 这个“设计图”,创建了一个具体的、属于当前密码 'MyPass123' 的工具对象 password_tool。同时,__init__ 方法被自动调用,完成了属性初始化。
  2. password_tool.process_password():我们告诉这个工具对象:“开始处理你的密码吧!” 对象内部就会运行三条规则,并计算出 strength_level。
  3. password_tool.strength_level:处理完成后,我们直接询问对象:“你的强度等级是多少?” 然后根据结果做出判断。

面向对象的核心优势——封装: 看看现在的主程序,你是不是完全不用关心“怎么检查数字”、“怎么检查字母”了?你只需要知道:

  1. 用 PasswordTool(密码) 创建一个工具。
  2. 调用工具的 process_password() 方法。
  3. 查看工具的 strength_level 属性。

至于工具内部是怎么实现的,你可以不关心(如果想了解,当然可以看类的代码)。这种“隐藏内部细节,只暴露使用接口”的思想,就叫做封装。它让代码模块化,让协作变简单(别人给你一个类,你拿来就用),也让程序更容易维护。

📝 动手练一练

  1. 【理解与修改】 我们当前的 PasswordTool 类在 process_password 方法中,无论密码是否合格,都会把结果写入文件。如果我们想只在密码合格时才记录,应该修改哪部分代码?是修改主程序,还是修改 PasswordTool 类?为什么?
👉 点击查看参考答案

思路:这个需求是关于“何时进行记录”的业务逻辑,属于程序流程控制的一部分,而不是密码工具本身的核心功能(检查强度)。因此,应该修改主程序。

关键代码片段修改(在主程序 main 函数内):

# ... 实例化 password_tool 和调用 process_password() 之后 ...

if password_tool.strength_level == 3:
    print('恭喜!密码强度合格!')
    # 只有合格时才写入文件
    f = open('password_v5.txt', 'a')
    f.write(f'密码:{password}, 强度:{password_tool.strength_level}\n')
    f.close()
    break
else:
    print('密码强度不合格!')
    try_times -= 1
# 注意:原来在判断条件之前的那行写文件代码需要移除

这样修改后,文件操作这个“行为”的发生时机就由主程序的业务逻辑来决定了,PasswordTool 类只专注于“计算强度”这一件事,职责更清晰。

  1. 【动手实现】 尝试为 PasswordTool 类增加一条新的密码规则:密码必须同时包含大写和小写字母。你需要添加一个新的检查方法(例如 check_upper_lower_exist),并在 process_password 方法中调用它。提示:可以使用字符串的 .isupper() 和 .islower() 方法。
👉 点击查看参考答案

思路:首先在类中添加一个新的检查方法,遍历密码,分别记录是否遇到过大写字母和小写字母。然后在 process_password 中调用该方法,并根据结果更新强度等级。

关键代码片段(添加到 PasswordTool 类中):

def check_upper_lower_exist(self):
    """
    判断字符串中是否同时包含大写和小写字母
    """
    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:
            break
    return has_upper and has_lower

# 在 process_password 方法中,在规则3之后添加规则4
def process_password(self):
    # ... 规则1, 2, 3 的代码保持不变 ...
    # 规则3之后:
    # 规则4:同时包含大小写字母
    if self.check_upper_lower_exist():
        self.strength_level += 1
    else:
        print('密码要求同时包含大小写字母!')

注意:添加新规则后,合格的 strength_level 就变成了 4,主程序中判断合格的条件也需要相应修改为 == 4。

本章小结

恭喜!你刚刚完成了编程思维的一次重要升级——从面向过程迈向了面向对象。你不仅学会了两个核心概念(类和对象),还亲手打造了一个结构清晰的 PasswordTool 类,体验了封装带来的整洁与便利。

面向对象编程是构建中大型程序的基石。虽然我们只是初窥门径,但你已经掌握了最核心的思想:将数据和操作数据的方法捆绑在一起,形成一个独立的、易于使用的“对象”。

📋 行动清单

  • 运行本节代码,尝试输入不同的密码(如 ‘123’、 ‘abcdefgh’、 ‘12345678’、 ‘MyPass123’),观察 PasswordTool 是如何工作的。
  • 修改 PasswordTool 类,比如改变某条规则的提示信息,或者调整强度等级的计算方式,感受一下修改被“封装”起来的代码是多么集中和方便。
  • 思考一下,你生活中还有哪些事物可以抽象成“类”?比如“手机”类有什么属性(品牌、型号、颜色)和行为(打电话、拍照、上网)?

在下一节,我们将继续巩固面向对象的写法,把“文件读写”这个功能也封装成一个类,让我们的密码管理程序变得更加模块化和强大。

—— 小象教研组

配套资料 · 直接下载

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

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