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

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


相关推荐
love530love3 小时前
LiveTalking 数字人项目 Windows 部署完全指南(EPGF 架构)
人工智能·windows·python·架构·livetalking·epgf
遇事不決洛必達3 小时前
【Python基础】GIL 锁是什么及其对爬虫的影响
爬虫·python·线程·进程·gil锁
星辰徐哥3 小时前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥3 小时前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约3 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee3 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐3 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs3 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐3 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司3 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录