python super().__init__()参数_用__init __()方法理解Python super()方法[duplicate]

文章目录

This question already has an answer here:

我试图理解super()的用法。从外观上看,这两个子类都可以创建,就好了。

我很想知道以下两个子类的实际区别。

class Base(object):

def __init__(self):

print "Base created"

class ChildA(Base):

def __init__(self):

Base.__init__(self)

class ChildB(Base):

def __init__(self):

super(ChildB, self).__init__()

ChildA()

ChildB()

super()`可以避免显式地引用基类,这可以很好。但主要优势来自多重继承,其中各种有趣的东西可以发生。如果还没有,请参阅super上的标准文档。 p>

请注意,Python

3.0中的语法已更改:您可以说super().__ init __(),而不是super(ChildB,self).__ init __() IMO更好一些。

I’m trying to understand super()

我们使用super的原因是,可能使用协作多重继承的子类将在方法解析顺序(MRO)中调用正确的下一个父类函数。

在Python 3中,我们可以这样调用它:

class ChildB(Base):

def __init__(self):

super().__init__()

在Python 2中,我们需要像这样使用它:

super(ChildB, self).__init__()

没有超级,你在使用多继承方面的能力有限:

Base.__init__(self) # Avoid this.

我在下面进一步解释。

“What difference is there actually in this code?:”

class ChildA(Base):

def __init__(self):

Base.__init__(self)

class ChildB(Base):

def __init__(self):

super(ChildB, self).__init__()

# super().__init__() # you can call super like this in Python 3!

这个代码的主要区别在于你在 init 中用 super 得到一个间接层,它使用当前类来确定下一个类的 init

`在MRO中查找。

If Python didn’t have super

这里的代码实际上与super非常相似(它是如何在C中实现的,减去一些检查和回退行为,并转换为Python):

class ChildB(Base):

def __init__(self):

mro = type(self).mro() # Get the Method Resolution Order.

check_next = mro.index(ChildB) + 1 # Start looking after *this* class.

while check_next < len(mro):

next_class = mro[check_next]

if '__init__' in next_class.__dict__:

next_class.__init__(self)

break

check_next += 1

写得更像本机Python:

class ChildB(Base):

def __init__(self):

mro = type(self).mro()

for next_class in mro[mro.index(ChildB) + 1:]: # slice to end

if hasattr(next_class, '__init__'):

next_class.__init__(self)

break

如果我们没有super对象,我们必须在每个地方编写这个手册代码(或者重新创建它!),以确保我们调用方法解析顺序!

super如何在Python 3中完成这个工作,而不需要明确地告诉它被调用的方法是哪个类和实例呢?

它获取调用堆栈框架,并找到该类(隐式存储为本地自由变量,使调用函数成为类的闭包)以及该函数的第一个参数,这应该是通知它使用哪个方法解析顺序(MRO)的实例或类。

因为它需要MRO的第一个参数,所以使用super与静态方法是不可能的。

Criticisms of other answers:super() lets you avoid referring to the base class explicitly, which can be

nice. . But the main advantage comes with multiple inheritance, where all

sorts of fun stuff can happen. See the standard docs on super if you haven’t

already.

这是相当有趣的,并没有告诉我们很多,但是super的目的不是为了避免写父类。重点是确保调用方法解析顺序(MRO)中的下一个方法。这在多重继承中变得重要。

我会在这里解释。

class Base(object):

def __init__(self):

print("Base init'ed")

class ChildA(Base):

def __init__(self):

print("ChildA init'ed")

Base.__init__(self)

class ChildB(Base):

def __init__(self):

print("ChildB init'ed")

super(ChildB, self).__init__()

让我们创建一个我们希望在Child之后调用的依赖项:

class UserDependency(Base):

def __init__(self):

print("UserDependency init'ed")

super(UserDependency, self).__init__()

现在请记住,ChildB使用super,ChildA不会:

class UserA(ChildA, UserDependency):

def __init__(self):

print("UserA init'ed")

super(UserA, self).__init__()

class UserB(ChildB, UserDependency):

def __init__(self):

print("UserB init'ed")

super(UserB, self).__init__()

和UserA不会调用UserDependency方法:

>>> UserA()

UserA init'ed

ChildA init'ed

Base init'ed

但是UserB,因为ChildB使用super,所以!

>>> UserB()

UserB init'ed

ChildB init'ed

UserDependency init'ed

Base init'ed

Criticism for another answer

在任何情况下,你都不应该做下面的问题,而另一个答案建议,因为当你继承ChildB时,你一定会得到错误:

super(self.__class__, self).__init__() # Don't do this. Ever.

(这个答案不是很聪明或者特别有趣,但是尽管在评论中有直接的批评,还有超过17个投票,回答者仍然坚持这样做,直到一位好心的编辑解决了他的问题。)

解释:这个答案建议调用超级像这样:

super(self.__class__, self).__init__()

这完全是错误的。 super让我们查看MRO中的下一个父级(参见本答案的第一部分)。如果你告诉super我们在子实例的方法中,它会查找下一个方法(可能是这个),导致递归,可能导致逻辑失败(在回答者的例子中, )或超过递归深度时的RuntimeError。

>>> class Polygon(object):

... def __init__(self, id):

... self.id = id

...

>>> class Rectangle(Polygon):

... def __init__(self, id, width, height):

... super(self.__class__, self).__init__(id)

... self.shape = (width, height)

...

>>> class Square(Rectangle):

... pass

...

>>> Square('a', 10, 10)

Traceback (most recent call last):

File "", line 1, in

File "", line 3, in __init__

TypeError: __init__() missing 2 required positional arguments: 'width' and 'height'

未经作者同意,本文严禁转载,违者必究!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值