【问题标题】:How do I initialize the base (super) class?如何初始化基(超)类?
【发布时间】:2011-04-11 07:08:20
【问题描述】:

在 Python 中,假设我有以下代码:

class SuperClass(object):
    def __init__(self, x):
        self.x = x
        
class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

如何在子类中初始化SuperClass __init__?我正在关注 Python 教程,但它没有涵盖这一点。当我在谷歌上搜索时,我发现了不止一种方法。处理此问题的标准方法是什么?

【问题讨论】:

    标签: python oop


    【解决方案1】:

    两者

    SuperClass.__init__(self, x)
    

    或

    super(SubClass,self).__init__( x )
    

    会起作用(我更喜欢第二个,因为它更符合 DRY 原则)。

    请看这里:http://docs.python.org/reference/datamodel.html#basic-customization

    【讨论】:

    • 错误。 super 仅适用于新式类,并且是使用新式类时调用基的唯一正确方法。此外,您还需要使用旧式构造显式传递“自我”。
    • @Ivo - OP 在示例中给出了一个新样式类,谈论新样式和旧样式之间的区别没有什么意义,因为没有人应该再使用旧样式了.我提供的链接(给 Python 文档)表明,调用超类 __init__ 的“正确”方式不止一种。
    【解决方案2】:

    Python(直到第 3 版)支持“旧式”和新式类。新式类派生自object,是你正在使用的,通过super()调用它们的基类,例如

    class X(object):
      def __init__(self, x):
        pass
    
      def doit(self, bar):
        pass
    
    class Y(X):
      def __init__(self):
        super(Y, self).__init__(123)
    
      def doit(self, foo):
        return super(Y, self).doit(foo)
    

    因为 python 知道新旧样式的类,所以调用基方法有不同的方法,这就是为什么您找到了多种方法。

    为了完整起见,旧式类使用基类显式调用基方法,即

    def doit(self, foo):
      return X.doit(self, foo)
    

    但既然你不应该再使用旧式了,我不会太在意这个。

    Python 3 只知道新式类(无论你是否派生自 object)。

    【讨论】:

    • 从 Python 3.5.2 开始,您可以省略 super() 的参数,请参阅下面 Bob Jordan 的回答。
    【解决方案3】:

    从 python 3.5.2 开始,您可以使用:

    class C(B):
    def method(self, arg):
        super().method(arg)    # This does the same thing as:
                               # super(C, self).method(arg)
    

    https://docs.python.org/3/library/functions.html#super

    【讨论】:

      【解决方案4】:

      如何初始化基(超)类?

      class SuperClass(object):
          def __init__(self, x):
              self.x = x
      
      class SubClass(SuperClass):
          def __init__(self, y):
              self.y = y
      

      使用super 对象确保您获得方法解析顺序中的下一个方法(作为绑定方法)。在 Python 2 中,您需要将类名和 self 传递给 super 以查找绑定的 __init__ 方法:

       class SubClass(SuperClass):
            def __init__(self, y):
                super(SubClass, self).__init__('x')
                self.y = y
      

      在 Python 3 中,有一个小魔法让 super 的参数变得不必要 - 作为一个附带好处,它的工作速度更快:

       class SubClass(SuperClass):
            def __init__(self, y):
                super().__init__('x')
                self.y = y
      

      像下面这样对父级进行硬编码会阻止您使用协作多重继承:

       class SubClass(SuperClass):
            def __init__(self, y):
                SuperClass.__init__(self, 'x') # don't do this
                self.y = y
      

      注意__init__ may only return None - 它旨在就地修改对象。

      某事__new__

      还有另一种初始化实例的方法——它是 Python 中不可变类型的子类的唯一方法。因此,如果您想继承 str 或 tuple 或其他不可变对象,则需要它。

      你可能认为它是一个类方法,因为它有一个隐含的类参数。但它是actually a staticmethod。所以你需要用cls显式调用__new__。

      我们通常从__new__ 返回实例,因此如果这样做,您还需要在基类中通过super 调用基类的__new__。因此,如果您同时使用这两种方法:

      class SuperClass(object):
          def __new__(cls, x):
              return super(SuperClass, cls).__new__(cls)
          def __init__(self, x):
              self.x = x
      
      class SubClass(object):
          def __new__(cls, y):
              return super(SubClass, cls).__new__(cls)
      
          def __init__(self, y):
              self.y = y
              super(SubClass, self).__init__('x')
      

      Python 3 回避了一些由 __new__ 是静态方法引起的超级调用的怪异之处,但您仍然需要将 cls 传递给未绑定的 __new__ 方法:

      class SuperClass(object):
          def __new__(cls, x):
              return super().__new__(cls)
          def __init__(self, x):
              self.x = x
      
      class SubClass(object):
          def __new__(cls, y):
              return super().__new__(cls)
          def __init__(self, y):
              self.y = y
              super().__init__('x')
      

      【讨论】:

        猜你喜欢
        • 2021-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 2020-02-05
        • 2019-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多