Python面向对象四大支柱——封装(Encapsulation)详解
off999 2025-08-01 20:04 60 浏览 0 评论
封装是面向对象编程的四大支柱之一,它指的是将数据(属性)和操作数据的方法(行为)捆绑在一起,并对外部隐藏对象内部实现的细节。下面我将全面详细地讲解Python中的封装概念及其实现方式。
一、封装的基本概念
1. 封装的核心思想
- 数据隐藏:隐藏对象的内部状态和实现细节
- 接口暴露:通过公共方法提供对数据的受控访问
- 实现隔离:外部代码不依赖于对象内部实现
2. 封装的好处
- 提高代码安全性(防止意外修改)
- 增强代码可维护性(内部修改不影响外部调用)
- 简化接口使用(隐藏复杂性)
- 便于修改实现(不影响客户端代码)
二、Python中的封装实现
Python通过命名约定而非强制机制实现封装,主要有三种访问级别:
1. 公开(Public)成员
- 无任何前缀的属性和方法
- 可以在任何地方被访问
class Person:
def __init__(self, name):
self.name = name # 公开属性
def greet(self): # 公开方法
print(f"Hello, I'm {self.name}")
p = Person("Alice")
print(p.name) # 可以直接访问
p.greet() # 可以直接调用2. 保护(Protected)成员
- 单下划线前缀:_member
- 约定为仅供类内部和子类使用(Python不强制限制)
class Person:
def __init__(self, name, age):
self.name = name
self._age = age # 保护属性
def _protected_method(self): # 保护方法
print("This is a protected method")
p = Person("Bob", 30)
print(p._age) # 仍然可以访问(只是约定)
p._protected_method() # 仍然可以调用3. 私有(Private)成员
- 双下划线前缀:__member
- Python会进行名称修饰(name mangling):_ClassName__member
- 无法直接从外部访问(但可以通过修饰后的名称访问)
class Person:
def __init__(self, name, age, id_number):
self.name = name
self._age = age
self.__id_number = id_number # 私有属性
def __private_method(self): # 私有方法
print("This is a private method")
def show_id(self):
# 类内部可以访问私有成员
print(f"ID last 4 digits: {self.__id_number[-4:]}")
p = Person("Charlie", 25, "123-45-6789")
# print(p.__id_number) # 报错: AttributeError
print(p._Person__id_number) # 可以通过修饰名访问(但不推荐)
p.show_id() # ID last 4 digits: 6789
# p.__private_method() # 报错
p._Person__private_method() # 可以调用(但不推荐)三、属性访问控制
Python提供了@property装饰器来实现更精细的属性访问控制。
1. 基本用法
class Temperature:
def __init__(self, celsius):
self._celsius = celsius # 保护属性
@property
def celsius(self): # getter
return self._celsius
@celsius.setter
def celsius(self, value): # setter
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
@property
def fahrenheit(self): # 只读属性
return self._celsius * 9/5 + 32
temp = Temperature(25)
print(temp.celsius) # 25
print(temp.fahrenheit) # 77.0
temp.celsius = 30
print(temp.fahrenheit) # 86.0
# temp.fahrenheit = 100 # 报错: AttributeError2. 只读属性
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def area(self):
return 3.14 * self._radius ** 2
c = Circle(5)
print(c.radius) # 5
print(c.area) # 78.5
# c.area = 100 # 报错: AttributeError3. 带验证的属性
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = balance
@property
def balance(self):
return self._balance
@balance.setter
def balance(self, amount):
if amount < 0:
raise ValueError("Balance cannot be negative")
self._balance = amount
acc = Account("Alice", 100)
print(acc.balance) # 100
acc.balance = 150
print(acc.balance) # 150
# acc.balance = -50 # ValueError四、封装的高级技巧
1. 使用__slots__限制属性
class Point:
__slots__ = ['x', 'y'] # 只允许这两个属性
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(3, 4)
print(p.x, p.y) # 3 4
# p.z = 5 # 报错: AttributeError2. 自定义属性访问
class SecretHolder:
def __init__(self, secret):
self.__secret = secret
def __getattribute__(self, name):
if name == "_SecretHolder__secret":
raise AttributeError("Access denied")
return super().__getattribute__(name)
def get_secret(self, password):
if password == "1234":
return self.__secret
return "Wrong password"
s = SecretHolder("Top Secret")
# print(s._SecretHolder__secret) # 报错: Access denied
print(s.get_secret("1234")) # Top Secret
print(s.get_secret("wrong")) # Wrong password3. 使用描述符(Descriptor)
class NonNegative:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if value < 0:
raise ValueError("Value cannot be negative")
instance.__dict__[self.name] = value
class Order:
price = NonNegative() # 描述符实例
quantity = NonNegative() # 描述符实例
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
def total(self):
return self.price * self.quantity
order = Order("Apple", 1.5, 5)
print(order.total()) # 7.5
# order.price = -1 # ValueError
# order.quantity = -2 # ValueError五、封装的最佳实践
- 最小化公开接口:只暴露必要的属性和方法
- 使用属性代替直接访问字段:通过@property控制访问
- 遵循命名约定:
- 公开成员:无前缀
- 保护成员:_single_underscore
- 私有成员:__double_underscore
- 文档化接口:使用docstring说明如何使用类
- 保持一致性:在整个项目中保持相同的封装风格
六、封装的实际应用示例
1. 银行账户封装
class BankAccount:
def __init__(self, account_holder, initial_balance=0):
self._account_holder = account_holder
self._balance = initial_balance
self._transactions = []
@property
def balance(self):
return self._balance
@property
def account_holder(self):
return self._account_holder
def deposit(self, amount):
if amount > 0:
self._balance += amount
self._transactions.append(f"Deposit: +{amount}")
return True
return False
def withdraw(self, amount):
if 0 < amount <= self._balance:
self._balance -= amount
self._transactions.append(f"Withdraw: -{amount}")
return True
return False
def get_transactions(self):
return self._transactions.copy()
account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(200)
print(account.balance) # 1300
print(account.get_transactions()) # ['Deposit: +500', 'Withdraw: -200']
# account._balance = 1000000 # 技术上可行,但违反封装原则2. 温度转换封装
class Temperature:
def __init__(self):
self._celsius = 0
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
@property
def fahrenheit(self):
return self._celsius * 9/5 + 32
@fahrenheit.setter
def fahrenheit(self, value):
self._celsius = (value - 32) * 5/9
temp = Temperature()
temp.celsius = 25
print(f"Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenheit}")
temp.fahrenheit = 77
print(f"Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenheit}")总结
Python通过命名约定和特殊机制提供了灵活的封装能力:
- 使用单下划线_表示保护成员(约定)
- 使用双下划线__实现名称修饰的私有成员
- 使用@property实现精细的属性访问控制
- 可以通过__slots__、描述符等高级特性增强封装
良好的封装实践可以使你的代码更加健壮、安全和易于维护。记住,封装不仅仅是隐藏数据,更重要的是定义清晰的接口和边界。
相关推荐
- c盘删除的东西能恢复吗(c盘删掉的东西还在吗)
-
1.重新安装。 如果是安装在c盘下的普通应用程序,重新下载安装即可; 2.备份恢复或重装系统。 如果是删除了系统文件,在系统备过份且知道删除...
- 电脑如何重装系统winxp(电脑如何重装xp系统教程)
-
重装XP系统的步骤如下:1.首先备份您的重要文件和数据。2.插入XP系统安装光盘,重新启动计算机。3.在启动时按下计算机制造商指定的键(通常是F2、F12、Esc等)进入BIOS设置或启动菜单。...
- win8密钥永久激活工具(win8密钥永久激活工具在哪)
-
win8.1正式版升级win10,自动激活,win8.1的密钥不能激活win10,升级win10正式版以后,无论怎么安装win10,系统都是自动激活状态。终极PID检测产品密钥:GCRJD...
- 制作系统安装u盘教程(制作系统安装盘及系统安装的步骤)
-
答u盘做系统详细步骤如下: 1.首先我们要准备一个10G内存的空白u盘,然后在装机吧官网下载一个装机吧一键重装系统软件,安装完成后打开软件,制作模式选择”USB-HDD“分区格式为”NTFS“点击...
-
- 联想win7怎么进入bios设置(联想win7进入bios设置win10)
-
联想电脑win7进入bios设置的具体步骤如下: 1、首先我们打开电脑的同时,按下键盘上的“F2”。2、然后我们在弹出来的窗口中就可以进入到BIOS界面中。3、然后我们按下键盘上的“F10”,之后回车确定即可退出。联想电脑win7...
-
2025-11-09 14:03 off999
- 优盘里面的文件被误删了能否找回
-
如果您的文件在很久以前被误删并且没有进行任何操作,那么有可能通过一些专业的数据恢复工具来恢复被删除的文件。以下是一些可能的操作步骤:1.停止使用U盘:为了最大限度地提高恢复成功的几率,请停止使用U盘...
- 电脑系统程序下载(电脑应用程序下载)
-
1、首先下载并安装DriverDroid,运行后根据设置向导进行设置。2、然后注意安卓手机已获取ROOT,设置时需要连接电脑。3、将手机自动下载的bios文件移动到镜像根目录下(手机内存/Downlo...
- 万能网卡驱动离线安装包下载
-
电脑没网是吧,那你可以先用手机下载。之后放电脑上安装的万能网卡驱动下载地址http://drivers.160.com/universal/camera.html该驱动能够使大部分的网卡能够被系统...
- 正版office和盗版区别(office正版和盗版可以共存吗)
-
区别主要有三方面:1.office正版是付费的,而且价格相对而言较高,盗版呢价格相对低或者干脆免费。2.office正版因为是官方发行,文件肯定完整,功能齐全,稳定。盗版呢一般都是破译的或者是拷贝的,...
- ヽ这个符号怎么打出来(这个符号怎么打出来是在中间的)
-
下载酷狗拼音,软键盘就有了。ˋ☆╲ヽ
- 120g固态硬盘够用吗(10几年的老电脑换个固态硬盘)
-
一般办公家用还是够用了,分两个区,系统盘分50G,剩余的分一个区做资料盘。特殊要求,资料文件比较多的话,128g是不够用,只能分一个区。这个主要取决于您电脑主要的用途,如果您的电脑只是用来日常办公和娱...
- 谷歌浏览器google(谷歌浏览器googleplay)
-
GoogleChrome,又称Google浏览器,是一个美国Google(谷歌)公司开发的网页浏览器。该浏览器是基于其他开源软件所撰写,包括WebKit,目标是提升稳定性、速度和安全性,并创造出简单且...
- android13正式版下载(安卓版本13)
-
出现该问题的原因是,用户在设置里开启了新下载的APP,仅添加到APP资源库选项。大家只要进入“设置-主屏幕”,把新下载的APP,改为“添加到主屏幕”即可解决问题。修改完成后,你再进入AppStore下...
- firefox浏览器安卓版(firefox浏览器安卓版 打开本地网页)
-
要进入火狐浏览器手机版的主页,你可以通过以下几种方式进行:首先,打开火狐浏览器App,然后点击右上角的三条横线菜单按钮,接着选择“主页”选项。另外,你也可以直接在浏览器地址栏中输入“about:hom...
- 电脑cpu性能排行榜天梯图(“电脑cpu性能天梯图”)
-
一、英特尔酷睿i7670。这款英特尔CPU采用的是超频新芯,最大程度的提升处理器的超频能力。二、英特尔酷睿i74790kCPU:这款CPU采用22纳米制程工艺的框架,它的默认频率是4.0到4.4Ghz...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
