在Python 2.6+中使用super(...)时如何避免样板?

时间:2012-08-04 22:43:55

标签: python oop python-2.7 python-2.6 super

在这样的事情中是否有好的(适合在实际项目中使用)方法或减少样板

class B(A):
    def qqq(self): # 1 unwanted token "self"
        super(B, self).qqq() # 7 unwanted tokens plus 2 duplications ("B", "qqq")
        do_something()

我希望它看起来更像这样:

class B(A):
    def qqq:
        super
        do_something()

或(更现实地)

class B(A):
    @autosuper_before
    def qqq(self):
        do_something()

在Python 2.6+中是否有可能没有明显的黑客攻击?

@link super() in Python 2.x without args

1 个答案:

答案 0 :(得分:4)

<强> TL;博士

正如OP所说的那样“在Python 2.6+中是否有可能没有明显的黑客攻击?”,答案是:

长版

您可以创建一个简单的装饰器,使用此方法调用下一个父级。问题是你无法控制你想传递的参数。

修改 这对于已经使用autosuper的子类不起作用,因为它会选择错误的类并进行无限循环。

def autosuper(fn):
    def f(self, *args, **kw):
        cl = super(type(self), self)
        getattr(cl, fn.__name__)(*args, **kw)
        return fn(self, *args, **kw)
    return f

怎么可以这样做? Python 3.x确实有一个不带参数的super函数!

不幸的是,Python 3.x的super是一个,同时也是一个关键字,因为它的名称只会改变它当前环境揭示了一个名为__class__的变量,它是您需要使用的正确类!

如果检查类中声明的函数内的框架,则没有__class__变量,并且框架co_freevars属性的f_code属性为空。当您编写名称super(不需要调用它)时,__class__字符串将出现在co_freevars中,这意味着它来自另一个闭包。此外,如果您尝试在不使用super的情况下访问__class__变量,它将使用LOAD_DEFER字节码,原因与此相同,而不是LOAD_GLOBAL,这与每个未定义的名称一样正常。< / p>

这太疯狂了,你不能只做hyper = super并在没有参数的情况下调用这个新的hyper变量(这与super完全相同)。

因为我无法在Python解释器中与这么多黑魔法竞争,并且因为autosuper装饰器未在类中声明(所以它永远不能访问__class__变量,即使那是可能在Python 2.x中,我不会尝试编写一个新的装饰器,并且会在这里留下这个答案,作为对其他想要这样做的人的警告。

可能有一些hackeries可以找到合适的类来使用,但我不会那么深入。需要考虑的事项:

  • 当应用装饰器时,该类尚不存在,所以这应该在调用装饰函数时完成。
  • 正在修饰的函数还不是unbound method(从Py3k中删除了),因此您无法检查im_class属性。
  • 该框架似乎不包含用于进行此调用的类的任何信息(除非__class__变量当然存在,并且可以获得对它的引用)
  • OP提供的
  • This answer也非常破碎,因为它做了很多错误的假设,并且在装饰函数方面存在问题。