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

Python Day17 面向对象 及例题分析

一、多态

1. 核心概念

多态是面向对象的核心概念,指同一个操作在不同对象上表现出不同行为

2. 实现方式
  • 传统实现:通过继承中的方法重写实现(子类重写父类方法,不同子类表现不同)。
  • Python 中的特殊实现
    由于 Python 是 “动态语言”,多态不一定依赖继承,只要两个对象有相同的方法名但行为不同,即可称为多态,这一特性被称为 “鸭子模型”(“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子”)。
    Python 天生支持多态。
3. 示例代码

class Cat:def speak(self):print("喵呜~~")class Dog:def speak(self):print("汪汪汪~~")class Sheep:def speak(self):print("灰太狼来啦~~")if __name__ == '__main__':cat = Cat()dog = Dog()sheep = Sheep()animals = [cat, dog, sheep]# 同一个操作speak(),不同对象表现不同for animal in animals:animal.speak()  # 输出:喵呜~~ / 汪汪汪~~ / 灰太狼来啦~~

二、反射

1. 核心概念

反射指程序运行期间动态操作对象属性(获取、设置、删除、判断是否存在)。

2. 常用函数(均接收字符串类型的属性名)
函数作用
getattr(obj, 'name')获取对象obj中属性name的值
setattr(obj, 'name', value)给对象obj的属性name设置值value
delattr(obj, 'name')删除对象obj中的属性name
hasattr(obj, 'name')判断对象obj中是否存在属性name(返回布尔值)
3. 示例代码

class Adog:def __init__(self, name):self.name = nameif __name__ == '__main__':dog = Adog("小黑")print(dog.name)  # 直接访问属性:小黑# 动态设置属性dog.age = 2print(dog.age)  # 2# 判断属性是否存在print(hasattr(dog, "age"))  # True# 删除属性delattr(dog, "age")print(hasattr(dog, "age"))  # False# 重新设置并获取属性setattr(dog, "age", 3)print(hasattr(dog, "age"))  # Trueprint(getattr(dog, "age"))  # 3

三、动态属性处理(Model 类示例)

通过__new__魔术方法动态生成类的属性、property( getter/setter )和__repr__方法,简化类的定义。

1. 核心逻辑
  • 定义Model类,通过__new__方法在类创建时动态处理属性:
    1. 从子类的__all_fields__获取需要的属性列表;
    2. 检查传入的关键字参数是否合法(仅允许__all_fields__中的属性);
    3. 为每个属性生成私有变量,并通过property绑定 getter 和 setter;
    4. 动态生成__repr__方法,格式化对象的字符串表示。
2. 示例代码

class Model:def __new__(cls, *args, **kwargs):instance = super().__new__(cls)# 获取子类定义的所有属性fields = cls.__all_fields__# 检查关键字参数合法性for key in kwargs:if key not in fields:raise KeyError(f"不识别关键字{key},允许的关键字:{','.join(fields)}")# 动态生成属性和propertyfor field in fields:value = kwargs.get(field)  # 默认为None# 定义私有变量(格式:_类名__属性名)setattr(instance, f"_{cls.__name__}__{field}", value)# 生成getter(获取私有变量值)getter = (lambda x: lambda self: getattr(self, f"_{cls.__name__}__{x}"))(field)# 生成setter(设置私有变量值)setter = (lambda x: lambda self, val: setattr(self, f"_{cls.__name__}__{x}", val))(field)# 绑定property到类setattr(cls, field, property(getter, setter))# 动态生成__repr__方法(格式化对象信息)prefix = f"_{cls.__name__}__"setattr(cls, "__repr__", lambda self: f"{self.__class__.__name__}({ {k.removeprefix(prefix):v for k,v in self.__dict__.items()} })")return instance# 子类继承Model,仅需定义__all_fields__
class Human(Model):__all_fields__ = ('name', 'age', 'gender', 'tel', 'email')if __name__ == '__main__':human = Human(name='小光', age=20, gender='<UNK>', tel='<UNK>', email='<UNK>')print(human.name, human.tel)  # 小光 <UNK>print(human)  # Human({'name': '小光', 'age': 20, 'gender': '<UNK>', 'tel': '<UNK>', 'email': '<UNK>'})

四、元类

1. 核心概念
  • 元类是 “描述类的类型”,用type表示(所有类都是type的实例)。
  • 作用:
    a) 创建类;
    b) 控制类的创建过程(如动态添加属性 / 方法、限制类的实例化等)。
2. type的用法

type有两种核心用法:

  • 获取对象类型type(obj)返回对象obj的类型(类)。
  • 动态创建类type(name, bases, kwargs)直接创建一个类,参数说明:
    • name:类名(字符串);
    • bases:父类元组(无父类时为空元组);
    • kwargs:类的属性和方法(字典)。
3. 用type创建类的示例

# 用type创建Dog1类(类名:Dog1,无父类,包含__init__、eat、speak方法)
Dog1 = type('Dog1',  # 类名(),  # 父类元组(空){"__init__": lambda self, name: setattr(self, "name", name),  # 初始化方法'eat': lambda self: print('狗在吃骨头!'),  # 自定义方法'speak': lambda self: print('汪汪汪!')  # 自定义方法}
)# 使用创建的类
dog = Dog1("小黑")
dog.speak()  # 汪汪汪!
print(dog.name)  # 小黑
4. 自定义元类(通过metaclass控制类的创建)

通过metaclass参数指定元类,可在类创建时插入自定义逻辑。元类需继承type,核心魔术方法:

  • __new__:创建类(返回类的实例);
  • __init__:初始化类(给类添加属性 / 方法);
  • __call__:控制类的实例化(创建类的对象)。
示例 1:给类自动添加__repr__和私有类属性

class Repr(type):"""元类:给类添加__repr__方法和私有类属性__logo"""def __new__(cls, name, bases, kwargs):# 动态添加__repr__方法(格式化对象信息)kwargs['__repr__'] = lambda self: f"{self.__class__.__name__}({self.__dict__})"# 动态添加私有类属性(格式:_类名__logo)kwargs[f"_{name}__logo"] = 'QIKU'# 创建并返回类return super().__new__(cls, name, bases, kwargs)# 使用Repr元类
class Person(metaclass=Repr):def __init__(self, name, age):self.name = nameself.age = agep = Person("小明", 18)
print(p)  # Person({'name': '小明', 'age': 18})
print(Person._Person__logo)  # QIKU(私有类属性)
示例 2:单例模式(类仅能创建一个对象)

class Singleton(type):"""元类:确保类仅能实例化一个对象"""def __call__(self, *args, **kwargs):# 定义私有类属性存储唯一实例(格式:_类名__instance)instance_attr = f"_{self.__name__}__instance"# 若实例不存在,则创建并保存;若存在,直接返回if not hasattr(self, instance_attr):instance = super().__call__(*args, **kwargs)  # 调用父类创建对象setattr(self, instance_attr, instance)  # 保存实例return getattr(self, instance_attr)  # 返回唯一实例# 同时添加__repr__和__logo(复用Repr的逻辑)def __new__(cls, name, bases, kwargs):kwargs['__repr__'] = lambda self: f"{self.__class__.__name__}({self.__dict__})"kwargs[f"_{name}__logo"] = 'QIKU'return super().__new__(cls, name, bases, kwargs)# 使用Singleton元类(单例)
class Person(metaclass=Singleton):def __init__(self, name, age):self.name = nameself.age = age# 测试单例:两个对象指向同一实例
p1 = Person("糕糕", 20)
p2 = Person("曹操", 30)  # 虽传入新参数,但不会创建新对象
print(p1)  # Person({'name': '糕糕', 'age': 20})(p2与p1相同)
print(p1 is p2)  # True(同一实例)

五、类与元类中的核心魔术方法对比

魔术方法类中作用元类中作用
__new__创建类的对象(实例)创建类(类本身)
__init__初始化对象的属性初始化类的属性 / 方法
__call__使对象可调用(如obj()控制类的实例化(创建对象)

以上整理完整覆盖了您笔记中的多态、反射、动态属性处理、元类定义与应用等核心知识点,并通过代码示例与逻辑说明强化理解。

一、单例模式(多种实现方式)

单例模式确保一个类只有一个实例,并提供全局访问点。

1. 装饰器实现

def Singleton(cls):_instances = {}def wrapper(*args, **kwargs):if cls not in _instances:_instances[cls] = cls(*args, **kwargs)return _instances[cls]return wrapper@Singleton
class A:def __init__(self, name):self.name = name# 测试
a = A(1)
b = A(3)
print(a.name)  # 1(单例模式,参数仅首次生效)
print(b.name)  # 1
2. 元类实现

class Singleton1(type):def __call__(cls, *args, **kwargs):field = f'_{cls.__name__}__instance'if not hasattr(cls, field):instance = super().__call__(*args, **kwargs)setattr(cls, field, instance)return getattr(cls, field)class B(metaclass=Singleton1):def __init__(self, name, age):self.name = nameself.age = age# 测试
b1 = B("Alice", 20)
b2 = B("Bob", 30)
print(b1.name, b1.age)  # Alice 20
print(b2.name, b2.age)  # Alice 20(单例模式,参数仅首次生效)
3. __new__方法实现

class B:_instance = Nonedef __init__(self, name, age):# 注意:若实例已存在,__init__仍会被调用,可能覆盖属性self.name = nameself.age = agedef __new__(cls, *args, **kwargs):if cls._instance is None:cls._instance = super().__new__(cls)return cls._instance# 测试
b1 = B("Alice", 20)
b2 = B("Bob", 30)
print(b1.name, b1.age)  # Bob 30(__init__被二次调用,覆盖属性)
print(b2.name, b2.age)  # Bob 30

二、元类应用:类属性转换为大写

将类中的类属性名全部转换为大写,并通过大写名称访问原值。

class V(type):def __new__(cls, name, bases, dct):new_dct = {}for k, v in dct.items():new_dct[k.upper()] = v  # 将属性名转为大写return super().__new__(cls, name, bases, new_dct)class A(metaclass=V):name = "a"sex = "m"print(A.NAME)  # a
print(A.SEX)   # m

三、元类应用:实例计数器

跟踪使用该元类创建的所有类的实例数量。

class CountingMeta(type):__global_instance_dict__ = {}  # 存储类名到实例数量的映射def __call__(cls, *args, **kwargs):instance = super().__call__(*args, **kwargs)count = cls.__global_instance_dict__.get(cls.__name__, 0)cls.__global_instance_dict__[cls.__name__] = count + 1return instance@classmethoddef get_instance_count(cls, target_cls):"""返回指定类的实例数量"""return cls.__global_instance_dict__.get(target_cls.__name__, 0)class A(metaclass=CountingMeta):pass# 测试
a1 = A()
a2 = A()
a3 = A()
print(CountingMeta.get_instance_count(A))  # 3

四、责任链模式:采购审批流程

根据采购金额自动选择相应的审批者(直接领导→部门经理→总经理→董事长)。

1. 抽象处理器基类

from abc import ABC, abstractmethodclass Procurement(ABC):def __init__(self, price):self.price = priceself.next_approval = Nonedef set_next_approval(self, next_approval):self.next_approval = next_approvalreturn next_approval  # 支持链式调用@abstractmethoddef approval(self):pass
2. 具体处理器实现

class Approval0(Procurement):  # 直接领导(<5000)def approval(self):if self.price < 5000:print("申请直接领导审批")else:self.next_approval.approval()class Approval1(Procurement):  # 部门经理(<30000)def approval(self):if self.price < 30000:print("申请部门经理审批")else:self.next_approval.approval()class Approval2(Procurement):  # 总经理(<200000)def approval(self):if self.price < 200000:print("申请总经理审批")else:self.next_approval.approval()class Approval3(Procurement):  # 董事长(≥200000)def approval(self):print("申请董事长审批")
3. 流程管理器

class Process:def __init__(self, price):self.price = price# 构建责任链approval0 = Approval0(price)approval1 = Approval1(price)approval2 = Approval2(price)approval3 = Approval3(price)approval0.set_next_approval(approval1) \.set_next_approval(approval2) \.set_next_approval(approval3)self.__handler = approval0def process(self):return self.__handler.approval()
4. 测试

if __name__ == "__main__":Process(4000).process()    # 申请直接领导审批Process(15000).process()   # 申请部门经理审批Process(80000).process()   # 申请总经理审批Process(250000).process()  # 申请董事长审批

五、元类应用:自动生成方法

根据类的__fields__属性自动生成__init____str__方法。

1. 元类实现

class AutoMethodsMeta(type):def __new__(cls, name, bases, dct):# 获取字段列表fields = dct.get('__fields__', [])# 生成__init__方法def __init__(self, *args, **kwargs):# 处理位置参数if args:if len(args) > len(fields):raise TypeError(f"{name}接受最多{len(fields)}个位置参数")for i, value in enumerate(args):setattr(self, fields[i], value)# 处理关键字参数for key, value in kwargs.items():if key not in fields:raise KeyError(f"未知参数'{key}',有效参数:{fields}")setattr(self, key, value)# 检查必填字段for field in fields:if not hasattr(self, field):setattr(self, field, None)# 生成__str__方法def __str__(self):attrs = ", ".join(f"{field}={getattr(self, field)!r}" for field in fields)return f"{name}({attrs})"# 更新类属性dct['__init__'] = __init__dct['__str__'] = __str__return super().__new__(cls, name, bases, dct)

2. 使用示例

class ExampleClass(metaclass=AutoMethodsMeta):__fields__ = ['name', 'age']# 测试
obj = ExampleClass(name='John', age=30)
print(obj)  # ExampleClass(name='John', age=30)

以上整理完整覆盖了您例题中的单例模式、元类应用、责任链模式等核心知识点,并通过代码示例与逻辑说明强化理解。

 

http://www.dtcms.com/a/304263.html

相关文章:

  • Apache Ignite 的分布式队列(IgniteQueue)和分布式集合(IgniteSet)的介绍
  • 集成电路学习:什么是Wi-Fi无线保真度
  • 机器学习sklearn:泰坦尼克幸存预测(决策树、网格搜索找最佳参数)
  • 永磁同步电机无速度算法--静态补偿电压模型Harnefors观测器
  • 泛微E9 引入高版本spring导致webservices接口报错
  • vue2 使用liveplayer加载视频
  • 【初识数据结构】CS61B中的基数排序
  • 彻底清理ArcGIS 10.2残留的步骤
  • 【自制组件库】从零到一实现属于自己的 Vue3 组件库!!!
  • 堆的理论知识
  • uniapp如何封装uni.request 全局使用
  • qt webengine播放视频
  • VS+Qt中使用QCustomPlot绘制曲线标签(附源码)
  • 002 TrafficGenerator 类详解
  • FCN语义分割算法原理与实战
  • 八股训练营 40 天心得:一场结束,也是一场新的开始
  • 力扣热题100--------240.搜索二维矩阵
  • LeetCode热题100——46. 全排列
  • 研电赛-基于GD32的纳型无人机AI追踪系统1
  • vue相关的拖拉拽官网
  • minio安装 windows系统
  • C语言第六章函数递归
  • Linux文件归档和备份
  • Qt 多线程网络编程实战
  • iOS 能耗·电池·电量监控实战指南:如何全面查看与优化 App 电能消耗
  • VTK开发笔记(一):VTK介绍,Qt5.9.3+VS2017x64+VTK8.2编译
  • AI驱动的浏览器自动化革命:Claude Code + BrowserCat MCP深度实践指南
  • 【MySQL学习|黑马笔记|Day2】SQL|DML、DGL、DCL,函数,约束
  • Python 打造 Excel 到 JSON 转换工具:从开发到打包全攻略
  • Java后端开发数据校验工作