【问题标题】:How to decorate inherited method - Python如何装饰继承的方法 - Python
【发布时间】:2019-08-02 23:10:39
【问题描述】:

我必须装饰一个继承的方法,但它装饰了所有继承的方法。基本上我必须创建一个装饰器来装饰类中的一个方法。

测试看起来像这样

@my_decorator
    class TestClass(Subclass):
        pass

t = TestClass()
t.say_hi

假设我的子类看起来像这样

class SubClass():
    def __init__(self):
        pass

    def say_hi():
        print("Hi")

    def say_wow():
        print("wow")

现在我必须创建my_decorator,它必须在打印“Hi”之前将继承的函数say_hi() 装饰为print("*****")

我尝试这样做,但装饰器适用于来自SubClass的所有方法

def my_decorator(cls)
    def say_hi():
        print("*********")
        cls.say_hi()

    return say_hi()

自然它适用于子类的每个函数,但我如何让它只适用于say_hi() 函数? - 它还返回一个TypeError "NoneType" object is not callable

【问题讨论】:

  • 装饰一个类和装饰一个in类的方法有很大的不同。您展示的装饰器,除了错误之外,在调用它的say_hi 方法之后,看起来它用None 替换了SubClass
  • 那就是我不知道该怎么做。我只想装饰TestClass的一种方法
  • 你......装饰方法,而不是类。
  • 对不起,对python很新,我仍然不能只装饰方法,因为这些是测试数据,我不能改变它们

标签: python decorator python-decorators


【解决方案1】:

首先让我们修复SubClass,因为实例方法在定义时需要一个显式的实例参数:

class SubClass():
    def __init__(self):
        pass

    def say_hi(self):
        print("Hi")

    def say_wow(self):
        print("wow")

现在您希望装饰器在调用原始方法之前将say_hi 方法替换为打印'****' 的方法。让我们写一个装饰器来做这个(*):

def my_decorator(cls):
    orig = cls.say_hi          # save the original method
    def say_hi(self):          # define a new one
        print('****')
        return orig(self)      # ... calling the original method
    cls.say_hi = say_hi        # replace the method in the class
    return cls

然后您可以使用:

@my_decorator
class TestClass(SubClass):
    pass
t = TestClass()
t.say_hi()

并按预期获得:

****
Hi

(*) 这是一个非常简单的装饰器,只能替换 say_hi(self) 方法:既没有不同的名称,也没有额外的参数,但装饰器可以更智能...

【讨论】:

  • 非常感谢,它现在完美运行。我用python编写的第一个程序让我抓狂:)
【解决方案2】:

如果你想装饰一个方法,那么装饰这个方法,而不是包含它的类。如果你想要一个 new 类,那么应用于该类的装饰器需要返回一个类。

def print_banner(f):
    def _(*args, **kwargs):
       print("****")
       f(*args, **kwargs)
    return _

class SubClass():
    def __init__(self):
        pass

    @print_banner
    def say_hi(self, ):
        print("Hi")

    def say_wow(self):
        print("wow")

【讨论】:

  • 然而,我不是装饰班级的人,但我得到了将在我的程序上运行的测试,它要求我为这个 TestClass 制作一个装饰器。这是一个练习,否则我只会装饰继承的方法
猜你喜欢
  • 2018-01-16
  • 1970-01-01
  • 2014-09-06
  • 2019-03-15
  • 2020-06-03
  • 2012-11-14
  • 2019-11-27
  • 2019-10-02
  • 2011-03-01
相关资源
最近更新 更多