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

Python Day15 面向对象核心特性笔记 及 例题分析

一、运算符重载

运算符重载允许自定义类的对象支持算术运算、比较运算等,通过重写对应的魔术方法实现。

1. 算术运算符重载

运算符对应魔术方法说明
+__add__加法
-__sub__减法
*__mul__乘法
/__truediv__真除法(返回浮点数)
//__floordiv__整除(返回整数)
%__mod__取模(取余数)
**__pow__幂运算

示例(Cat 类算术运算)

class Cat:def __init__(self, name, age):self.name = nameself.age = agedef __add__(self, other):  # 加法return self.age + other.agedef __sub__(self, other):  # 减法return self.age - other.age# 其他算术方法省略...

2. 关系运算符重载

运算符对应魔术方法说明
>__gt__大于
>=__ge__大于等于
<__lt__小于
<=__le__小于等于
==__eq__等于
!=__ne__不等于

示例(Cat 类比较运算)

def __gt__(self, other):if not isinstance(other, self.__class__):raise TypeError(f'{other} 必须是Cat类型')return self.age > other.agedef __ge__(self, other):# 实现大于等于逻辑return self.age >= other.age

二、可迭代对象与迭代器

可迭代对象和迭代器用于表示多值集合,支持for...in循环遍历。

1. 可迭代对象

需满足两个条件:

  • 能表示多值
  • 支持len()函数获取长度

需实现的魔术方法:

  • __len__:返回元素数量
  • __iter__:返回迭代器对象(可通过生成器或iter()转换实现)

示例(Array 类)

class Array:def __init__(self):self.lst = []def add(self, val):self.lst.append(val)def __len__(self):return len(self.lst)def __iter__(self):# 生成器方式返回迭代器for x in self.lst:yield x

2. 迭代器

迭代器是可迭代对象的具体实现,支持逐个获取元素。

需实现的魔术方法:

  • __iter__:返回自身(迭代器本身也是可迭代对象)
  • __next__:返回下一个元素,无元素时抛出StopIteration

示例(C 类迭代器)

class C:def __init__(self):self.lst = []def add(self, val):self.lst.append(val)def __iter__(self):return self  # 返回自身作为迭代器def __next__(self):if len(self.lst) == 0:raise StopIterationreturn self.lst.pop(0)  # 弹出第一个元素

三、对象创建与初始化

对象的创建和初始化通过__new____init__两个魔术方法控制。

1. __new____init__的区别

  • __new__:负责创建对象(静态方法),返回创建的实例
  • __init__:负责初始化对象属性,在__new__之后自动调用

2. 单例模式

单例模式确保一个类只能创建一个对象,通过__new__实现:

class Sun:__instance = None  # 存储唯一实例def __new__(cls, *args, **kwargs):if cls.__instance is None:# 首次创建对象cls.__instance = super().__new__(cls)return cls.__instance  # 返回唯一实例

四、可调用对象与装饰器

通过__call__方法可使对象像函数一样被调用,结合类可实现装饰器。

1. 可调用对象

实现__call__方法后,对象可直接被调用:

class D:def __call__(self, *args):print(f'被调用了,参数:{args}')d = D()
d(123)  # 输出:被调用了,参数:(123,)

2. 类装饰器

类装饰器通过__call__实现,可用于统计函数执行时间、参数校验等。

示例 1:统计执行时间(Timer 类)

class Timer:def __init__(self, func):self.__func = funcdef __call__(self, *args, **kwargs):start = time.time()self.__func(*args, **kwargs)end = time.time()print(f'执行时长:{end - start}')

示例 2:参数类型校验(LimitParameterType 类)

class LimitParameterType:def __init__(self, *args, **kwargs):self.args = args  # 位置参数类型self.kwargs = kwargs  # 关键字参数类型def __call__(self, func):def wrapper(*args, **kwargs):# 校验位置参数类型for i, arg_type in enumerate(self.args):if not isinstance(args[i], arg_type):raise TypeError(f'参数{i}类型错误')# 校验关键字参数类型(省略)return func(*args, **kwargs)return wrapper

装饰器使用示例

@LimitParameterType(str, str)  # 校验参数为字符串
@Timer  # 统计执行时间
def sum_num(a, b):return a + b

五、面向对象三大特性

1. 封装

将数据和操作数据的方法封装在类中,通过访问控制隐藏内部实现。

2. 继承

子类继承父类的属性和方法,可扩展或重写父类功能。

继承语法

class 子类(父类):# 子类实现
方法重写与调用父类方法
  • 子类可重写父类方法(如eatsleep
  • 通过super()调用父类方法:

class VipDog(Dog):  # 继承Dog类def __init__(self, name, age, gender):super().__init__(age, gender)  # 调用父类初始化self.name = name  # 子类特有属性def eat(self):super().eat()  # 调用父类eat方法print(f'{self.name}吃上大骨头啦!')

3. 多态

不同子类对同一方法的不同实现,调用时自动适配具体类型(Python 中通过动态类型实现)。

六、关键问题解答

问题:能否让变量a满足a + 1 == 2 and a + 1 == 3 and a + 1 == 5

解答:可以通过重载__add____eq__实现:

class B:def __add__(self, other):return self  # 加法返回自身def __eq__(self, other):return True  # 相等判断永远返回Truea = B()
print(a + 1 == 2 and a + 1 == 3 and a + 1 == 5)  # 输出:True

原理:a + 1返回a本身,a == 任意值均为True

 

一、魔术方法应用

1. 单例模式实现

需求:定义一个Sington类,确保该类只能创建唯一对象。

class Sington:"""单例模式类:一个类只能创建一个对象"""__instance = None  # 私有类属性,存储唯一实例def __new__(cls, *args, **kwargs):# 判断是否已创建过对象if cls.__instance is None:# 首次创建对象时,调用父类new方法cls.__instance = super().__new__(cls)return cls.__instance  # 返回唯一实例def __init__(self, val):self.val = val  # 初始化属性# 测试
if __name__ == '__main__':a = Sington(1)a1 = Sington(2)print(a1, a2, a3, a, sep='\n')  # 所有对象地址相同(单例特性)

2. Person 类(对象比较与去重)

需求

  • 打印对象时显示姓名和年龄
  • 支持按姓名和年龄比较相等性
  • 存储到 Set 中时按 “姓名 + 年龄” 去重

class Person:def __init__(self, name, age):self.name = nameself.age = age# 打印对象格式:姓名、年龄def __repr__(self):return f'{self.name}、{self.age}'# 比较相等性(姓名和年龄均相同则相等)def __eq__(self, other):if other is None:return Falseif self is other:return Trueif not isinstance(other, Person):return Falsereturn self.name == other.name and self.age == other.age# 支持Set去重(基于姓名和年龄生成哈希值)def __hash__(self):return hash((self.name, self.age))# 测试
if __name__ == '__main__':a = Person('王五', 18)b = Person('赵磊', 18)c = Person('王五', 18)print(a)  # 王五、18print(a == c)  # True(姓名和年龄相同)print(set([a, b, c]))  # {王五、18, 赵磊、18}(去重)

3. Num 类(算术运算重载)

需求

  • 私有化value属性
  • 支持两个 Num 对象的加减乘除、整除、取余运算
  • 打印格式为Num(值)
class Num:def __init__(self, value):self.value = value  # 通过属性装饰器私有化# 算术运算重载(返回新的Num对象)def __add__(self, other):return Num(self.value + other.value)def __sub__(self, other):return Num(self.value - other.value)def __mul__(self, other):return Num(self.value * other.value)def __truediv__(self, other):return Num(self.value / other.value)def __floordiv__(self, other):return Num(self.value // other.value)def __mod__(self, other):return Num(self.value % other.value)# 打印格式def __repr__(self):return f'Num({self.value})'# 私有化value属性@propertydef value(self):return self.__value@value.setterdef value(self, value):self.__value = value# 测试
if __name__ == '__main__':num1 = Num(2)num2 = Num(3)print(num1 + num2)  # Num(5)print(num1 * num2)  # Num(6)

4. 特殊表达式满足(a + 1 == 2 and a + 1 == 3)

需求:创建类 A,使其实例a满足a + 1 == 2 and a + 1 == 3

class A:def __add__(self, other):return self  # 加法运算返回自身def __eq__(self, other):return True  # 相等判断永远返回True# 测试
if __name__ == '__main__':a = A()print(a + 1 == 2 and a + 1 == 3)  # True

原理a + 1返回a本身,a == 2a == 3均返回True

5. 可迭代与可相加类 B

需求

  • 实例支持for循环遍历传入的参数
  • 两个实例相加时合并数据并返回新结果

class B:def __init__(self, *args):self.args = args  # 存储传入的多个参数# 支持for循环(返回迭代器)def __iter__(self):return iter(self.args)# 支持加法(合并两个实例的参数)def __add__(self, other):return B(*(self.args + other.args))  # 返回新B实例# 打印格式def __repr__(self):return f'B{self.args}'# 测试
if __name__ == '__main__':a = B(1, 2, 3)b = B(4, 5)for x in a:print(x)  # 1、2、3print(a + b)  # B(1, 2, 3, 4, 5)

6. 基于类的装饰器 GeneratorKey

需求

  • 为类实例自动生成或校验id属性
  • 未传入id时自动分配(从seq开始,每次 + 1)
  • 传入id时需大于当前seq,否则抛异常

class GeneratorKey:def __init__(self, *, seq=1):self.seq = seq  # 初始序列值def __call__(self, cls):def wrapper(*args, **kwargs):if 'id' not in kwargs:# 未传入id:自动分配并递增seqkwargs['id'] = self.seqself.seq += 1else:# 传入id:检查是否大于当前seqif kwargs['id'] <= self.seq:raise RuntimeError('id必须大于当前seq')self.seq = kwargs['id']  # 更新seq为传入的idreturn cls(*args, **kwargs)  # 创建并返回实例return wrapper# 使用装饰器
@GeneratorKey(seq=1)
class User:def __init__(self, name, id):self.name = nameself.id = iddef __repr__(self):return f'User(name={self.name}, id={self.id})'# 测试
if __name__ == '__main__':u1 = User('张三')  # 自动分配id=1,seq变为2u2 = User('李四')  # 自动分配id=2,seq变为3u3 = User('王五', id=5)  # 传入id=5(>3),seq更新为5u4 = User('赵六')  # 自动分配id=6,seq变为7print(u1, u2, u3, u4)# u5 = User('陆奇', id=4)  # 抛异常(4 <= 5)

7. 对象创建次数统计类 D

需求:通过__new__记录类的实例创建次数

class D:instance_count = 0  # 类属性:记录创建次数def __new__(cls):cls.instance_count += 1  # 每次创建对象时+1return super().__new__(cls)# 测试
if __name__ == '__main__':a = D()b = D()c = D()print(D.instance_count)  # 3

二、继承与图形计算

1. 基础图形类设计

按要求实现图形类及其子类,支持周长、面积、体积计算。

import math# 1. 基础图形类
class Shape:"""图形基类:定义周长和面积方法"""def perimeter(self):passdef area(self):pass# 2. 长方形
class Rectangle(Shape):"""长方形:继承Shape,实现周长和面积"""def __init__(self, length, width):self.__length = length  # 私有属性self.__width = width@propertydef length(self):return self.__length@propertydef width(self):return self.__width# 周长 = 2*(长+宽)def perimeter(self):return 2 * (self.length + self.width)# 面积 = 长*宽def area(self):return self.length * self.width# 3. 正方形(继承长方形)
class Square(Rectangle):"""正方形:继承Rectangle,边长作为参数"""def __init__(self, side):super().__init__(side, side)  # 调用父类构造(长=宽=边长)# 4. 圆形
class Circle(Shape):"""圆形:继承Shape,实现周长和面积"""def __init__(self, radius):self.__radius = radius@propertydef radius(self):return self.__radius# 周长 = 2πrdef perimeter(self):return 2 * math.pi * self.radius# 面积 = πr²def area(self):return math.pi * (self.radius **2)# 5. 立体图形基类
class Stereograph(Shape):"""立体图形:继承Shape,定义体积方法"""def volume(self):raise RuntimeError("请使用具体立体图形完成体积的计算")# 6. 圆柱体
class Cylinder(Stereograph, Circle):"""圆柱体:继承立体图形和圆形,实现表面积和体积"""def __init__(self, radius, height):Circle.__init__(self, radius)  # 初始化半径self.__height = height@propertydef height(self):return self.__height# 圆柱体周长:不支持(抛异常)def perimeter(self):raise TypeError("图形不支持该计算")# 表面积 = 2个底面积 + 侧面积(周长×高)def area(self):return 2 * Circle.area(self) + self.perimeter() * self.height# 体积 = 底面积×高def volume(self):return Circle.area(self) * self.height# 7. 圆锥体(继承圆柱体)
class Cone(Cylinder):"""圆锥体:继承Cylinder,重写表面积和体积"""def volume(self):# 体积 = 1/3 × 底面积 × 高return super().volume() / 3def area(self):# 表面积 = 底面积 + 侧面积(π×半径×母线)母线 = math.sqrt(self.radius** 2 + self.height **2)return math.pi * self.radius** 2 + math.pi * self.radius * 母线def perimeter(self):raise TypeError("图形不支持该计算")

2. 图形测试代码

if __name__ == '__main__':# 长方形rect = Rectangle(5, 3)print(f"长方形周长:{rect.perimeter()},面积:{rect.area()}")# 正方形square = Square(4)print(f"正方形周长:{square.perimeter()},面积:{square.area()}")# 圆形circle = Circle(2)print(f"圆形周长:{circle.perimeter()},面积:{circle.area()}")# 圆柱体cylinder = Cylinder(2, 5)print(f"圆柱体表面积:{cylinder.area()},体积:{cylinder.volume()}")# 圆锥体cone = Cone(2, 5)print(f"圆锥体表面积:{cone.area()},体积:{cone.volume()}")

三、总结

本次作业重点练习:

  1. 魔术方法:运算符重载(__add____eq__等)、对象创建(__new__)、迭代(__iter__)等
  2. 继承与多态:通过图形类层级实现方法重写与扩展
  3. 装饰器:基于类的装饰器实现属性自动生成与校验
  4. 封装:通过私有属性和属性装饰器隐藏内部实现

http://www.xdnf.cn/news/16172.html

相关文章:

  • 数组toString方法及类型检测修复方案
  • Linux 内核基础统简全解:Kbuild、内存分配和地址映射
  • 【推荐100个unity插件】Animator 的替代品?—— Animancer Pro插件的使用介绍
  • 同花顺前端潜在面试题目与答案
  • 星慈光编程虫2号小车讲解第一篇--向前向后
  • 力扣1287:有序数组中出现次数超过25%的元素
  • 背包DP之分组背包
  • 嵌入式通信知识串讲:从同步 / 异步传输到 UART 协议 STM32F103 硬件解析
  • ​Excel——SUMPRODUCT 函数
  • 基于CloudBase+React+CodeBudddy的云上智能睡眠应用开发实践
  • PCL 间接平差拟合球
  • 基于20和28 nm FPGAs的实现多通道、低非线性时间到数字转换器
  • 变量和函数底层工作原理
  • T-RO顶刊|单视角“找相似”,大阪大学提出新型点云描述符(C-FPFH),杂乱场景一抓一个准!
  • 0724 双向链表
  • C语言(十)
  • 移动端自动化Appium框架
  • 清除浮动以及原理
  • 2025年6月GESP(C++六级):学习小组
  • wiz2025 挑战赛从 SpringActuator 泄露到 s3 敏感文件获取全解析
  • Linux驱动19 --- FFMPEG
  • 7.3.2 内核内存管理运行机制
  • Lua(迭代器)
  • 现代C++的一般编程规范
  • 论文阅读:《针对多目标优化和应用的 NSGA-II 综述》一些关于优化算法的简介
  • Python生成折线图
  • 二、计算机网络技术——第6章:应用层
  • matrix-breakout-2-morpheus靶场通过
  • 详解FreeRTOS开发过程(五)-- 系统内核控制函数及任务相关API函数
  • 低功耗设计双目协同画面实现光学变焦内带AI模型