在Python-2.x中super()是否损坏? [英] Is super() broken in Python-2.x?

查看:87
本文介绍了在Python-2.x中super()是否损坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常说 super 应该是

It's often stated that super should be avoided in Python 2. I've found in my use of super in Python 2 that it never acts the way I expect unless I provide all arguments such as the example:

super(ThisClass, self).some_func(*args, **kwargs)

在我看来,这违背了使用super()的目的,它既不简洁也不比TheBaseClass.some_func(self, *args, **kwargs)好得多.在大多数情况下,方法解析顺序是一个遥远的童话.

It seems to me this defeats the purpose of using super(), it's neither more concise, or much better than TheBaseClass.some_func(self, *args, **kwargs). For most purposes method resolution order is a distant fairy tale.

  • Other than the fact that 2.7 is the last major release to Python 2, why does super remain broken in Python 2?
  • How and why has Python 3's super changed? Are there any caveats?
  • When and why should I use super going forward?

推荐答案

super()并未损坏-不应将其视为调用基类方法的标准方法.使用Python 3.x并没有改变.唯一改变的是,在标准情况下,无需传递参数self, cls,因为self是当前函数的第一个参数,而cls是当前正在定义的类.

super() is not broken -- it just should not be considered the standard way of calling a method of the base class. This did not change with Python 3.x. The only thing that changed is that you don't need to pass the arguments self, cls in the standard case that self is the first parameter of the current function and cls is the class currently being defined.

关于何时实际使用super()的问题,我的回答是:几乎不会.我个人尝试避免使用使super()有用的多重继承.

Regarding your question when to actually use super(), my answer would be: hardly ever. I personally try to avoid the kind of multiple inheritance that would make super() useful.

编辑:我曾经遇到的一个真实示例:我有一些类定义了run()方法,其中有些具有基类.我使用super()来调用继承的构造函数-我认为这并不重要,因为我仅使用单一继承:

Edit: An example from real life that I once ran into: I had some classes defining a run() method, some of which had base classes. I used super() to call the inherited constructors -- I did not think it mattered because I was using single inheritance only:

class A(object):
    def __init__(self, i):
        self.i = i
    def run(self, value):
        return self.i * value

class B(A):
    def __init__(self, i, j):
        super(B, self).__init__(i)
        self.j = j
    def run(self, value):
        return super(B, self).run(value) + self.j

试想一下,其中有几个类,都具有单独的构造函数原型,并且都具有与run()相同的接口.

Just imagine there were several of these classes, all with individual constructor prototypes, and all with the same interface to run().

现在,我想为所有这些类添加一些其他功能,例如日志记录.附加功能要求在所有这些类上定义附加方法,例如info().我不想入侵原始类,而是定义从原始类继承的第二组类,添加info()方法并从提供实际日志记录的混入中继承.现在,我再也不能在构造函数中使用super()了,所以我使用了直接调用:

Now I wanted to add some additional functionality to all of these classes, say logging. The additional functionality required an additional method to be defined on all these classes, say info(). I did not want to invade the original classes, but rather define a second set of classes inheriting from the original ones, adding the info() method and inheriting from a mix-in providing the actual logging. Now, I could not use super() in the constructor any more, so I used direct calls:

class Logger(object):
    def __init__(self, name):
        self.name = name
    def run_logged(self, value):
        print "Running", self.name, "with info", self.info()
        return self.run(value)

class BLogged(B, Logger):
    def __init__(self, i, j):
        B.__init__(self, i, j)
        Logger.__init__("B")
    def info(self):
        return 42

这里一切都停止了.基类构造函数中的super()调用突然调用Logger.__init__(),而BLogged对此无能为力.除了删除B本身中的super()调用外,实际上没有任何方法可以实现此目的.

Here things stop working. The super() call in the base class constructor suddenly calls Logger.__init__(), and BLogged can't do anything about it. There is actually no way to make this work, except for removing the super() call in B itself.

[另一个编辑:从这里和其他答案下面的所有评论来看,我似乎没有提出我的观点.这是使用super()来使此代码起作用的方法:

[Another Edit: I don't seem to have made my point, judging from all the comments here and below the other answers. Here is how to make this code work using super():

class A(object):
    def __init__(self, i, **kwargs):
        super(A, self).__init__(**kwargs)
        self.i = i
    def run(self, value):
        return self.i * value

class B(A):
    def __init__(self, j, **kwargs):
        super(B, self).__init__(**kwargs)
        self.j = j
    def run(self, value):
        return super(B, self).run(value) + self.j

class Logger(object):
    def __init__(self, name, **kwargs):
        super(Logger,self).__init__(**kwargs)
        self.name = name
    def run_logged(self, value):
        print "Running", self.name, "with info", self.info()
        return self.run(value)

class BLogged(B, Logger):
    def __init__(self, **kwargs):
        super(BLogged, self).__init__(name="B", **kwargs)
    def info(self):
        return 42

b = BLogged(i=3, j=4)

使用显式超类调用对此进行比较.您可以选择自己喜欢的版本.]

Compare this with the use of explicit superclass calls. You decide which version you prefer.]

这个和类似的故事就是为什么我认为super() 不应被视为基类的标准调用方法的原因.这并不意味着super()已损坏.

This and similar stories are why I think that super() should not be considered the standard way of calling methods of the base class. It does not mean super() is broken.

这篇关于在Python-2.x中super()是否损坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆