Files
PythonLearn/03_面向对象/3_2_Python与Java的封装差异/encapsulation_comparison.py

70 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 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("差异 1Python 主要依靠命名约定表达成员用途。")
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()