Python中super关键字的作用

本文详细介绍了Python中的super()函数,解释了它如何简化父类方法的调用,并避免了重复调用的问题。同时对比了Python2.2之前的方法,展示了super()如何减少代码维护的工作量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1:
代码段1:
class A:
def __init__(self):
   print "enter A"
   print "leave A"


class B(A):
def __init__(self):
   print "enter B"
   A.__init__(self)
   print "leave B"


>>> b = B()

enter B
enter A
leave A
leave B


即,使用非绑定的类方法(用类名来引用的方法),并在参数列表中,引入待绑定的对象(self),从而达到调用父类的目的。

这样做的缺点是,当一个子类的父类发生变化时(如类B的父类由A变为C时),必须遍历整个类定义,把所有的通过非绑定的方法的类名全部替换过来,例如代码段2,

代码段2:

class B(C):    # A --> C
def __init__(self):
   print "enter B"
   C.__init__(self) # A --> C
   print "leave B"

如果代码简单,这样的改动或许还可以接受。但如果代码量庞大,这样的修改可能是灾难性的。很容易导致修改错误的出现。

因此,自Python 2.2开始,Python添加了一个关键字super,来解决这个问题。下面是Python 2.3的官方文档说明:

super(type[, object-or-type])

Return the superclass of type. If the second argument is omitted the super object
returned is unbound. If the second argument is an object, isinstance(obj, type) 
must be true. If the second argument is a type, issubclass(type2, type) must be 
true. super() only works for new-style classes.

A typical use for calling a cooperative superclass method is:

   class C(B):
       def meth(self, arg):
           super(C, self).meth(arg)

New in version 2.2.

从说明来看,可以把类B改写如代码段3:

代码段3:

class A(object):    # A must be new-style class
def __init__(self):
   print "enter A"
   print "leave A"

class B(C):     # A --> C
def __init__(self):
   print "enter B"
   super(B, self).__init__()
   print "leave B"

尝试执行上面同样的代码,结果一致,但修改的代码只有一处,把代码的维护量降到最低,是一个不错的用法。因此在我们的开发过程中,super关键字被大量使用,而且一直表现良好。

-------------------------------

1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象;
2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super);
5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。

------------------------------

从super关键字的help我们也能看出来。

Help on class super in module __builtin__:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |           super(C, self).meth(arg)
 |  
 |  Methods defined here:
.......

从上面也能看出来,super是一个类,而且是__builtin__模块中的。

---------------------------

从上面的描述来看,super主要是用于调用父类的方法。

那么,在2.2之前的方法也能调用。为啥非得用super呢?

这是因为super能够阻止对父类方法的多次调用。

super,改变了父类搜索顺序, 返回的是一个特殊的父类对象
看例子:
class A: pass class B(A): pass class C(A):pass class D(B, C): pass
这是4个类的基本关系。
假如不使用super,让D的对象调用他们共有的一个方法,会2次调用A中这个方法。
### Python `super()` 关键字的使用说明 `super()` 是 Python 中用于调用父类方法的一个内置函数。它的主要作用是在继承层次结构中简化对父类方法的调用,尤其是在多层继承的情况下能够保持代码的可读性和可维护性。 #### 基本功能 在 Python 3 中,`super()` 不再需要显式传递参数即可调用父类的方法[^2]。这使得代码更加简洁明了。具体来说,`super()` 返回一个代理对象,该对象允许我们调用当前类的父类中的方法。 #### 调用方式 以下是 `super()` 的典型用法: ```python class ParentClass: def __init__(self, name): self.name = name def greet(self): print(f"Hello from {self.name}!") class ChildClass(ParentClass): def __init__(self, name, age): super().__init__(name) # 调用父类的构造函数 self.age = age def introduce(self): super().greet() # 调用父类的方法 print(f"I am {self.age} years old.") ``` 在这个例子中,`ChildClass` 继承自 `ParentClass` 并重写了其初始化方法 (`__init__`) 和另一个方法 (`introduce`)。通过 `super()`,我们可以方便地调用父类的实现部分而不必硬编码父类名。 #### 多继承场景下的应用 当存在多个基类时,`super()` 可以按照 Method Resolution Order (MRO)[^4] 来决定调用顺序。下面是一个简单的多继承示例: ```python class A: def method(self): print("A's method") class B(A): def method(self): super().method() print("B's method") class C(A): def method(self): super().method() print("C's method") class D(B, C): def method(self): super().method() print("D's method") d_instance = D() d_instance.method() ``` 运行上述程序会依次打印出: ``` A's method C's method B's method D's method ``` 这是因为 MRO 遵循广度优先原则决定了各方法被调用的实际次序。 #### 自动化与灵活性 相比传统写法如 `ParentClass.some_method(self)`,采用 `super()` 提供了更高的自动化程度以及更好的适应未来可能的变化的能力。即使修改了继承链或者增加了新的中间层,只要遵循正确的设计模式,就不需调整子类内部的具体实现细节[^4]。 --- ### 示例总结 综上所述,`super()` 主要用来解决单继承或多继承情况下如何优雅地调用父类成员的问题。它不仅让代码更干净易懂,还增强了系统的扩展能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值