"super(type(self), self)" 的快捷键是什么?

11

当我在子类中重写一个方法时,我经常这样做:

def method_x(self):
    x = super(type(self), self).method_x()

    [Some extra code]
    return x

我的问题是:有没有一种简便方式可以达到 super(type(self), self) 的效果?


19
警告任何阅读此内容的人:上述代码是错误的。不要模仿它! - Glenn Maynard
Glenn, Duncan:感谢指出这个错误。我需要在我的代码中使用grep并进行更改。 - Gary van der Merwe
@Glenn Maynard:不确定我理解为什么你认为这是“错误”的。使用super(self.__class__, self)会更好吗? - martineau
9
@martineau: 不,那样不好。 super的第一个参数是继承链中的当前类,因此超级可以找出下一个类是哪个。说type(self)self.__class__将给出最高类,如果那是前面的类,就会导致无限循环。请参见:http://pastebin.com/vhu5urCL - Glenn Maynard
@Glenn Maynard:啊哈!现在我明白了。感谢您忍耐我的迟钝 - 您的回复以及示例代码最终使问题变得清晰明了。 - martineau
1个回答

20
不要这么做:如果super只能使用type(self)作为第一个参数,那么它就没有必要在第一次编写时采用两个参数的形式。在这里,您必须传递实际的类,而不是可能因为类已被子类化而发生变化的表达式。
super的第一个参数需要是包含当前方法定义的类,因为您告诉super从基类列表的哪个位置开始搜索。
Python 3知道这一点,并在编译时神奇地处理super(),但在Python 2.x中,它只是一个普通函数,因此无法自行找出这些参数。
[编辑添加我的初始观点] 实际上,在Python 2.x中还有另一种不常用的使用super()的方法。您可以使用未绑定形式的super,并在访问时将其绑定:
>>> class A(object):
    def foo(self):
        print "A.foo"


>>> class B(A):
    def foo(self):
        self.__super.foo()
        print "B.foo"


>>> B._B__super = super(B)
>>> class C(A):
    def foo(self):
        self.__super.foo()
        print "C.foo"


>>> C._C__super = super(C)
>>> class D(C,B): pass

>>> D._D__super = super(D)
>>> D().foo()
A.foo
B.foo
C.foo

这里有一个重要的注意点:您必须为每个super对象使用不同的名称进行存储,可以通过使用self.__super来实现,但是您不能直接在类定义中创建未绑定的super(因为如果该类尚不存在,则无法命名该类),如果在外部创建它,则必须手动混淆名称以确保为类设置了正确的__super对象。对于Python 2.6及更高版本,您可能可以将其包装为一个类装饰器。


1
我建议不要推荐这个;做一些如此不寻常的事情并没有太大的收获。 - Glenn Maynard
2
是的,它可能会有些混乱,这也许是为什么它使用较少的原因,但我认为应该将其作为一种选择提出。当然,更好的选择是直接使用Python 3.x(前提是它支持你所需的任何库)。 - Duncan
今天我尝试使用Python3。我正在使用Pylons Pyramid,但是它和一些依赖项目前还不支持py3,所以我将在几个月后再来检查。 - Gary van der Merwe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接