理解Python中super()与__init__()方法的使用
技术背景
在Python中,super()
函数是一个非常有用的工具,它允许子类调用父类的方法,避免显式地引用父类名称。特别是在多重继承的场景中,super()
能确保在方法解析顺序(MRO)中正确调用下一个父类的函数。
实现步骤
Python 3 中使用 super()
在 Python 3 中,调用 super()
变得更加简洁,可以直接使用 super().__init__()
调用父类的 __init__
方法:
1 2 3 4 5 6 7 8
| class Base: def __init__(self): print("Base init'ed")
class ChildB(Base): def __init__(self): print("ChildB init'ed") super().__init__()
|
Python 2 中使用 super()
在 Python 2 中,需要显式地指定子类和实例对象:
1 2 3 4 5 6 7 8
| class Base(object): def __init__(self): print("Base init'ed")
class ChildB(Base): def __init__(self): print("ChildB init'ed") super(ChildB, self).__init__()
|
不使用 super()
如果不使用 super()
,则需要显式地调用父类的方法:
1 2 3 4 5 6 7 8
| class Base: def __init__(self): print("Base init'ed")
class ChildA(Base): def __init__(self): print("ChildA init'ed") Base.__init__(self)
|
核心代码
模拟 super()
的实现
以下是一个简化的 super()
实现:
1 2 3 4 5 6 7
| class ChildB(Base): def __init__(self): mro = type(self).mro() for next_class in mro[mro.index(ChildB) + 1:]: if hasattr(next_class, '__init__'): next_class.__init__(self) break
|
多重继承示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Base(object): def __init__(self): print("Base init'ed")
class ChildA(Base): def __init__(self): print("ChildA init'ed") Base.__init__(self)
class ChildB(Base): def __init__(self): print("ChildB init'ed") super().__init__()
class UserDependency(Base): def __init__(self): print("UserDependency init'ed") super().__init__()
class UserA(ChildA, UserDependency): def __init__(self): print("UserA init'ed") super().__init__()
class UserB(ChildB, UserDependency): def __init__(self): print("UserB init'ed") super().__init__()
|
最佳实践
- 使用 Python 3:Python 3 中的
super()
语法更加简洁,建议使用 Python 3 进行开发。 - 设计可协作的类:在多重继承场景中,使用
super()
确保类之间的协作性,避免硬编码父类调用。 - 避免使用
self.__class__
:在 super()
中使用 self.__class__
会导致递归调用,应避免使用。
常见问题
使用 self.__class__
导致递归错误
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Polygon(object): def __init__(self, id): self.id = id
class Rectangle(Polygon): def __init__(self, id, width, height): super(self.__class__, self).__init__(id) self.shape = (width, height)
class Square(Rectangle): pass
Square('a', 10, 10)
|
静态方法无法使用 super()
由于静态方法没有访问类的 MRO,因此无法使用 super()
。
Python 2 中 super()
的限制
在 Python 2 中,只有当父类继承自 object
(新风格类)时才能使用 super()
。