弗兰的悲惨之旅
99.73M · 2026-04-04
封装的核心思想是:
举个例子,假设我们要设计一个银行账户类:
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
print(f"存入 {amount} 元,当前余额:{self.balance}")
def withdraw(self, amount):
if amount > self.balance:
print("余额不足!")
else:
self.balance -= amount
print(f"取出 {amount} 元,当前余额:{self.balance}")
在这里,BankAccount 将“账户信息”和“操作方法”封装到一个类中,对外只暴露 deposit() 和 withdraw() 两个安全接口,而不让外部直接修改余额。
Python 没有像 Java 那样严格的访问控制符(public、private、protected),但提供了约定俗成的方式来实现封装。
_attr:表示受保护的属性,建议只在类或子类中访问。__attr:表示私有属性,会触发“名称重整”(Name Mangling),外部无法直接访问。例如:
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance # 私有属性
def deposit(self, amount):
self.__balance += amount
print(f"存入 {amount} 元,当前余额:{self.__balance}")
def __check_balance(self): # 私有方法
print(f"账户余额:{self.__balance}")
def show_balance(self):
self.__check_balance()
使用时:
acc = BankAccount("小明", 1000)
acc.deposit(500)
acc.show_balance()
输出:
存入 500 元,当前余额:1500
账户余额:1500
如果你尝试:
print(acc.__balance)
会报错:
AttributeError: 'BankAccount' object has no attribute '__balance'
保护数据安全 防止外部代码直接修改对象内部数据。 例如:外部不能直接把余额改成负数。
控制访问权限 通过方法控制数据操作逻辑,保证一致性与正确性。
隐藏实现细节 外部只需调用接口,不关心内部实现。 例如用户不需要知道银行系统如何校验密码,只需要使用登录接口。
虽然双下划线属性外部无法直接访问,但 Python 提供了间接方式:
print(acc._BankAccount__balance)
输出:
1500
️ 这不是推荐做法,只是说明 Python 的封装是“约定优于强制”。 在实际开发中,应遵守封装原则,通过方法或属性装饰器访问内部数据。
如果希望安全地访问和修改私有属性,可以使用 属性方法(Property)。
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance
@property
def balance(self):
return self.__balance
@balance.setter
def balance(self, amount):
if amount < 0:
print("余额不能为负!")
else:
self.__balance = amount
使用方式:
acc = BankAccount("小红", 1000)
print(acc.balance) # 调用 getter
acc.balance = 2000 # 调用 setter
print(acc.balance)
输出:
1000
2000
这样,我们既能保持封装性,又能以更自然的方式访问数据。
| 概念 | 说明 |
|---|---|
| 封装 | 将属性与方法组合并限制外部访问 |
| 私有属性 | 以 __ 开头,只能在类内部访问 |
| 受保护属性 | 以 _ 开头,约定仅供类及子类使用 |
| 私有方法 | 以 __ 开头的方法,只能内部调用 |
| @property | 用于优雅地封装属性访问与修改 |
封装让对象更像“黑箱”,使用者只需通过接口操作,而不用关心内部结构。这种设计不仅提高了程序的安全性和可维护性,也让代码更符合“高内聚、低耦合”的设计原则。