在方法的开头或结尾调用 super() 有什么区别?
What is the difference between super() being called at the beginning or end of a method?
我正在尝试了解 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)
super().__init__()
执行 "this"(或 py 中的 self)继承的 class 的构造函数。所以如果有修改继承变量的动作,或者在继承的class的构造函数中需要用到的变量,必须先调用。
否则,只要您还不需要它,何时调用它都没有关系。虽然最佳做法是始终在构造函数的开头调用它,以便您始终知道它在哪里被调用(如果需要的话)。
class b
(如果有)的两个版本之间的区别完全取决于超级class(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
Class b1
首先将 foo
设置为 42——然后(实际上)调用 a.__init__
,将相同的属性重置为 23。因此,self.foo
在 b1.__init__
之后最终值 23。
Class b2
首先(实际上)调用 a.__init__
,它将 foo
设置为 23 —— 然后,它继续将相同的属性重置为 42。因此,self.foo
在 b2.__init__
之后最终值 42。
我发现这种情况更简单、更清晰,因为它归结为对同一事物进行两次不同值的赋值——因此非常直观的是,第二次赋值覆盖了第一次赋值的效果。因此,在 subclass 执行自己的操作之前调用 superclass 的 __init__
意味着 subclass 会覆盖 superclass 中完成的部分或全部设置class;之后调用它,意思正好相反。
完全相同的推理适用于初始化操作,这些操作比对 self
属性的简单赋值要微妙一些:它是关于 class、sub 或 super 进行调整或否决的由对方完成的事情(就两个初始化而言非常重要)。
在 OOP 中,希望子 class 到 "override" 超级 class 比相反更常见;因此,调用 superclass 的 __init__
的正常时间恰好在 subclass 的开头——这更符合习惯。当需要更微妙的效果时,稍后调用 superclass 的 __init__
很好,但在那些 "slightly anomalous" 情况下,它通常会帮助代码的 reader添加评论解释正在做什么以及为什么...
我正在尝试了解 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)
super().__init__()
执行 "this"(或 py 中的 self)继承的 class 的构造函数。所以如果有修改继承变量的动作,或者在继承的class的构造函数中需要用到的变量,必须先调用。
否则,只要您还不需要它,何时调用它都没有关系。虽然最佳做法是始终在构造函数的开头调用它,以便您始终知道它在哪里被调用(如果需要的话)。
class b
(如果有)的两个版本之间的区别完全取决于超级class(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
Class b1
首先将 foo
设置为 42——然后(实际上)调用 a.__init__
,将相同的属性重置为 23。因此,self.foo
在 b1.__init__
之后最终值 23。
Class b2
首先(实际上)调用 a.__init__
,它将 foo
设置为 23 —— 然后,它继续将相同的属性重置为 42。因此,self.foo
在 b2.__init__
之后最终值 42。
我发现这种情况更简单、更清晰,因为它归结为对同一事物进行两次不同值的赋值——因此非常直观的是,第二次赋值覆盖了第一次赋值的效果。因此,在 subclass 执行自己的操作之前调用 superclass 的 __init__
意味着 subclass 会覆盖 superclass 中完成的部分或全部设置class;之后调用它,意思正好相反。
完全相同的推理适用于初始化操作,这些操作比对 self
属性的简单赋值要微妙一些:它是关于 class、sub 或 super 进行调整或否决的由对方完成的事情(就两个初始化而言非常重要)。
在 OOP 中,希望子 class 到 "override" 超级 class 比相反更常见;因此,调用 superclass 的 __init__
的正常时间恰好在 subclass 的开头——这更符合习惯。当需要更微妙的效果时,稍后调用 superclass 的 __init__
很好,但在那些 "slightly anomalous" 情况下,它通常会帮助代码的 reader添加评论解释正在做什么以及为什么...