使用super()和使用self从父类调用方法有什么区别?

时间:2016-09-26 06:33:04

标签: python python-3.x oop

class Car:
    def __init__(self, car_name, manufacturer, cost):
        self.__car_name=car_name
        self.__manufacturer=manufacturer
        self.__cost=cost

    def display_car_details(self):
        print(self.__car_name, self.__manufacturer, self.__cost)

class Super_Car(Car):
    def __init__(self, car_name, manufacturer, cost, 
                 top_speed, material_used, engine_type):
        super().__init__(car_name, manufacturer, cost)
        self.__top_speed=top_speed
        self.__material_used=material_used
        self.__engine_type=engine_type

    def display_super_car_details(self):
        self.display_car_details()  # this?
        super().display_car_details()  # or that?
        print(self.__top_speed, self.__material_used, 
              self.__engine_type)

请告诉我使用display_car_details()拨打self.…super().…拨打电话之间的区别。调用上述函数的方法是Super_car类,名称为display_super_car_details()

1 个答案:

答案 0 :(得分:1)

在您的具体情况下,没有区别。如果方法具有相同的名称,则不会使用self.…调用父类,而是再次调用自己的方法,从而创建无限递归。

使用super(),调用始终转到Method Resolution Order中父类中的方法,从而阻止无限递归。有关super()本身的更多详细信息,请参见official documentation

通常,如果您确实需要继承方法,则只需要super(),例如重新实现该方法时。

例如,由于超出了最大递归深度,运行此代码将导致RecursionError。原因是Bar.method1()一遍又一遍地调用本身,因为我们使用的是self.…而不是super().…

class Foo:
    def method1(self):
        print("I just want to be called")

class Bar(Foo):
    def method1(self):
        self.method1()  # oops

b = Bar()
b.method1()

另一方面,这有预期的效果:

class Foo:
    def method1(self):
        print("I just want to be called")

class Bar(Foo):
    def method1(self):
        super().method1()  # sweet

b = Bar()
b.method1()

同样,在您的具体示例中,它无关紧要,因为另一种方法(display_car_details)仅父类中定义,因此它是毫不含糊地调用哪种方法。如果您使用不同的内容覆盖了display_car_details,则super()self的使用会再次产生不同的结果:

class Bar(Foo):
   def method1(self):
       print("You are not supposed to call this")
   def method2(self):
       super().method1()
   def method3(self):
       self.method1()

观察交互式解释器的不同之处:

>>> b = Bar()
>>> b.method1()
You are not supposed to call this
>>> b.method2()
I just want to be called
>>> b.method3()
You are not supposed to call this