Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 摆脱显式超链接_Python_Python 3.x_Python Decorators - Fatal编程技术网

Python 摆脱显式超链接

Python 摆脱显式超链接,python,python-3.x,python-decorators,Python,Python 3.x,Python Decorators,我想实现这样的东西 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

我想实现这样的东西

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
/
@before
decorator(可能带有参数)替换它

也就是说,在本例中,我希望打印
hello world


这样做的目的是提高代码的可读性,因为在某些类中我经常使用多重继承,所以我经常重写方法,并且经常必须使用
super()

我想我可以使用
inspect
来确定调用decorator的类实例(尽管如果我有许多类实例,则不确定性能)


有没有一种方法可以在不牺牲性能的情况下实现这一点?

您可以让decorator正常工作,您只需要将它变成一个描述符类,而不是一个函数。您需要实现
\uuuu set\u name\uuuu
方法来获取对已添加到的类的引用。使用类引用,您可以进行双参数
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)
您也可以在之前执行一个
,这几乎是相同的,只是最后两行的顺序相反(并对返回值进行一些处理)

我要注意的是,这个decorator通常没有正常方式调用
super
有用,因为您无法有效地与重写方法返回的值交互,也无法更改传递给它的参数。没有任何
before
before
修饰方法可以复制这些类:

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

调用
super()
有什么不对?使用这样的装饰器如何改善这种情况?其目的是提高代码的可读性。我必须经常编写类似于
super()的东西。一些方法(*args,**kwargs)
。也就是说,我不想重复自己指定python可以自动获取的方法和参数(在
super()
行中)。使用
super()
比创建只有您使用的新包装更具可读性。@me2只认为这会降低代码的可读性。1) 没有那么明确。2) 它混淆了执行顺序,因为该函数的实际内容现在已经以装饰器的形式移到了它之外。所以,如果你想知道发生了什么,你必须在body和decorator之间来回跳跃,看看这个函数应该做什么。decorator是用来扩充功能的,而不是吞下部分内容。3)它不会在代码行方面保存任何内容。酷!请更正输入错误。是的,这不是一种通用的方法,我还要补充一点,有时为不同的类调用
super
可能会有用,或者有时您可能需要在
之前
之后
。但这两个装饰师似乎足以满足我的大部分需求。谢谢