摆脱显式超级

我想实现这样的东西


def after(f):

    def inner(*args, **kwargs):

        super().f(*args, **kwargs)

        f(*args, **kwargs)

    return inner



class A:

  def f(self):

    print ('hello')



class B(A):


  @after

  def f(self):

    print ('world')


b = B()

b.f()

那就是我想在我的一些类中去掉显式并用/装饰器super替换它(也许用参数)。@before@after


也就是说,在这个例子中,我想hello world被打印出来。


这个想法是为了增加代码的可读性,因为在一些类中我经常使用多重继承,所以我经常重写方法并且经常不得不使用super().


我想我可以用它inspect来确定调用装饰器的类实例(尽管如果我有很多类实例则不确定性能)。


有没有办法在不牺牲性能的情况下做到这一点?


湖上湖
浏览 108回答 1
1回答

倚天杖

你可以让你的装饰器工作,你只需要让它成为一个描述符类,而不是一个函数。您需要实现该__set_name__方法以获取对您已添加到的类的引用。使用类引用,您可以进行两个参数的super调用:import functoolsclass after:    def __init__(self, method):        self.method = method    def __set_name__(self, owner, name):        self.owner = owner        self.name = name                 # using self.method.__name__ might be better?    def __get__(self, instance, owner):        if instance is None:            return self        return functools.partial(self, instance)    def __call__(self, instance, *args, **kwargs):        assert(self.owner is not None and self.name is not None)        getattr(super(self.owner, instance), self.name)(*args, **kwargs)        return self.method(instance, *args, **kwargs)你也可以这样做before,这几乎是一样的,只是最后两行以相反的顺序(以及一些处理返回值的摆弄)。我注意到这个装饰器比调用super普通方法的用处要小得多,因为你不能有效地与被覆盖的方法返回的值交互,或者改变传递给它的参数。没有before或after修饰的方法可以复制这些类:class Foo:    def foo(self, x, y):        return x + yclass Bar(Foo):    def foo(self, x, y, z):        return super().foo(x//2, y+1) * z
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java