小型网站商城建设,网站源码路径,西班牙网站后缀,WordPress模板申报功能下载功能OOP-封装、继承、多态 本章学习知识点 封装#xff1a;私有成员#xff08;__xxx#xff09;、属性访问器#xff08;property/setter#xff09;、最小暴露原则继承#xff1a;单继承、多继承#xff08;MRO 方法解析顺序#xff09;、子类派生 / 方法重写、super () …OOP-封装、继承、多态本章学习知识点封装私有成员__xxx、属性访问器property/setter、最小暴露原则继承单继承、多继承MRO 方法解析顺序、子类派生 / 方法重写、super () 调用多态继承重写、统一接口调用、抽象基类abc 模块、开闭原则一、OOP 三大核心特性封装、继承、多态是面向对象编程的核心支柱三者形成 “基础 - 复用 - 扩展” 的闭环封装 构建模块化的代码单元保障数据安全继承 实现代码复用与分层设计减少重复逻辑多态 则在统一接口下支持灵活的功能扩展最终达成 “高内聚、低耦合” 的代码设计目标。特性核心目标核心价值落地关键封装隐藏内部实现暴露安全接口保护数据安全、降低外部依赖、简化使用私有化成员、getter/setter、接口收敛继承复用已有逻辑扩展新功能减少重复代码、构建类的层级关系父类提取共性、子类派生扩展、super () 调用多态统一接口不同实现解耦调用与实现、提升代码扩展性父类定义接口、子类重写方法、抽象基类约束1.1、封装封装是将对象的属性和方法包裹在类的边界内对外隐藏复杂的内部实现仅提供经过设计的公开接口供外部访问。核心是 “对内开放、对外约束”既保证数据安全又降低外部使用的复杂度。封装的核心逻辑隐藏封通过语法规则限制外部对内部成员的直接访问避免非法操作整合装将属性数据和方法行为封装为统一的逻辑单元形成独立的名称空间接口化用对外暴露简洁、稳定的接口内部实现可自由修改而不影响外部调用。1.1.1、私有成员(__xxx)Python 通过 “双下划线前缀__” 实现成员私有化本质是名称修饰非严格私有私有成员仅能在类内部访问外部需通过公开接口操作。示例class User: def __init__(self, username, password): self.usernameusername# 公有属性对外可见self.__passwordpassword# 私有属性仅类内部访问# 私有方法封装加密逻辑外部无需感知def __encrypt_pwd(self,pwd):returnpwd_salt# 模拟加盐加密# 公开接口验证密码封装核心逻辑对外提供安全操作def verify_password(self, input_pwd): encrypted_inputself.__encrypt_pwd(input_pwd)returnencrypted_inputself.__encrypt_pwd(self.__password)# 实例化与调用userUser(zhangsan,123456)print(user.username)# 公有属性可直接访问zhangsanprint(user.verify_password(123456))# 通过接口验证True# print(user.__password) # 直接访问私有属性报错AttributeError# print(user.__encrypt_pwd(123)) # 直接调用私有方法报错AttributeError# 【原理说明】名称修饰规则__xxx → _类名__xxx不推荐外部使用破坏封装print(user._User__password)# 强制访问私有属性仅作原理说明禁止实际使用1.1.2、属性访问器(getter/setter)对于需要外部访问的私有属性推荐使用propertygetter和属性名.settersetter封装在方法中添加数据校验、格式转换等逻辑保证数据合法性。示例classStudent:def__init__(self,name,age):self.namename self.__ageage# 私有年龄属性需校验范围# getter读取属性无需加()像访问普通属性一样使用propertydefage(self):returnself.__age# setter修改属性直接赋值自动触发校验age.setterdefage(self,new_age):ifnotisinstance(new_age,int):raiseTypeError(年龄必须是整数)if0new_age120:self.__agenew_ageelse:raiseValueError(年龄必须在0-120之间)# 调用示例stuStudent(小明,18)print(stu.age)# 读取18stu.age20# 修改合法值print(stu.age)# 输出20# stu.age 150 # 非法值触发ValueError# stu.age 20 # 非法类型触发TypeErrors1Student(Bob,1111)# 如果是直接赋值则不会抛异常1.1.3、封装设计原则最小暴露原则仅暴露必要的接口非核心逻辑全部私有化接口稳定原则公开接口的命名和参数尽量稳定内部实现可灵活调整数据校验原则所有外部传入的数据必须在接口中完成合法性校验。1.2、继承与派生继承是让一个类子类 / 派生类复用另一个类父类 / 基类的属性和方法子类可在父类基础上新增属性、重写方法实现 “共性抽取、个性扩展”。Python 支持单继承和多继承推荐以单继承为主多继承仅用于整合独立功能。1.2.1、基本概念父类 / 基类提供共性功能的类如 “动物类”查看父类通过类名.__bases__查看子类的父类列表继承语法class 子类名(父类1, 父类2, ...):Python 支持多继承新式类与经典类Python3 中所有类默认继承object新式类采用 “广度优先” 查找规则Python2 中未继承object的是经典类采用 “深度优先”实际开发均用新式类以经典的 “菱形继承”为例A / \ B C \ / DD 继承 B 和 CB、C 又都继承 A。此时 D 调用 A 的方法该先找 B→A 还是 C→A早期 Python 经典类用 “深度优先”D→B→A→C会跳过 C 的重写新式类用 C3 算法D→B→C→A既保证子类优先又避免跳过中间类更合理。子类 / 派生类继承并扩展父类的类如 “狗类”“猫类”派生子类新增属性 / 方法、重写父类方法的过程MRO方法解析顺序多继承时Python 查找方法的优先级规则C3 线性化算法。(C3 算法的核心规则)C3 算法生成 MRO 列表时遵循 3 个核心原则优先级从高到低子类优先于父类先查子类自己再查父类父类声明顺序优先子类定义时写在前面的父类查找时也优先保持父类自身的 MRO 顺序每个父类的查找顺序不能被打乱。1.2.2、单继承单继承是最易维护的继承方式适合构建 “通用→特殊” 的层级关系。# 父类抽取所有动物的共性classAnimal:def__init__(self,name,color):self.namename self.colorcolordefeat(self):print(f{self.color}的{self.name}正在进食)# 子类狗类继承派生classDog(Animal):def__init__(self,name,color,breed):# 复用父类初始化逻辑推荐super()适配继承体系super().__init__(name,color)self.breedbreed# 新增子类独有属性品种defbark(self):print(f{self.breed}{self.name}在汪汪叫)# 新增子类独有方法defeat(self):# 重写父类方法保留父类逻辑扩展super().eat()print(f{self.name}专吃骨头)# 子类个性化逻辑# 调用示例dogDog(旺财,黄色,中华田园犬)dog.eat()# 输出黄色的旺财正在进食 → 旺财专吃骨头dog.bark()# 输出中华田园犬 旺财在汪汪叫子类调用父类方法的两种方式方式语法适用场景优点缺点super()super().方法名(参数)单继承 / 多继承适配 MRO 顺序无需硬编码父类名依赖继承顺序直接调用父类名.方法名(self, 参数)多继承精准调用不依赖继承顺序精准指定父类硬编码父类名耦合度高通过「父类名」直接调用通用支持多继承classParent:def__init__(self):print(父类初始化方法)classChild(Parent):def__init__(self):# 第一步调用父类的__init__手动传selfParent.__init__(self)# 第二步执行子类自己的初始化逻辑print(子类初始化方法)c1Child()# 输出顺序# 父类初始化方法# 子类初始化方法通过super()调用推荐适配 MRO 顺序classParent:def__init__(self):print(父类初始化方法)classChild(Parent):def__init__(self):# 第一步调用父类的__init__无需传selfsuper自动处理super().__init__()# 第二步执行子类自己的初始化逻辑print(子类初始化方法)c1Child()# 输出和方式1一致# 父类初始化方法# 子类初始化方法如果两种都不写 -- 异常说明classParent:def__init__(self):print(父类初始化方法)classChild(Parent):def__init__(self):print(子类初始化方法)c1Child()c1.Parent()c1是Child的实例它的属性只有Child类中通过self.xxx绑定的内容没有Parent这个属性若强行想通过实例访问父类正确的方式是先通过type(c1).__bases__拿到父类再调用但实际开发中绝对不推荐c1Child()# 错误写法# c1.Parent.__init__() # 直接报错Child object has no attribute Parent# 强行通过实例找父类并调用仅作原理演示禁止实际使用ParentClasstype(c1).__bases__[0]# 拿到Child的第一个父类ParentParentClass.__init__(c1)# 手动传实例c1调用父类__init__# 输出父类初始化方法两种加上函数classPar:def__init__(self,name):self.namenamedefshow(self):print(父类属性,self.name)classChild(Par):def__init__(self,name):# 复用父类初始化逻辑super().__init__(name)defshow(self):# super()调用推荐Par.show(self)print(子类属性,self.name)c1Child(子类)c1.show()# 父类属性 子类# 子类属性 子类总结写法是否正确适用场景Parent.__init__(self)✅ 正确单 / 多继承需精准调用指定父类super().__init__()✅ 正确推荐单继承或按 MRO 顺序调用父类c1.Parent.__init__()❌ 错误无适用场景实例无 Parent 属性type(c1).__bases__[0].__init__(c1)✅ 语法正确但不推荐仅原理演示实际开发禁止使用1.2.3、多继承与 MRO 顺序多继承允许子类整合多个父类的功能但易引发方法冲突需通过 MRO 规则解决采用 C3 线性化算法。多继承基础示例# 父类1飞行能力classFlyable:deffly(self):print(拥有飞行能力)# 父类2游泳能力classSwimmable:defswim(self):print(拥有游泳能力)# 子类鸭子类继承飞行游泳能力classDuck(Flyable,Swimmable):def__init__(self,name):self.namename# 测试# 查看MRO顺序子类→父类1→父类2→objectprint(Duck.mro())# 输出[class __main__.Duck, class __main__.Flyable, class __main__.Swimmable, class object]duckDuck(小黄鸭)duck.fly()# 输出拥有飞行能力duck.swim()# 输出拥有游泳能力MRO 核心规则与查看方式核心规则子类优先于父类、先继承的父类优先于后继承的父类、每个类仅被查找一次查看 MRO通过类名.__mro__或类名.mro()查看返回的元组/列表即为方法查找顺序。示例MRO 解决同名方法冲突# 父类1AclassA:defshow(self):print(A类的show方法)# 父类2B继承AclassB(A):defshow(self):print(B类的show方法)# 父类3C继承AclassC(A):defshow(self):print(C类的show方法)# 子类D继承B、CclassD(B,C):pass# 查看MRO顺序print(D.mro())# 输出[class __main__.D, class __main__.B, class __main__.C, class __main__.A, class object]# 调用show方法按MRO顺序查找优先B类dD()d.show()# 输出B类的show方法# 子类重写后优先调用自身classD(B,C):defshow(self):print(D类的show方法)d2D()d2.show()# 输出D类的show方法菱形继承与多继承建议菱形继承子类继承多个父类且多个父类最终继承同一个基类如所有类最终继承object此时 MRO 顺序尤为重要。多继承使用建议尽量避免「多层多继承」复杂度高且易出现逻辑冲突若需整合多个独立功能如飞行游泳优先使用「组合」而非多继承多继承场景下务必通过类.mro()确认方法查找顺序避免同名方法冲突。1.3、多态多态是指 “不同子类继承同一父类后重写父类同名方法使得同一接口调用能适配不同子类的实现”。核心是 “接口统一实现各异”大幅提升代码的可扩展性。多态的核心要素存在继承关系子类继承同一父类子类重写父类的同名方法外部通过父类接口调用无需区分具体子类类型多态实战案例统一接口实现不同功能以“计算不同形状的面积”为例通过多态实现“统一调用接口自动适配不同形状”。# 父类形状类定义统一接口classShape:# 统一接口计算面积子类必须重写否则报错defcalculate_area(self):raiseNotImplementedError(子类必须重写calculate_area方法)# 子类1圆形重写面积计算方法classCircle(Shape):def__init__(self,radius):self.radiusradius# 圆形独有属性半径defcalculate_area(self):importmathreturnmath.pi*self.radius**2# 圆形面积公式# 子类2矩形重写面积计算方法classRectangle(Shape):def__init__(self,length,width):self.lengthlength# 矩形独有属性长self.widthwidth# 矩形独有属性宽defcalculate_area(self):returnself.length*self.width# 矩形面积公式# 子类3三角形重写面积计算方法classTriangle(Shape):def__init__(self,base,height):self.basebase# 三角形独有属性底self.heightheight# 三角形独有属性高defcalculate_area(self):return0.5*self.base*self.height# 三角形面积公式# 统一调用函数多态核心无需区分对象类型调用统一接口defprint_area(shape):ifisinstance(shape,Shape):print(f{shape.__class__.__name__}的面积为{shape.calculate_area():.2f})else:print(传入的不是Shape子类对象)# 测试多态性circleCircle(5)rectangleRectangle(4,6)triangleTriangle(3,8)print_area(circle)# 输出Circle的面积为78.54print_area(rectangle)# 输出Rectangle的面积为24.00print_area(triangle)# 输出Triangle的面积为12.00# 扩展新增正方形类无需修改print_area函数classSquare(Shape):def__init__(self,side):self.sidesidedefcalculate_area(self):returnself.side**2squareSquare(5)print_area(square)# 输出Square的面积为25.00多态的标准化实现抽象基类ABC通过abc模块定义抽象基类可强制子类实现指定方法保证接口统一适合团队开发 / 框架设计。importabc# 抽象基类定义文件读取的统一标准无法实例化classFileReader(metaclassabc.ABCMeta):abc.abstractmethod# 抽象方法子类必须实现defread(self):pass# 子类1文本文件读取器classTxtReader(FileReader):def__init__(self,file_path):self.file_pathfile_pathdefread(self):print(f读取文本文件{self.file_path}格式UTF-8)# 子类2Excel文件读取器classExcelReader(FileReader):def__init__(self,file_path):self.file_pathfile_pathdefread(self):print(f读取Excel文件{self.file_path}格式xlsx)# 子类3未实现抽象方法实例化报错# class PdfReader(FileReader):# pass# pdf PdfReader(test.pdf) # TypeError: Cant instantiate abstract class PdfReader with abstract method read# 统一调用接口defread_file(reader):ifisinstance(reader,FileReader):reader.read()# 测试txt_readerTxtReader(data.txt)excel_readerExcelReader(data.xlsx)read_file(txt_reader)# 输出读取文本文件data.txt格式UTF-8read_file(excel_reader)# 输出读取Excel文件data.xlsx格式xlsx多态设计价值解耦调用者只需关注接口无需关注具体实现扩展新增功能仅需新增子类无需修改原有调用逻辑开闭原则统一通过抽象基类强制接口规范降低团队协作成本。二、特性整合总结特性说明特性核心思想典型应用场景避坑要点封装隐藏细节暴露接口数据校验、权限控制、复杂逻辑封装避免过度封装接口不宜过多继承抽取共性扩展个性类的层级设计、基础功能复用避免多层多继承优先 super () 调用多态接口统一实现各异通用功能适配、插件化扩展依赖抽象接口而非具体实现三者协同设计示例# 1. 基类定义统一接口所有用户的共性classUser:def__init__(self,name):self.namename# 公有属性用户名# 统一接口operate子类必须重写体现多态核心defoperate(self):raiseNotImplementedError(子类必须实现operate方法)# 2. 子类1管理员重写operate方法classAdmin(User):defoperate(self):print(f{self.name}执行管理员操作)# 3. 子类2普通用户重写operate方法classNormalUser(User):defoperate(self):print(f{self.name}执行普通用户操作)# 4. 多态核心统一调用函数面向父类接口defexecute_operation(user:User):user.operate()# 5. 调用示例execute_operation(Admin(管理员))# 输出管理员执行管理员操作execute_operation(NormalUser(用户))# 输出用户执行普通用户操作######################### 也可以写成 但需要人工判断是否在这个接口中defprit_user_role(user):ifisinstance(user,User):user.operate()else:print(未被定义的用户角色)a1Admin(admin)a2NormalUser(normal)prit_user_role(a1,Admin)prit_user_role(a2,NormalUser)解析一下组合def execute_operation(user: User):—— 类型注解user: User是 Python 的类型注解Type Hint作用是提示开发者这个函数的user参数期望接收User类或其子类的实例辅助 IDE如 PyCharm做语法检查避免传错类型但 Python 运行时不会强制校验只是 “提示”核心意义明确函数的入参接口 —— 只要是User子类的实例都能传入体现 “统一接口” 的设计。user.operate()—— 调用统一接口多态的核心执行逻辑这里的user是函数接收的参数它本质是User子类Admin/NormalUser的实例调用user.operate()时Python 会根据user的实际类型自动调用对应子类的operate方法当传入Admin(管理员)时user是Admin实例调用Admin.operate()当传入NormalUser(用户)时user是NormalUser实例调用NormalUser.operate()这就是多态的核心同一个接口operate()不同实例表现出不同行为。