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 用于优雅地封装属性访问与修改

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


相关推荐
kjkdd7 分钟前
6.1 核心组件(Agent)
python·ai·语言模型·langchain·ai编程
小镇敲码人13 分钟前
剖析CANN框架中Samples仓库:从示例到实战的AI开发指南
c++·人工智能·python·华为·acl·cann
萧鼎14 分钟前
Python 包管理的“超音速”革命:全面上手 uv 工具链
开发语言·python·uv
源代码•宸34 分钟前
大厂技术岗面试之谈薪资
经验分享·后端·面试·职场和发展·golang·大厂·职级水平的薪资
alvin_20051 小时前
python之OpenGL应用(二)Hello Triangle
python·opengl
铁蛋AI编程实战1 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘1 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
jiang_changsheng1 小时前
RTX 2080 Ti魔改22GB显卡的最优解ComfyUI教程
python·comfyui
喵叔哟1 小时前
06-ASPNETCore-WebAPI开发
服务器·后端·c#
0思必得02 小时前
[Web自动化] Selenium处理滚动条
前端·爬虫·python·selenium·自动化