# 第 3-2 课完整示例:Python 与 Java 的封装差异 # # 本示例重点演示 Python 的下划线命名约定和 @property。 # 运行时会直接输出关键结论,不完整阅读讲义也能看到本课重点。 class Account: """表示一个账户,并演示 Python 常见的封装方式。""" def __init__(self, owner: str, balance: float = 0.0) -> None: # 单下划线表示“仅供内部使用”的约定,但不会禁止外部访问。 self._owner = owner # 双下划线会触发名称改写(Name Mangling),避免子类意外覆盖同名属性。 # 它不是 Java private 那样的安全边界,也不能用于保护敏感信息。 self.__balance = 0.0 self.balance = balance @property def owner(self) -> str: """允许调用者以 account.owner 的形式读取账户所有者。""" return self._owner @property def balance(self) -> float: """读取余额;调用时不需要写成 get_balance()。""" return self.__balance @balance.setter def balance(self, value: float) -> None: """设置余额,并集中执行非负校验。""" if value < 0: raise ValueError("余额不能小于 0。") self.__balance = value def deposit(self, amount: float) -> None: """存入资金,并复用 balance 属性中的校验入口。""" if amount <= 0: raise ValueError("存入金额必须大于 0。") self.balance = self.balance + amount def main() -> None: """运行封装差异示例。""" account = Account("小明", 100.0) print("差异 1:Python 主要依靠命名约定表达成员用途。") print(f"单下划线属性仍可访问:{account._owner}") print() print("差异 2:@property 让方法校验和普通属性访问可以同时存在。") print(f"{account.owner} 当前余额:{account.balance}") account.balance = 150.0 print(f"赋值后的余额:{account.balance}") print() print("差异 3:双下划线是名称改写,不是绝对私有或安全机制。") print(f"对象中保存的实际属性名:{account.__dict__}") print() print("差异 4:属性赋值可以统一执行校验。") try: account.balance = -1.0 except ValueError as error: print(f"非法赋值已被阻止:{error}") if __name__ == "__main__": main()