如何用type和super实现Python动态继承父类的属性与方法
实现方案
你要的功能不需要自定义元类,只要处理好super的传参规则和方法绑定逻辑就行,下面是可直接运行的实现:
最小符合预期版本
完全匹配你最初的调用逻辑和输出要求:
class A: def __init__(self, a, b): self.a = a self.b = b def some_method(self, q): return (self.a + self.b)**q def another_method(self): return 1 def class_B_factory(parent_class): # __init__放在工厂内部定义,可直接捕获生成的类对象 def B_init(self, **kwargs): # 显式给super传当前类和self,避免无参super的命名空间依赖问题 super(new_cls, self).__init__(**kwargs) new_cls = type( 'B', (parent_class,), # 有其他父类可补充到元组里 { '__init__': B_init, 'another_method': another_method } ) return new_cls
调用测试:
model = class_B_factory(A)(a = 1, b = 5) print(model.some_method(2)) # 输出36 print(model.another_method()) # 输出1
扩展场景修复(方法外置的情况)
你补充的用partial绑定参数的方案报错,是因为partial包装的函数不会被Python识别为类的绑定方法,实例化时不会自动注入self参数,改用闭包包装即可修复:
from inspect import signature from functools import partial class A: def __init__(self, a, b): self.a = a self.b = b def some_method(self, q): return (self.a + self.b)**q def B_init(self, produced_class, **kwargs): super(produced_class, self).__init__(**kwargs) def another_method(self, q, parent_class = None): if parent_class is not None: # 已经继承父类,直接调用self的方法即可,不需要通过父类调用 return 3 * self.some_method(q) return 1 def class_B_factory(parent_class, additional_methods): methods = {} for name, method in additional_methods.items(): if "parent_class" in signature(method).parameters: method = partial(method, parent_class = parent_class) methods[name] = method # 用闭包包装__init__,捕获当前生成的类,避免partial的绑定问题 def wrapped_init(self, **kwargs): B_init(self, new_cls, **kwargs) methods['__init__'] = wrapped_init new_cls = type( 'B', (parent_class,), methods ) return new_cls
调用测试:
B_cls = class_B_factory(parent_class = A, additional_methods = {"another_method": another_method}) instance = B_cls(a=1, b=5) print(instance.some_method(2)) # 输出36 print(instance.another_method(2)) # 输出108
核心原理说明
- Python3的无参
super()仅支持类内部定义的方法,依赖方法的__class__单元格变量定位当前类,类外定义的方法没有这个变量,必须显式传入当前类和self两个参数。 - 不要用partial包装类的实例方法,partial生成的是普通函数,Python不会自动处理self参数的注入,用闭包捕获上下文变量是更稳妥的方案。
内容的提问来源于stack exchange,提问作者Matthew K
相关产品推荐
相关产品推荐

