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 = 2 print(dog.age) # 2 # 判断属性是否存在 print(hasattr(dog, \"age\")) # True # 删除属性 delattr(dog, \"age\") print(hasattr(dog, \"age\")) # False # 重新设置并获取属性 setattr(dog, \"age\", 3) print(hasattr(dog, \"age\")) # True print(getattr(dog, \"age\")) # 3
三、动态属性处理(Model 类示例)
通过__new__
魔术方法动态生成类的属性、property
( getter/setter )和__repr__
方法,简化类的定义。
1. 核心逻辑
- 定义
Model
类,通过__new__
方法在类创建时动态处理属性:- 从子类的
__all_fields__
获取需要的属性列表; - 检查传入的关键字参数是否合法(仅允许
__all_fields__
中的属性); - 为每个属性生成私有变量,并通过
property
绑定 getter 和 setter; - 动态生成
__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)}\") # 动态生成属性和property for 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=\'\', tel=\'\', email=\'\') print(human.name, human.tel) # 小光 print(human) # Human({\'name\': \'小光\', \'age\': 20, \'gender\': \'\', \'tel\': \'\', \'email\': \'\'})
四、元类
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 = name self.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 = name self.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@Singletonclass 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 = name self.age = age# 测试b1 = B(\"Alice\", 20)b2 = B(\"Bob\", 30)print(b1.name, b1.age) # Alice 20print(b2.name, b2.age) # Alice 20(单例模式,参数仅首次生效)
3. __new__
方法实现
class B: _instance = None def __init__(self, name, age): # 注意:若实例已存在,__init__仍会被调用,可能覆盖属性 self.name = name self.age = age def __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) # aprint(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 + 1 return instance @classmethod def 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 = price self.next_approval = None def set_next_approval(self, next_approval): self.next_approval = next_approval return next_approval # 支持链式调用 @abstractmethod def 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 = approval0 def 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)
以上整理完整覆盖了您例题中的单例模式、元类应用、责任链模式等核心知识点,并通过代码示例与逻辑说明强化理解。