为了账号安全,请及时绑定邮箱和手机立即绑定

摆脱显式超级

摆脱显式超级

湖上湖 2022-06-02 18:07:21
我想实现这样的东西def after(f):    def inner(*args, **kwargs):        super().f(*args, **kwargs)        f(*args, **kwargs)    return innerclass 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来确定调用装饰器的类实例(尽管如果我有很多类实例则不确定性能)。有没有办法在不牺牲性能的情况下做到这一点?
查看完整描述

1 回答

?
倚天杖

TA贡献1828条经验 获得超3个赞

你可以让你的装饰器工作,你只需要让它成为一个描述符类,而不是一个函数。您需要实现该__set_name__方法以获取对您已添加到的类的引用。使用类引用,您可以进行两个参数的super调用:


import functools


class 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 + y


class Bar(Foo):

    def foo(self, x, y, z):

        return super().foo(x//2, y+1) * z


查看完整回答
反对 回复 2022-06-02
  • 1 回答
  • 0 关注
  • 106 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信