Python编程实战 - 面向对象与进阶语法 - 封装与私有属性

在面向对象编程(OOP)中,封装(Encapsulation) 是最核心的概念之一。它强调"数据与方法的绑定",并通过访问控制保护对象的内部状态不被随意修改。简单来说,封装让类更安全、更易维护,也让代码更具可控性和清晰性。


一、什么是封装

封装的核心思想是:

把数据(属性)和行为(方法)组织在一起,对外提供有限的接口访问,而隐藏内部实现细节。

举个例子,假设我们要设计一个银行账户类:

python 复制代码
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),外部无法直接访问。

例如:

python 复制代码
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()

使用时:

python 复制代码
acc = BankAccount("小明", 1000)
acc.deposit(500)
acc.show_balance()

输出:

复制代码
存入 500 元,当前余额:1500
账户余额:1500

如果你尝试:

python 复制代码
print(acc.__balance)

会报错:

csharp 复制代码
AttributeError: 'BankAccount' object has no attribute '__balance'

三、为什么需要封装

  1. 保护数据安全 防止外部代码直接修改对象内部数据。 例如:外部不能直接把余额改成负数。

  2. 控制访问权限 通过方法控制数据操作逻辑,保证一致性与正确性。

  3. 隐藏实现细节 外部只需调用接口,不关心内部实现。 例如用户不需要知道银行系统如何校验密码,只需要使用登录接口。


四、访问私有属性的方法

虽然双下划线属性外部无法直接访问,但 Python 提供了间接方式:

python 复制代码
print(acc._BankAccount__balance)

输出:

yaml 复制代码
1500

⚠️ 这不是推荐做法,只是说明 Python 的封装是"约定优于强制"。 在实际开发中,应遵守封装原则,通过方法或属性装饰器访问内部数据。


五、通过 getter 和 setter 管理属性

如果希望安全地访问和修改私有属性,可以使用 属性方法(Property)

python 复制代码
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

使用方式:

python 复制代码
acc = BankAccount("小红", 1000)
print(acc.balance)  # 调用 getter
acc.balance = 2000  # 调用 setter
print(acc.balance)

输出:

yaml 复制代码
1000
2000

这样,我们既能保持封装性,又能以更自然的方式访问数据。


六、总结

概念 说明
封装 将属性与方法组合并限制外部访问
私有属性 __ 开头,只能在类内部访问
受保护属性 _ 开头,约定仅供类及子类使用
私有方法 __ 开头的方法,只能内部调用
@property 用于优雅地封装属性访问与修改

封装让对象更像"黑箱",使用者只需通过接口操作,而不用关心内部结构。这种设计不仅提高了程序的安全性和可维护性,也让代码更符合"高内聚、低耦合"的设计原则。


相关推荐
码界奇点19 小时前
Python从0到100一站式学习路线图与实战指南
开发语言·python·学习·青少年编程·贴图
码事漫谈19 小时前
C++ 多线程开发:从零开始的完整指南
后端
9ilk20 小时前
【C++】--- 特殊类设计
开发语言·c++·后端
码事漫谈20 小时前
十字路口的抉择:B端与C端C++开发者的职业路径全解析
后端
Laravel技术社区21 小时前
pytesseract 中英文 识别图片文字
python
提笔了无痕21 小时前
git基本了解、常用基本命令与使用
git·后端
java1234_小锋21 小时前
Spring IoC的实现机制是什么?
java·后端·spring
喵个咪21 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:JWT 集成指南
后端·go
生骨大头菜1 天前
使用python实现相似图片搜索功能,并接入springcloud
开发语言·python·spring cloud·微服务
绝不收费—免费看不了了联系我1 天前
Fastapi的单进程响应问题 和 解决方法
开发语言·后端·python·fastapi