我正在努力了解super()
的工作原理。我理解它的作用,但我不了解幕后发生的事情的机制。我不太清楚的一点是:
class b(a):
def __init__(self, name, age):
self.name=name
self.age=age
super(b, self).__init__(name, age)
和
class b(a):
def __init__(self, name, age):
super(b, self).__init__(name, age)
self.name=name
self.age=age
也许这两个例子没有区别,但我知道还有其他情况super()
的位置很重要。例如,这个我需要帮助的Django方法,我被指示将super()
移到if语句之上,而不是在底部。我想知道为什么这很重要。
class Mymodel(models.Model):
photo = models.ImageField(upload_to="...", blank=True)
def save(self, *args, **kwargs):
image_resized = kwargs.pop('image_resized',False)
super(Mymodel, self).save(*args, **kwargs)
if self.photo and image_resized:
basewidth = 300
filename = self.get_source_filename()
image = Image.open(filename)
wpercent = (basewidth/float(image.size[0]))
hsize = int((float(image.size[1])*float(wpercent)))
img = image.resize((basewidth,hsize), PIL.Image.ANTIALIAS)
self.photo = img
self.save(image_resized = True)
答案 0 :(得分:8)
您的两个版本的类b
(如果有)之间的差异完全取决于超类(a
)的作用。让我们来看一个更简单,更清晰的例子:
class a(object):
def __init__(self):
self.foo = 23
class b1(a):
def __init__(self, name, age):
self.foo = 42
super(b, self).__init__()
class b2(a):
def __init__(self, name, age):
super(b, self).__init__()
self.foo = 42
类b1
首先将foo
设置为42 - 然后(实际上)调用a.__init__
,将相同的属性重置为23.因此,self.foo
最终成为在b1.__init__
之后价值23。
类b2
首先(在实践中)调用a.__init__
,将foo
设置为23 - 然后,它会将相同的属性重置为42.因此,{{1} } self.foo
之后最终值42。
我发现这种情况更简单,更清晰,因为它归结为两个不同值的赋值给同一个东西 - 所以它非常直观,第二个赋值会覆盖第一个赋值的效果。因此,在子类之前调用超类的b2.__init__
做自己的事情意味着子类会覆盖超类中完成的部分或全部设置;之后调用它意味着完全相反。
完全相同的推理适用于初始化操作,这些操作比__init__
属性的简单赋值更微妙:它是关于哪个类,子或超级,可以调整或否决完成的事情另一方面(两个初始化都很重要)。
在OOP中,希望子类更改"覆盖"更常见。超类,反之亦然;因此,调用超类self
的正常时间恰好位于子类的开头 - 这更加惯用。当需要更微妙的效果时,可以稍后调用超类__init__
,但在那些"稍微异常"通常情况下,它会帮助读者的代码添加注释来解释正在做什么以及为什么......
答案 1 :(得分:1)
super().__init__()
执行“this”(或py中的self)继承自的类的构造函数。因此,如果存在修改继承变量的操作,或者需要在继承的类的构造函数中使用的变量,则必须先调用它。
否则,只要你不需要它就被调用它并不重要。虽然最好总是在构造函数的开头调用它,这样你总能知道它的调用位置(如果需要的话)。