ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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 三种级别的直观对比看代码最清楚pythonclass 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 为什么要有封装保护数据—— 不让外面乱改关键数据控制访问—— 只暴露必要的方法隐藏内部实现降低耦合—— 改里面不影响外面调用的代码第二章属性property—— 让方法“装”成数据2.1 为什么要用属性有时候你想在别人“取数据”或“改数据”的时候偷偷干点别的事——比如校验输入、打日志、触发更新。但你不想让调用者感受到“我是在调用方法”希望他们觉得“我就是在直接访问一个数据”。property就是干这个的——把方法伪装成属性。2.2propertyxxx.setter的基本用法pythonclass 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.setter的xxx2.3 用property()函数的写法对标你图中的代码除了装饰器还有另一种写法——用property()函数把 getter 和 setter 绑到一起pythonclass 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 提供了四个内置函数方便你动态操作对象的属性pythonclass 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 结尾到今天为止封装和属性你就拿下了封装—— 控制“谁能看到什么”把数据藏好只露该露的。属性—— 给数据访问加“智能门禁”外面看起来像直接读/写背后帮你做校验、打日志、触发更新。
返回列表