Python面向对象进阶:__slots__、@property、枚举类、元类到底是什么?一篇彻底讲明白!(小白必看) (六.1)

Python面向对象进阶:__slots__、@property、枚举类、元类到底是什么?一篇彻底讲明白!(小白必看) (六.1)
目录一、__slots__为什么对象可以随便增加属性1.1 __slots__ 怎么使用1.2 用生活中的例子理解 __slots__1.3 __slots__ 还能节省内存1.4 __slots__ 有没有缺点1.5 __slots__ 需要注意的一点本节小结二、property为什么别人家的属性既安全用起来还像普通变量2.1 为什么不能让别人直接修改属性2.2 第一种解决方案使用 get 和 set 方法2.3 property 到底是什么2.4 property 到底做了什么2.5 property 可以理解成门卫2.6 为什么还要写 score.setter2.7 实际开发中为什么喜欢用 property本节小结本章节篇幅较多后续‘枚举类、元类’等内容可在 六.2 章节进行阅读学习感谢您的点赞关注和收藏前面的几篇文章我们已经学习了 Python 面向对象编程的基础知识例如类Class对象Object属性和方法继承多态相信大家已经能够写出一个简单的类了例如class Student: def __init__(self, name, age): self.name name self.age age def introduce(self): print(f大家好我叫{self.name}今年{self.age}岁。)创建对象s Student(张三,18) s.introduce()输出大家好我叫张三今年18岁。是不是已经有点像那么回事了但是如果你真正开始写项目很快就会发现新的问题。例如为什么对象可以随便增加属性怎样才能保证数据不会被别人乱改为什么别人写的对象还能直接使用len()、print()为什么有些类还能同时继承多个父类元类到底是什么网上教程为什么越看越迷糊别着急今天这篇文章我们继续学习 Python 面向对象编程中的几个进阶知识。虽然名字看起来有点高深但实际上每一个知识点都是为了解决实际开发中的问题。理解了它们你写出来的代码会更加规范也更接近真正的 Python 开发方式。一、__slots__为什么对象可以随便增加属性先来看一个非常神奇的现象上一篇文章我们创建过一个学生类class Student: pass注意这个类里面什么都没有。现在创建对象s Student()接下来我们给它添加一个属性s.name 张三打印一下print(s.name)输出张三没有任何问题继续添加s.age 18 s.score 98 s.address 北京 s.phone 123456789再次运行依然没有报错。很多小白第一次看到这里都会觉得Python 这么随意的吗没错Python 的对象就是这么自由。你想什么时候增加属性就什么时候增加。甚至s.game 王者荣耀 s.favorite_food 火锅都没有问题。自由虽然爽但问题也来了来看下面这段代码class Student: pass s Student() s.name 张三 print(s.name)没有问题但是如果哪天手滑了写成s.nmae 张三注意这里不是name而是nmae很多语言会直接报错但是 Python 不会因为 Python 认为哦你不是写错了。你只是新增了一个叫nmae的属性。于是对象里面真的多了一个nmae程序还能继续运行结果等你调试两个小时以后才发现原来只是拼错了一个字母……相信很多 Python 程序员都经历过这种社死现场。那怎么办如果一个对象只能拥有固定几个属性是不是就不会出现这种问题了答案就是__slots__它的作用只有一句话限制对象能够拥有哪些属性。1.1 __slots__怎么使用例如class Student: __slots__ (name, age)这里只有两个属性nameage创建对象s Student()赋值s.name 张三 s.age 18都没有问题但是如果继续s.score 100程序会直接报错AttributeError意思就是对不起。score 不允许存在。为什么会报错因为__slots__ (name,age)已经提前告诉 Python这个类以后只能拥有name age除此之外任何新的属性统统不允许这样一来如果你再写s.nmae 张三程序会立刻报错你马上就知道~哦原来我拼写错了而不是等程序运行半天以后才发现。1.2 用生活中的例子理解__slots__假设学校发给你一张学生信息登记表上面只有几个栏目姓名 年龄 班级老师说只能填写这些。结果你在下面又写了游戏段位 微博账号 外卖地址老师肯定会说同学这不是你自由发挥的时候。表格上没有这一栏。__slots__就相当于这张固定格式的表格。它规定了哪些信息可以填写。哪些信息不能填写。1.3 __slots__还能节省内存除了限制属性之外__slots__还有一个优点。节省内存。为什么因为普通对象会专门留出一块空间。记录我有哪些属性如果对象很多如100万个对象这些记录也会占用不少内存而__slots__提前告诉 Python属性只有这几个。Python 就不用再额外记录所以会节省一些内存。当然对于刚开始学习 Python 的同学来说这一点了解即可。真正写大型项目的时候你才会真正体会到它的优势。1.4 __slots__有没有缺点当然有最大的缺点就是不够灵活。例如以前你可以随时增加属性s.score 98现在不行了如果以后需求变化又想增加score怎么办只能修改__slots__ (name,age,score)重新定义。所以__slots__并不是所有类都要使用。它更适合那些属性固定、不会频繁变化的类。例如身份证信息商品信息配置信息这些数据通常比较固定使用__slots__会更加规范。1.5 __slots__需要注意的一点还有一个容易踩坑的地方来看下面的代码class Student: __slots__ (name,) class GoodStudent(Student): pass创建子类对象g GoodStudent() g.name 张三 g.score 100很多同学会以为这里会报错。其实不会为什么因为__slots__默认只对当前类生效。子类如果没有定义__slots__依然可以动态添加新的属性。如果希望子类也受到限制就需要在子类中继续定义__slots__。这一点初学者记住即可真正开发中遇到再深入研究也不迟。本节小结今天我们学习了一个新的知识点__slots__它主要有两个作用限制对象能够拥有的属性。节省对象占用的内存。对于初学者来说只需要记住一句话__slots__就像给对象制定了一份属性名单名单之外的属性一律不允许添加。理解这一点以后看到别人代码里的__slots__就不会再觉得神秘了。二、property为什么别人家的属性既安全用起来还像普通变量上一篇文章我们学过私有属性。例如class Student: def __init__(self): self.__score 0这里的__score就是一个私有属性外部不能直接访问s Student() print(s.__score)运行后会报错AttributeError很多小伙伴看到这里可能会想那我以后怎么查看成绩总不能创建了一个对象里面的数据自己都看不到吧当然不是。Python 给我们提供了一种更加安全的方法。2.1 为什么不能让别人直接修改属性假设你正在开发一个学生管理系统每个学生都有一个成绩。最简单的写法就是class Student: def __init__(self): self.score 0创建对象s Student()修改成绩s.score 95没有任何问题但是……如果有人这样写呢s.score -100或者s.score 999程序同样不会报错可是现实中考试成绩怎么可能是-100分或者999分这明显是不合理的所以我们需要一种办法在修改数据之前先检查数据是否合法。2.2 第一种解决方案使用 get 和 set 方法很多编程语言都会采用这种方式例如class Student: def __init__(self): self.__score 0 def set_score(self, score): if 0 score 100: self.__score score else: print(成绩必须在0~100之间) def get_score(self): return self.__score创建对象s Student()修改成绩s.set_score(95)查看成绩print(s.get_score())输出95如果输入s.set_score(200)输出成绩必须在0~100之间是不是安全多了因为所有的数据都必须经过set_score()这个方法只有检查通过才能真正修改。但是这种写法有一个缺点大家有没有觉得这样写有点麻烦以前s.score 95一句话搞定。现在变成s.set_score(95)读取又变成s.get_score()每次都要get... set...写多了也挺累于是 Python 想有没有办法既能保证安全又能让代码看起来像普通属性答案就是property2.3 property 到底是什么一句话理解它可以把一个方法伪装成一个普通属性。是不是有点绕没关系直接看代码。class Student: def __init__(self): self.__score 0 property def score(self): return self.__score score.setter def score(self, value): if 0 value 100: self.__score value else: print(成绩必须在0~100之间)创建对象s Student()修改成绩s.score 90读取成绩print(s.score)输出90有没有发现代码看起来和普通属性一模一样。但是实际上Python 已经偷偷帮我们完成了数据检查。2.4 property 到底做了什么很多小白第一次学习这里都会觉得我明明写的是s.score 90为什么会执行def score(self, value):其实执行流程是这样的s.score 90 ↓ Python发现score有property ↓ 自动调用setter方法 ↓ 检查数据是否合法 ↓ 合法才真正修改所以你以为自己修改的是属性。实际上修改的是一个方法是不是有点神奇2.5 property 可以理解成门卫假设有一个小区居民想进入。看起来都是直接走进去。实际上门口一直站着一个保安。流程是居民 ↓ 保安检查 ↓ 身份正常 ↓ 放行如果身份异常居民 ↓ 保安 ↓ 拦住property 就像这个保安你觉得自己是在直接访问score实际上Python 已经偷偷帮你检查了一遍。2.6 为什么还要写 score.setter很多同学又有疑问为什么不是property一个就够了原因很简单。读取和修改是两件不同的事情。例如查看成绩print(s.score)Python 会调用property def score(self):返回成绩。而s.score 90Python 会调用score.setter修改成绩。所以一个负责读取。一个负责修改。分工明确。还能创建只读属性有时候我们希望别人只能查看不能修改。例如学生学号。身份证号码。订单编号。这些数据创建以后一般不会修改那么只写property即可。例如class Student: def __init__(self): self.__id 20250001 property def student_id(self): return self.__id读取print(s.student_id)可以但是s.student_id 8888程序会直接报错因为没有student_id.setter所以这个属性就是只读属性。2.7 实际开发中为什么喜欢用 property因为它同时拥有两个优点。第一使用方便代码像普通变量一样s.score 95第二数据安全程序内部已经偷偷完成检查。所以现在很多 Python 框架都会大量使用property你以后阅读别人代码的时候几乎天天都会遇见它。本节小结这一节我们学习了 Python 中一个非常重要的知识点property它最大的作用就是让方法拥有属性一样的使用方式。简单来说property负责获取属性值。xxx.setter负责修改属性值。可以在修改数据时进行合法性检查。如果不写setter属性就是只读的。对于初学者来说只需要记住一句话property的本质并不是普通属性而是把方法包装成了属性让代码既优雅又安全。本章节篇幅较多后续‘枚举类、元类’等内容可在 六.2 章节进行阅读学习感谢您的点赞关注和收藏