python类中越级跳过父类初始化
在 Python 中,通常我们使用 super().__init__() 来确保类的继承链(MRO)能够完整执行。但有时候,你可能会遇到一些奇葩的业务场景,需要越级跳过直接父类,直接调用爷爷类(祖父类)的初始化方法。
虽然这在设计模式上通常被视为一种“红灯信号”,但从技术实现角度来看,确实有几种方法可以做到。
为什么会有这种需求?
通常是因为直接父类(Parent)在 __init__ 中执行了一些你不想要的副作用,又需要爷爷类(Grandparent)的基础设置。
方法一:直接调用祖父类的 __init__ (最直接)
在 Python 3 中,类名本身就是对类对象的引用。你可以绕过 super(),直接通过类名调用实例方法,手动传入 self。
class Grandparent:
def __init__(self):
print("Grandparent initialized!")
self.legacy = "Old Money"
class Parent(Grandparent):
def __init__(self):
print("Parent initialized! (I do heavy stuff you might want to skip)")
super().__init__()
class Child(Parent):
def __init__(self):
print("Child initializing...")
# 越级调用:直接点名 Grandparent
Grandparent.__init__(self)
# 输出:
# Child initializing...
# Grandparent initialized!
方法二:利用 super() 的偏移特性
很多人认为 super() 只能指代父类,但实际上 super(type, obj) 的含义是:在 obj 的 MRO 链条中,从 type 的下一个类开始找方法。
利用这个特性,我们可以实现动态的“越级”。
class Grandparent:
def __init__(self):
print("Grandparent initialized!")
class Parent(Grandparent):
def __init__(self):
print("Parent initialized!")
super().__init__()
class Child(Parent):
def __init__(self):
print("Child initializing...")
# 从 Parent 的下一个类开始找 __init__
# 在 MRO 中,Parent 的下一个通常就是 Grandparent
super(Parent, self).__init__()
# 测试代码
c = Child()
print(Child.mro())
原理分析:
Child.mro() 的顺序通常是 [Child, Parent, Grandparent, object]。
当我们调用 super(Parent, self) 时,Python 会跳过 Child 和 Parent,直接从 Grandparent 开始搜索。
方法三:使用 Mixin 模式重构(更优雅的方案)
如果你发现自己必须跳过父类,通常意味着你的继承层级有问题。与其在底层“打补丁”,不如使用 Mixin(混入) 将功能拆分。
class BaseFeatures: # 将爷爷类的核心逻辑抽离
def __init__(self):
print("Base features initialized")
class Grandparent(BaseFeatures):
pass
class Parent(Grandparent):
def __init__(self):
print("Parent heavy init")
super().__init__()
class Child(BaseFeatures): # 直接继承核心逻辑,避开 Parent
def __init__(self):
print("Child initialized")
super().__init__()

浙公网安备 33010602011771号