一、多态
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 = name
if __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='<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 = name
self.age = age
p = 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
@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 = name
self.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 = 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) # 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 + 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, abstractmethod
class 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)
以上整理完整覆盖了您例题中的单例模式、元类应用、责任链模式等核心知识点,并通过代码示例与逻辑说明强化理解。