如何覆盖Python中的修饰方法?

sed*_*nym 3 python oop

假设我想扩展以下Python类,其中包括一个我不太了解的装饰器:

from somewhere import some_decorator

class One(object):
    @some_decorator
    def some_method(self):
        do_something()
Run Code Online (Sandbox Code Playgroud)

我应该装饰覆盖的方法吗?换句话说,我可以安全地执行以下操作:

class Two(One):
    def some_method(self):
        super(Two, self).some_method()
Run Code Online (Sandbox Code Playgroud)

还是我需要做:

class Two(One):
    @some_decorator
    def some_method(self):
        super(Two, self).some_method()
Run Code Online (Sandbox Code Playgroud)

Vin*_*ard 5

记住@decorator语法的作用:

@decorator
def foo():
    print "foo"
Run Code Online (Sandbox Code Playgroud)

只是语法糖

def foo():
    print "foo"
foo = decorator(foo)
Run Code Online (Sandbox Code Playgroud)

因此,未经修饰的函数在修饰后就无法再按其名称调用,因为其名称已分配给其他名称。

这意味着,当您super(Two, self).some_method()在子类中调用时,将调用some_method父类中的修饰函数。

知道是否还需要装饰子重写的方法完全取决于您要执行的操作以及装饰程序的工作。但是要知道,如果您调用super(Two, self).some_method(),那么您将调用修饰的函数。


Int*_*rer 5

对于那些想知道边缘情况的人,这里有一个例子:

import functools


def print_hi(func):
    """Decorate a function to print stuff."""

    @functools.wraps(func)
    def wrapper_print_hi(*args, **kwargs):
        print(f"hello and up next: calling {func.__qualname__}")
        return func(*args, **kwargs)

    return wrapper_print_hi


class Foo:
    @print_hi
    def gets_overridden(self) -> None:
        print(f"Foo.gets_overridden")


class DFooNoRedecorate(Foo):
    def gets_overridden(self) -> None:
        """Overridden but didn't re-decorate."""
        print(f"{self.__class__.__name__}.gets_overridden")


class DFooRedecorate(Foo):
    @print_hi
    def gets_overridden(self) -> None:
        """Overridden and re-decorated."""
        print(f"{self.__class__.__name__}.gets_overridden")


class DFooNoRedecorateWithSuperCall(Foo):
    def gets_overridden(self) -> None:
        """Overridden but didn't re-decorate, with super call."""
        super().gets_overridden()
        print(f"{self.__class__.__name__}.gets_overridden")


class DFooRedecorateWithSuperCall(Foo):
    @print_hi
    def gets_overridden(self) -> None:
        """Overridden and re-decorated, with super call."""
        super().gets_overridden()
        print(f"{self.__class__.__name__}.gets_overridden")


if __name__ == "__main__":
    print("---")
    # Decorator doesn't happen when not explicitly called out in subclass
    DFooNoRedecorate().gets_overridden()
    print("---")
    # Decorator does happen when explicitly called out in subclass
    DFooRedecorate().gets_overridden()
    print("---")
    # Decorator happens during super call
    DFooNoRedecorateWithSuperCall().gets_overridden()
    print("---")
    # Decorator happens twice: from explicit call out and during super call
    DFooRedecorateWithSuperCall().gets_overridden()
    print("---")
Run Code Online (Sandbox Code Playgroud)

打印输出:

---
DFooNoRedecorate.gets_overridden
---
hello and up next: calling DFooRedecorate.gets_overridden
DFooRedecorate.gets_overridden
---
hello and up next: calling Foo.gets_overridden
Foo.gets_overridden
DFooNoRedecorateWithSuperCall.gets_overridden
---
hello and up next: calling DFooRedecorateWithSuperCall.gets_overridden
hello and up next: calling Foo.gets_overridden
Foo.gets_overridden
DFooRedecorateWithSuperCall.gets_overridden
---
Run Code Online (Sandbox Code Playgroud)