简体   繁体   English

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

[英]How do I initialize the base (super) class?

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?如何在子类中初始化SuperClass __init__ I am following the Python tutorial and it doesn't cover that.我正在关注 Python 教程,但它没有涵盖这一点。 When I searched on Google, I found more than one way of doing.当我在 Google 上搜索时,我找到了不止一种方法。 What is the standard way of handling this?处理这个问题的标准方法是什么?

Python (until version 3) supports "old-style" and new-style classes. Python(直到版本 3)支持“旧式”和新式类。 New-style classes are derived from object and are what you are using, and invoke their base class through super() , eg新式类派生自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, ie为了完整起见,旧式类使用基类显式调用基方法,即

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 object or not). Python 3 只知道新式类(无论是否从object派生)。

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

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

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

Use a super object to ensure you get the next method (as a bound method) in the method resolution order.使用super对象来确保您获得方法解析顺序中的下一个方法(作为绑定方法)。 In Python 2, you need to pass the class name and self to super to lookup the bound __init__ method:在 Python 2 中,您需要将类名和self传递给 super 以查找绑定的__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 super unnecessary - 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.还有另一种初始化实例的方法——它是 Python 中不可变类型的子类的唯一方法。 So it's required if you want to subclass str or tuple or another immutable object.因此,如果您想对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 cls explicitly.所以你需要明确地用cls调用__new__

We usually return the instance from __new__ , so if you do, you also need to call your base's __new__ via super as well in your base class.我们通常从__new__返回实例,因此如果您这样做,您还需要在基类中通过super调用基类的__new__ So if you use both methods:因此,如果您同时使用这两种方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM