如何在Python中覆盖装饰方法?

时间:2015-12-10 16:12:18

标签: python oop

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

from somewhere import some_decorator

class One(object):
    @some_decorator
    def some_method(self):
        do_something()

我应该装饰被覆盖的方法吗?换句话说,我可以安全地做到:

class Two(One):
    def some_method(self):
        super(Two, self).some_method()

或者我需要这样做:

class Two(One):
    @some_decorator
    def some_method(self):
        super(Two, self).some_method()

2 个答案:

答案 0 :(得分:4)

记住@decorator语法的作用:

@decorator
def foo():
    print "foo"

只是

的语法糖
def foo():
    print "foo"
foo = decorator(foo)

因此,未装饰的功能在装饰后不再可以通过其名称来调用,因为它的名称已被分配给其他东西。

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

知道你是否还需要装饰子覆盖方法完全取决于你想做什么以及装饰器做什么。但要知道,如果你打电话给super(Two, self).some_method(),那么你将调用装饰函数。

答案 1 :(得分:0)

对于那些想知道边缘情况的人,下面是一个示例:

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("---")

打印输出:

---
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
---