当前位置: 首页 > news >正文

Python 封装与属性:类的“防护罩”和“智能门禁”

目录

📖 前言

第一章:封装 —— 类的“防护罩”

1.1 封装的本质

1.2 三种级别的直观对比

1.3 为什么要有封装?

第二章:属性(@property)—— 让方法“装”成数据

2.1 为什么要用属性?

2.2 @property + @xxx.setter 的基本用法

2.3 用 property() 函数的写法(对标你图中的代码)

2.4 属性封装的四个内置函数

🎯 一张图总结

🧁 结尾


📖 前言

面向对象有三大特性:封装、继承、多态。继承我们讲过了,今天聊另外两个合在一起的东西——封装属性

封装,就是把数据“藏”起来,不让外面随便改。

属性,就是给封装开一扇“智能门”——外面看起来像在直接访问数据,其实背后偷偷走了你写的校验逻辑。

这俩加在一起,既保安全,又保好用。let us show !🛡️


第一章:封装 —— 类的“防护罩”

1.1 封装的本质

封装就是把类的内部数据藏好,只暴露必要的东西出去。

Python 里没有真正的“私有”,全靠命名约定来示意访问级别:

写法级别访问范围
self.name公有(public)任何地方都能访问
self._age保护(protected)类内和子类用,类外“不建议”用
self.__gender私有(private)只能在类内访问,外面访问会报错

1.2 三种级别的直观对比

看代码最清楚:

python

class Person: def __init__(self, name, age, gender): self.name = name # ✅ 公有:谁都能访问 self._age = age # ⚠️ 保护:类内和子类用,外面别碰 self.__gender = gender # 🔒 私有:只有类内能访问 def get_name(self): return self.name # ✅ 类内访问公有 def _get_age(self): return self._age # ⚠️ 类内访问保护 def __get_gender(self): return self.__gender # 🔒 类内访问私有(可以) def show(self): # 类内:三种都能访问 print(self.name, self._age, self.__gender) class SuperPerson(Person): def show_sub(self): print(self.name) # ✅ 子类可以访问父类的公有 print(self._age) # ⚠️ 子类可以访问父类的保护 # print(self.__gender) # ❌ 子类访问不了父类的私有! # 测试 p = Person("张三", 30, "male") # 类外访问 print(p.name) # ✅ 张三(公有,随便看) print(p._age) # ⚠️ 30(保护,能看但最好别) # print(p.__gender) # ❌ AttributeError(私有,外面看不见) # 子类测试 sp = SuperPerson("李四", 25, "female") sp.show_sub() # 能访问 name 和 _age,但访问不了 __gender

📌一句话记死:单下划线_是“约定”:请尊重我,别在外面碰我;双下划线__是“强制”:Python 把它改名了,外面确实找不到。

1.3 为什么要有封装?

  1. 保护数据—— 不让外面乱改关键数据

  2. 控制访问—— 只暴露必要的方法,隐藏内部实现

  3. 降低耦合—— 改里面不影响外面调用的代码

第二章:属性(@property)—— 让方法“装”成数据

2.1 为什么要用属性?

有时候你想在别人“取数据”或“改数据”的时候偷偷干点别的事——比如校验输入、打日志、触发更新。但你不想让调用者感受到“我是在调用方法”,希望他们觉得“我就是在直接访问一个数据”。

@property就是干这个的——把方法伪装成属性。

2.2@property+@xxx.setter的基本用法

python

class Person: def __init__(self, name, age): self.__name = name # 私有属性(双下划线,不让外面直接碰) self.__age = age # 获取属性:用 @property 装饰,调用时不用加括号 @property def name(self): print("执行了获取函数") return self.__name # 设置属性:用 @属性名.setter 装饰 @name.setter def name(self, value): print("执行了设置函数") if 2 <= len(value) <= 4: self.__name = value else: print("名字长度不合法,请保持在 2-4 个字符") @property def age(self): return self.__age @age.setter def age(self, value): if 0 <= value <= 100: self.__age = value else: print("年纪不合法,请保持在 0-100 之间") # 使用——看起来像在直接读写数据,其实背后走了校验逻辑 p = Person("张三", 20) print(p.name) # "执行了获取函数" → "张三" p.name = "李四" # 执行了设置函数(合法,会改) p.name = "jleakogieskg" # 不合法 → 名字长度不合法,不改 p.age = -66 # 年纪不合法,不改

📌语法关键点

  • 上面:@property负责“取值”(类似getter

  • 下面:@age.setter负责“赋值”(类似setter

  • 名字必须一致,@property的方法名 =@xxx.setterxxx

2.3 用property()函数的写法(对标你图中的代码)

除了装饰器,还有另一种写法——用property()函数把 getter 和 setter 绑到一起:

python

class Person: def __init__(self, name, age): self.__name = name self.__age = age # getter def __get_name(self): print("执行了获取函数") return self.__name # setter def __set_name(self, name): print("执行了设置函数") if 2 <= len(name) <= 4: self.__name = name else: print("名字长度不合法") def __get_age(self): return self.__age def __set_age(self, age): if 0 <= age <= 100: self.__age = age else: print("年纪不合法") # 用 property() 函数把 getter 和 setter 绑定成属性 name = property(fget=__get_name, fset=__set_name) age = property(fget=__get_age, fset=__set_age) p = Person("张三", 20) print(p.name) # 执行了获取函数 → 张三 p.name = "李四" # 执行了设置函数

💡property(fget=..., fset=...)是装饰器写法的手动版。两种写法都能用,装饰器写法更常用,因为代码更直观、更简洁。

2.4 属性封装的四个内置函数

Python 提供了四个内置函数,方便你动态操作对象的属性:

python

class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("张三", 20) # hasattr:检查有没有这个属性 print(hasattr(p, "name")) # True print(hasattr(p, "salary")) # False # getattr:获取属性值(找不到可以给默认值) print(getattr(p, "name")) # 张三 print(getattr(p, "salary", 0)) # 0(找不到,返回默认值) # setattr:设置属性值 setattr(p, "name", "李四") print(p.name) # 李四 # delattr:删除属性 delattr(p, "age") # print(p.age) # ❌ AttributeError,已经被删了

🎯 一张图总结

text

封装:把数据藏起来,分三级权限 ── 公有(name) → 谁都能访问 ── 保护(_name) → 别在外面碰我(约定) ── 私有(__name) → 只有类内能访问(强制改名) 属性:让方法伪装成数据 ── @property → 给“取值”加一层 ── @xxx.setter → 给“赋值”加一层(可加校验) ── 效果:p.name 像数据,背后却能走校验逻辑 四个内置函数:hasattr / getattr / setattr / delattr

🧁 结尾

到今天为止,封装和属性你就拿下了:

封装—— 控制“谁能看到什么”,把数据藏好,只露该露的。

属性—— 给数据访问加“智能门禁”,外面看起来像直接读/写,背后帮你做校验、打日志、触发更新。

http://www.jsqmd.com/news/1370433/

相关文章:

  • A2UI:让AI Agent自动生成可交互界面的技术架构与实现
  • SpringBoot+Vue3宠物领养系统:全栈开发实战与毕设项目指南
  • 电竞比赛技术复盘:从BP策略到团战决策的系统性分析方法
  • 警惕技术债务清理中的虚假完成率:从状态变更到真实问题解决
  • AI 时代工程师的成长:把能力拆回可练习的工作
  • UVM验证中get_type_name、get_name与get_full_name的区别与应用详解
  • 蓝桥杯“甘蔗”题解析:区间DP与哈夫曼模型在最优切割问题中的应用
  • 朝花夕拾 · C语言 | 位运算篇
  • C++ noexcept操作符7大实战场景:从编译期检查到性能优化
  • 企业数字化转型中的数据埋点与异常检测实践
  • 大学生应该要考的证书有哪些?2026高质量考证指南与就业避坑建议
  • Unity画面优化利器:UniversalUnityDemosaics插件原理与实战指南
  • 广东热门的CNC精密加工厂家推荐指南银辰精密(广东销售中心) - 品牌优推
  • Unity打砖块游戏开发实战:从物理碰撞到对象池优化
  • Windows用户文件夹重命名:从原理到实践的安全操作指南
  • 2026 年至今,崇安诚信的冷库板回收施工公司推荐,用它换钱能省十几万?不少冷库老板还在当废品卖 - 行业严选官
  • Visual Studio 2022离线安装全攻略:内网环境部署与模块化布局实战
  • DIFI学习-入门之workflow
  • AI模型硬件化:从软件部署到芯片固化的技术演进与应用前景
  • 西施浣纱袜业:世界袜都年产超250亿双,为什么还需要一个……
  • 5分钟搞定GTNH汉化:让百万字模组包变中文的完整指南
  • 2026年度江苏AI超级公司系统怎么选?
  • 链表数据结构:核心操作与工程实践优化
  • 乐陵市瓷砖空鼓维修上门推荐_2026山东半岛价格行情与价格表_卫生间厨房墙砖阳台地砖客厅 - 雨婺虹修缮
  • 大规模数据迁移的故障演练:复盘应留下什么
  • 《Python 封装不是“锁门”,而是“贴标签”!深入 property、伪私有与 slots 的哲学》
  • C# OPC UA服务器开发实战:从协议原理到工业数据采集实现
  • C++ explicit关键字:从隐式转换陷阱到类型安全编程实践
  • 【内燃机】模拟六冲程内燃机(提供详细的热力学建模和动态可视化)【含Matlab源码 15925期】
  • Unity渐变着色器资源包:原理、应用与性能优化全解析