Python中super(type, obj) 和 super(type, type)的区别在哪?

class Person:
    def __init__(self, name):
        self.name = name
    # Getter function
    @property
    def name(self):
        return self._name
    # Setter function
    @name.setter
    def name(self, value):       
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self._name = value
    # Deleter function
    @name.deleter
    def name(self):
        raise AttributeError("Can't delete attribute")

class SubPerson(Person): @property def name(self): print(‘Getting name’) return super().name @name.setter def name(self, value): print(‘Setting name to’, value) super(SubPerson, SubPerson).name.set(self, value) @name.deleter def name(self): print(‘Deleting name’) super(SubPerson, SubPerson).name.delete(self)

s = SubPerson(‘Guido’) print(s.name)

当我将 super(SubPerson, SubPerson).name.__set__(self, value) 变成 super(SubPerson, self).name.__set__(self, value), 报了这样的错误

AttributeError: 'SubPerson' object has no attribute '_name'

为什么?


Python中super(type, obj) 和 super(type, type)的区别在哪?

3 回复

super(type, obj)super(type, type) 的核心区别在于第二个参数 objtype 决定了返回的 super 对象绑定到哪个实例(或类),这直接影响了后续方法解析顺序(MRO)的查找起点。

1. super(type, obj)

  • 作用:返回一个绑定到实例 objsuper 对象。
  • 要求obj 必须是 type 的实例(或子类实例)。
  • 行为:调用方法时,会从 type 在 MRO 中的下一个类开始查找,并将 obj 作为 self 自动传入。
  • 典型用途:在实例方法中调用父类方法,例如 super(CurrentClass, self).some_method()

2. super(type, type)

  • 作用:返回一个绑定到类 typesuper 对象。
  • 要求:第二个 type 必须是第一个 type 的子类(或它本身)。
  • 行为:调用方法时,会从 type 在 MRO 中的下一个类开始查找,但期望方法是 @classmethod 装饰的类方法,因为调用时会自动将第二个 type 作为 cls 传入。
  • 典型用途:在类方法中调用父类的类方法,例如 super(CurrentClass, cls).some_classmethod()

代码示例对比:

class A:
    def method(self):
        return "A.method"

    @classmethod
    def class_method(cls):
        return "A.class_method"

class B(A):
    def method(self):
        # 绑定到实例 self,查找 A.method
        return super(B, self).method() + " -> B.method"

    @classmethod
    def class_method(cls):
        # 绑定到类 cls,查找 A.class_method
        return super(B, cls).class_method() + " -> B.class_method"

b = B()
print(b.method())          # 输出: A.method -> B.method
print(B.class_method())    # 输出: A.class_method -> B.class_method

关键点总结:

  • super(type, obj) 用于实例方法,自动绑定实例 obj 作为 self
  • super(type, type) 用于类方法,自动绑定类 type 作为 cls
  • 在 Python 3 中,你可以简写为 super()(在实例方法中)和 super()(在类方法中),编译器会自动填充正确的参数。

一句话建议: 根据你是在实例方法还是类方法中调用,来正确选择 super 的绑定对象。


标准里面没有 super(SubPerson, SubPerson) 这种写法吧……即使你手头的 CPython 能工作,也不代表未来的 CPython,或者别的 Python 比如 IronPython 和 PyPy 能工作。建议规避掉这种写法。

我已经知道问题所在,结贴了:)

回到顶部