Python多继承与MRO机制一、多继承基础Python支持多继承一个类可以继承多个父类class Flyable:def fly(self):print(f{self.__class__.__name__} 正在飞行)class Swimmable:def swim(self):print(f{self.__class__.__name__} 正在游泳)class Duck(Flyable, Swimmable):def quack(self):print(嘎嘎嘎)duck Duck()duck.fly() # Duck 正在飞行duck.swim() # Duck 正在游泳duck.quack() # 嘎嘎嘎二、方法解析顺序MRO当多个父类有同名方法时Python使用C3线性化算法确定调用顺序class A:def method(self):print(A.method)class B(A):def method(self):print(B.method)class C(A):def method(self):print(C.method)class D(B, C):pass# 查看MROprint(D.__mro__)# (, , , , )d D()d.method() # B.method按MRO顺序B在C前面# MRO遵循的原则# 1. 子类优先于父类# 2. 多个父类按声明顺序# 3. 保持单调性如果A在B前面在所有子类中A都在B前面三、super()的工作原理super()不是简单地调用父类方法而是按MRO顺序调用下一个类的方法class Base:def __init__(self):print(Base.__init__)class Left(Base):def __init__(self):print(Left.__init__)super().__init__() # 调用MRO中的下一个不一定是Baseclass Right(Base):def __init__(self):print(Right.__init__)super().__init__()class Child(Left, Right):def __init__(self):print(Child.__init__)super().__init__()child Child()# 输出顺序# Child.__init__# Left.__init__# Right.__init__ Left的super()调用的是Right不是Base# Base.__init__# MRO: Child - Left - Right - Base - object四、协作式多继承正确使用多继承的关键是协作式设计class Shape:def __init__(self, **kwargs):# 消费自己需要的参数传递剩余参数super().__init__(**kwargs)class ColorMixin:def __init__(self, colorblack, **kwargs):self.color colorsuper().__init__(**kwargs)def describe_color(self):return f颜色: {self.color}class SizeMixin:def __init__(self, width0, height0, **kwargs):self.width widthself.height heightsuper().__init__(**kwargs)def area(self):return self.width * self.heightclass BorderMixin:def __init__(self, border_width1, **kwargs):self.border_width border_widthsuper().__init__(**kwargs)class Rectangle(ColorMixin, SizeMixin, BorderMixin, Shape):def __init__(self, **kwargs):super().__init__(**kwargs)def describe(self):return f矩形: {self.width}x{self.height}, {self.describe_color()}, 边框{self.border_width}px# 所有参数通过kwargs传递每个类取自己需要的rect Rectangle(colorred, width100, height50, border_width2)print(rect.describe())# 矩形: 100x50, 颜色: red, 边框2px五、Mixin模式Mixin是一种通过多继承为类添加功能的设计模式import jsonimport timeclass SerializableMixin:JSON序列化能力def to_json(self):return json.dumps(self.__dict__, defaultstr, ensure_asciiFalse)classmethoddef from_json(cls, json_str):data json.loads(json_str)return cls(**data)class TimestampMixin:自动时间戳def __init__(self, **kwargs):super().__init__(**kwargs)self.created_at time.time()self.updated_at time.time()def touch(self):self.updated_at time.time()class ValidatableMixin:数据验证能力_validators {}def validate(self):errors []for field, validator in self._validators.items():value getattr(self, field, None)try:validator(value)except (ValueError, TypeError) as e:errors.append(f{field}: {e})if errors:raise ValueError(f验证失败: {; .join(errors)})return Trueclass ComparableMixin:比较能力需要子类定义_compare_keydef _compare_key(self):raise NotImplementedErrordef __eq__(self, other):if not isinstance(other, self.__class__):return NotImplementedreturn self._compare_key() other._compare_key()def __lt__(self, other):if not isinstance(other, self.__class__):return NotImplementedreturn self._compare_key() other._compare_key()def __hash__(self):return hash(self._compare_key())# 组合使用class User(SerializableMixin, TimestampMixin, ValidatableMixin):_validators {name: lambda v: v and len(v) 2 or (_ for _ in ()).throw(ValueError(至少2个字符)),age: lambda v: 0 v 150 or (_ for _ in ()).throw(ValueError(必须在0-150之间)),}def __init__(self, name, age, **kwargs):self.name nameself.age agesuper().__init__(**kwargs)user User(Alice, 30)print(user.to_json())print(user.created_at)六、菱形继承问题class Logger:def __init__(self):self.log_entries []def log(self, message):self.log_entries.append(message)class FileLogger(Logger):def __init__(self):super().__init__()self.filename app.logdef log(self, message):super().log(message)# 写入文件...class ConsoleLogger(Logger):def __init__(self):super().__init__()def log(self, message):super().log(message)print(message)class DualLogger(FileLogger, ConsoleLogger):同时输出到文件和控制台def log(self, message):super().log(message) # 按MRO调用# MRO: DualLogger - FileLogger - ConsoleLogger - Logger# super()确保Logger.__init__只被调用一次七、抽象基类与多继承from abc import ABC, abstractmethodclass Readable(ABC):abstractmethoddef read(self) - bytes:passclass Writable(ABC):abstractmethoddef write(self, data: bytes) - int:passclass Seekable(ABC):abstractmethoddef seek(self, offset: int, whence: int 0) - int:passclass ReadWriteStream(Readable, Writable, Seekable):必须实现所有抽象方法def __init__(self):self._buffer bytearray()self._position 0def read(self) - bytes:data bytes(self._buffer[self._position:])self._position len(self._buffer)return datadef write(self, data: bytes) - int:self._buffer.extend(data)self._position len(self._buffer)return len(data)def seek(self, offset: int, whence: int 0) - int:if whence 0:self._position offsetelif whence 1:self._position offsetelif whence 2:self._position len(self._buffer) offsetreturn self._position八、__init_subclass__替代方案class PluginBase:使用__init_subclass__替代元类实现插件注册_plugins {}def __init_subclass__(cls, plugin_nameNone, **kwargs):super().__init_subclass__(**kwargs)name plugin_name or cls.__name__.lower()cls._plugins[name] clsclassmethoddef get_plugin(cls, name):return cls._plugins.get(name)classmethoddef list_plugins(cls):return list(cls._plugins.keys())class JSONProcessor(PluginBase, plugin_namejson):def process(self, data):return json.dumps(data)class XMLProcessor(PluginBase, plugin_namexml):def process(self, data):return f{data}print(PluginBase.list_plugins()) # [json, xml]processor PluginBase.get_plugin(json)()print(processor.process({key: value}))九、多继承的陷阱与规避# 陷阱1方法冲突class A:def action(self):return A的实现class B:def action(self):return B的实现class C(A, B):pass # C.action() 调用A的版本按声明顺序# 规避明确覆盖class C(A, B):def action(self):# 明确选择或组合result_a A.action(self)result_b B.action(self)return f{result_a} {result_b}# 陷阱2__init__参数不兼容# 规避使用**kwargs协作式设计# 陷阱3状态冲突class TimerMixin:def __init__(self):self.start_time time.time() # 可能覆盖其他类的同名属性# 规避使用名称前缀class TimerMixin:def __init__(self, **kwargs):super().__init__(**kwargs)self._timer_start_time time.time()十、设计建议1. 优先使用组合而非继承2. Mixin类应该小而专注只提供一种能力3. Mixin类不应该有自己的状态或最小化状态4. 使用**kwargs实现协作式__init__5. 避免超过2-3层的继承深度6. 使用ABC定义接口Mixin添加实现7. 当MRO变得复杂时考虑重构为组合模式# 组合优于继承的示例class Logger:def log(self, msg): passclass Serializer:def serialize(self, obj): pass# 继承方式紧耦合class Service(Logger, Serializer):pass# 组合方式松耦合更灵活class Service:def __init__(self, loggerNone, serializerNone):self.logger logger or Logger()self.serializer serializer or Serializer()总结多继承是Python的强大特性但需要谨慎使用。理解MRO和super()的工作原理是正确使用多继承的前提。Mixin模式是多继承最常见且最安全的应用方式它通过小而专注的类为目标类添加可复用的功能。
Python多继承与MRO机制
发布时间:2026/5/15 20:05:31
Python多继承与MRO机制一、多继承基础Python支持多继承一个类可以继承多个父类class Flyable:def fly(self):print(f{self.__class__.__name__} 正在飞行)class Swimmable:def swim(self):print(f{self.__class__.__name__} 正在游泳)class Duck(Flyable, Swimmable):def quack(self):print(嘎嘎嘎)duck Duck()duck.fly() # Duck 正在飞行duck.swim() # Duck 正在游泳duck.quack() # 嘎嘎嘎二、方法解析顺序MRO当多个父类有同名方法时Python使用C3线性化算法确定调用顺序class A:def method(self):print(A.method)class B(A):def method(self):print(B.method)class C(A):def method(self):print(C.method)class D(B, C):pass# 查看MROprint(D.__mro__)# (, , , , )d D()d.method() # B.method按MRO顺序B在C前面# MRO遵循的原则# 1. 子类优先于父类# 2. 多个父类按声明顺序# 3. 保持单调性如果A在B前面在所有子类中A都在B前面三、super()的工作原理super()不是简单地调用父类方法而是按MRO顺序调用下一个类的方法class Base:def __init__(self):print(Base.__init__)class Left(Base):def __init__(self):print(Left.__init__)super().__init__() # 调用MRO中的下一个不一定是Baseclass Right(Base):def __init__(self):print(Right.__init__)super().__init__()class Child(Left, Right):def __init__(self):print(Child.__init__)super().__init__()child Child()# 输出顺序# Child.__init__# Left.__init__# Right.__init__ Left的super()调用的是Right不是Base# Base.__init__# MRO: Child - Left - Right - Base - object四、协作式多继承正确使用多继承的关键是协作式设计class Shape:def __init__(self, **kwargs):# 消费自己需要的参数传递剩余参数super().__init__(**kwargs)class ColorMixin:def __init__(self, colorblack, **kwargs):self.color colorsuper().__init__(**kwargs)def describe_color(self):return f颜色: {self.color}class SizeMixin:def __init__(self, width0, height0, **kwargs):self.width widthself.height heightsuper().__init__(**kwargs)def area(self):return self.width * self.heightclass BorderMixin:def __init__(self, border_width1, **kwargs):self.border_width border_widthsuper().__init__(**kwargs)class Rectangle(ColorMixin, SizeMixin, BorderMixin, Shape):def __init__(self, **kwargs):super().__init__(**kwargs)def describe(self):return f矩形: {self.width}x{self.height}, {self.describe_color()}, 边框{self.border_width}px# 所有参数通过kwargs传递每个类取自己需要的rect Rectangle(colorred, width100, height50, border_width2)print(rect.describe())# 矩形: 100x50, 颜色: red, 边框2px五、Mixin模式Mixin是一种通过多继承为类添加功能的设计模式import jsonimport timeclass SerializableMixin:JSON序列化能力def to_json(self):return json.dumps(self.__dict__, defaultstr, ensure_asciiFalse)classmethoddef from_json(cls, json_str):data json.loads(json_str)return cls(**data)class TimestampMixin:自动时间戳def __init__(self, **kwargs):super().__init__(**kwargs)self.created_at time.time()self.updated_at time.time()def touch(self):self.updated_at time.time()class ValidatableMixin:数据验证能力_validators {}def validate(self):errors []for field, validator in self._validators.items():value getattr(self, field, None)try:validator(value)except (ValueError, TypeError) as e:errors.append(f{field}: {e})if errors:raise ValueError(f验证失败: {; .join(errors)})return Trueclass ComparableMixin:比较能力需要子类定义_compare_keydef _compare_key(self):raise NotImplementedErrordef __eq__(self, other):if not isinstance(other, self.__class__):return NotImplementedreturn self._compare_key() other._compare_key()def __lt__(self, other):if not isinstance(other, self.__class__):return NotImplementedreturn self._compare_key() other._compare_key()def __hash__(self):return hash(self._compare_key())# 组合使用class User(SerializableMixin, TimestampMixin, ValidatableMixin):_validators {name: lambda v: v and len(v) 2 or (_ for _ in ()).throw(ValueError(至少2个字符)),age: lambda v: 0 v 150 or (_ for _ in ()).throw(ValueError(必须在0-150之间)),}def __init__(self, name, age, **kwargs):self.name nameself.age agesuper().__init__(**kwargs)user User(Alice, 30)print(user.to_json())print(user.created_at)六、菱形继承问题class Logger:def __init__(self):self.log_entries []def log(self, message):self.log_entries.append(message)class FileLogger(Logger):def __init__(self):super().__init__()self.filename app.logdef log(self, message):super().log(message)# 写入文件...class ConsoleLogger(Logger):def __init__(self):super().__init__()def log(self, message):super().log(message)print(message)class DualLogger(FileLogger, ConsoleLogger):同时输出到文件和控制台def log(self, message):super().log(message) # 按MRO调用# MRO: DualLogger - FileLogger - ConsoleLogger - Logger# super()确保Logger.__init__只被调用一次七、抽象基类与多继承from abc import ABC, abstractmethodclass Readable(ABC):abstractmethoddef read(self) - bytes:passclass Writable(ABC):abstractmethoddef write(self, data: bytes) - int:passclass Seekable(ABC):abstractmethoddef seek(self, offset: int, whence: int 0) - int:passclass ReadWriteStream(Readable, Writable, Seekable):必须实现所有抽象方法def __init__(self):self._buffer bytearray()self._position 0def read(self) - bytes:data bytes(self._buffer[self._position:])self._position len(self._buffer)return datadef write(self, data: bytes) - int:self._buffer.extend(data)self._position len(self._buffer)return len(data)def seek(self, offset: int, whence: int 0) - int:if whence 0:self._position offsetelif whence 1:self._position offsetelif whence 2:self._position len(self._buffer) offsetreturn self._position八、__init_subclass__替代方案class PluginBase:使用__init_subclass__替代元类实现插件注册_plugins {}def __init_subclass__(cls, plugin_nameNone, **kwargs):super().__init_subclass__(**kwargs)name plugin_name or cls.__name__.lower()cls._plugins[name] clsclassmethoddef get_plugin(cls, name):return cls._plugins.get(name)classmethoddef list_plugins(cls):return list(cls._plugins.keys())class JSONProcessor(PluginBase, plugin_namejson):def process(self, data):return json.dumps(data)class XMLProcessor(PluginBase, plugin_namexml):def process(self, data):return f{data}print(PluginBase.list_plugins()) # [json, xml]processor PluginBase.get_plugin(json)()print(processor.process({key: value}))九、多继承的陷阱与规避# 陷阱1方法冲突class A:def action(self):return A的实现class B:def action(self):return B的实现class C(A, B):pass # C.action() 调用A的版本按声明顺序# 规避明确覆盖class C(A, B):def action(self):# 明确选择或组合result_a A.action(self)result_b B.action(self)return f{result_a} {result_b}# 陷阱2__init__参数不兼容# 规避使用**kwargs协作式设计# 陷阱3状态冲突class TimerMixin:def __init__(self):self.start_time time.time() # 可能覆盖其他类的同名属性# 规避使用名称前缀class TimerMixin:def __init__(self, **kwargs):super().__init__(**kwargs)self._timer_start_time time.time()十、设计建议1. 优先使用组合而非继承2. Mixin类应该小而专注只提供一种能力3. Mixin类不应该有自己的状态或最小化状态4. 使用**kwargs实现协作式__init__5. 避免超过2-3层的继承深度6. 使用ABC定义接口Mixin添加实现7. 当MRO变得复杂时考虑重构为组合模式# 组合优于继承的示例class Logger:def log(self, msg): passclass Serializer:def serialize(self, obj): pass# 继承方式紧耦合class Service(Logger, Serializer):pass# 组合方式松耦合更灵活class Service:def __init__(self, loggerNone, serializerNone):self.logger logger or Logger()self.serializer serializer or Serializer()总结多继承是Python的强大特性但需要谨慎使用。理解MRO和super()的工作原理是正确使用多继承的前提。Mixin模式是多继承最常见且最安全的应用方式它通过小而专注的类为目标类添加可复用的功能。