Python 如何初始化基(超级)类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3694371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:16:48  来源:igfitidea点击:

How do I initialize the base (super) class?

pythonoop

提问by Jeremy

In Python, consider I have the following code:

在 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?

How do I initialize the SuperClass __init__in the subclass? I am following the Python tutorial and it doesn't cover that. When I searched on Google, I found more than one way of doing. What is the standard way of handling this?

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

采纳答案by Ivo van der Wijk

Python (until version 3) supports "old-style" and new-style classes. New-style classes are derived from objectand are what you are using, and invoke their base class through super(), e.g.

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)

Because python knows about old- and new-style classes, there are different ways to invoke a base method, which is why you've found multiple ways of doing so.

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

For completeness sake, old-style classes call base methods explicitly using the base class, i.e.

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

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

But since you shouldn't be using old-style anymore, I wouldn't care about this too much.

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

Python 3 only knows about new-style classes (no matter if you derive from objector not).

Python 3 只知道新样式的类(无论您是否从其派生object)。

回答by adamk

Both

两个都

SuperClass.__init__(self, x)

or

或者

super(SubClass,self).__init__( x )

will work (I prefer the 2nd one, as it adheres more to the DRY principle).

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

See here: http://docs.python.org/reference/datamodel.html#basic-customization

请参阅此处:http: //docs.python.org/reference/datamodel.html#basic-customization

回答by Bob Jordan

As of python 3.5.2, you can use:

从 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

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

回答by Aaron Hall

How do I initialize the base (super) class?

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

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

如何初始化基(超级)类?

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

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

Use a superobject to ensure you get the next method (as a bound method) in the method resolution order. In Python 2, you need to pass the class name and selfto super to lookup the bound __init__method:

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

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

In Python 3, there's a little magic that makes the arguments to superunnecessary - and as a side benefit it works a little faster:

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

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

Hardcoding the parent like this below prevents you from using cooperative multiple inheritance:

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

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

Note that __init__may only return None- it is intended to modify the object in-place.

请注意,__init__可能只返回None- 它旨在就地修改对象。

Something __new__

某物 __new__

There's another way to initialize instances - and it's the only way for subclasses of immutable types in Python. So it's required if you want to subclass stror tupleor another immutable object.

还有另一种初始化实例的方法——它是 Python 中不可变类型的子类的唯一方法。所以,如果你想子类它需要strtuple或其他不可变对象。

You might think it's a classmethod because it gets an implicit class argument. But it's actually a staticmethod. So you need to call __new__with clsexplicitly.

你可能认为它是一个类方法,因为它有一个隐式的类参数。但它实际上是一个静态方法。所以,你需要打电话__new__cls明确。

We usually return the instance from __new__, so if you do, you also need to call your base's __new__via superas well in your base class. So if you use both methods:

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

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 sidesteps a little of the weirdness of the super calls caused by __new__being a static method, but you still need to pass clsto the non-bound __new__method:

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')