乐于分享
好东西不私藏

Python 面向对象习题(4/10)

Python 面向对象习题(4/10)

本文首发于微信公众号「拙见python」,基础板块第 7 篇。
适合人群:已阅读第 2 篇:Python 面向对象编程并动手敲过代码的读者。
题目难度:⭐ → ⭐⭐⭐⭐⭐ 逐步提升,建议先自己写,再看答案。


做题须知

  • 每道题标注了考察知识点难度星级
  • 先自己写,写不出来再看答案
  • 答案不是唯一的,能跑通且逻辑正确就行
  • 每道题答案下方附有思路解析

第 4 题:带校验的用户密码类 ⭐⭐⭐

考察知识点:封装(私有属性)、@property、@setter、异常处理

定义一个 User 类:

  1. 初始化接收 username,密码默认为空字符串
  2. 用 @property 暴露 password 属性
  3. 设置密码时校验:长度 6-20,必须包含数字和字母,否则抛出 ValueError
  4. 提供 verify(password) 方法验证密码是否正确
  5. 密码不能被直接读取@property 返回 "****"

测试正常设置、非法密码、密码验证。

参考答案:

class User:    def __init__(self, username):        self.username = username        self._password = ”” # 私有属性,存储真实密码     @property    def password(self):        ”””读取密码时返回掩码,不暴露真实密码”””        return ”****” if self._password else ”未设置”    @password.setter    def password(self, value):        ”””设置密码时进行校验”””        if not isinstance(value, str):            raise ValueError(”密码必须是字符串”)        if len(value) < 6 or len(value) > 20:            raise ValueError(”密码长度必须在 6-20 个字符之间”)        has_digit = any(c.isdigit() for c in value)        has_alpha = any(c.isalpha() for c in value)        if not (has_digit and has_alpha):            raise ValueError(”密码必须同时包含数字和字母”)        self._password = value        print(f”✅ 密码设置成功”)    def verify(self, password):        ”””验证密码是否正确”””        return password == self._password # 测试user = User(”zhuojian_python”)print(user.password) # 未设置# 正常设置user.password = ”abc123456”print(user.password) # **** # 密码验证print(user.verify(”abc123456”)) # Trueprint(user.verify(”wrong”)) # False # 非法密码测试for bad_pwd in [”123”, ”onlyletters”, ”12345678”, ”a” * 25]:    try:        user.password = bad_pwd    except ValueError as e:        print(f”❌ 「{bad_pwd[:10]}」设置失败:{e}”) # ❌ 「123」设置失败:密码长度必须在 6-20 个字符之间# ❌ 「onlyletters」设置失败:密码必须同时包含数字和字母# ❌ 「12345678」设置失败:密码必须同时包含数字和字母# ❌ 「aaaaaaaaaa」设置失败:密码长度必须在 6-20 个字符之间

思路解析:

  • _password用单下划线表示受保护属性,外部不应直接访问。

  • @property 定义 password 的读取行为:返回 "****" 而非真实密码,这是封装的体现——外部能「读」但读不到原始值。

  • @password.setter 定义写入行为在赋值时自动触发校验逻辑。user.password = "abc123456" 实际调用的是 setter 方法。

  • any(c.isdigit() for c in value)用生成器表达式检查是否包含数字,比写循环更简洁。

  • 真实密码存在 _password  中,但 @property  拦截了外部读取,实现了「可写不可读」的效果。

建议的练习方式

  1. 先自己写——不看答案,能写多少写多少

  2. 卡住了回看文章——第 2 篇对应章节有完整示例

关注「拙见python」,一起写干净的代码。

下一篇预告:Python 面向对象习题之5/10