32

可能重复:
类方法可以是装饰器吗?

这是一个例子。

class myclass:
    def __init__(self):
        self.start = False

    def check(self):
        return not self.start

    def doA(self):
        if self.check():
            return
        print('A')

    def doB(self):
        if self.check():
            return
        print('B')

如您所见,我想以装饰器的方式编写检查操作,但是经过多次尝试后,我发现我只能在课堂外编写该方法。请教我如何在课堂内编写它,谢谢

编辑:

我可以这样写代码:

def check(func):
    def checked(self):
        if not self.start:
            return
        func(self)
    return checked

class myclass:
    def __init__(self):
        self.start = False

    @check
    def doA(self):
        print('A')

    @check
    def doB(self):
        print('B')


a = myclass()

a.doA()
a.doB()

a.start = True

a.doA()
a.doB()

但我认为这不是一个好习惯,我想在我的类中定义检查方法。

4

2 回答 2

62

虽然我不认为这一直是完全需要的,但这里是你在课堂上制作装饰器的方法。self由于方法绑定到后者的方式,它有点麻烦。通常使用简单的函数装饰器,您不必担心这一点。

要求是:

  1. 装饰器需要在使用它的方法之前定义
  2. 它需要用来functools.wraps正确保存绑定的方法

例子:

from functools import wraps

class myclass:
    def __init__(self):
        self.start = False

    def _with_check(f):
        @wraps(f)
        def wrapped(inst, *args, **kwargs):
            if inst.check():
                return
            return f(inst, *args, **kwargs)
        return wrapped

    def check(self):
        return self.start

    @_with_check
    def doA(self):
        print('A')

    @_with_check
    def doB(self):
        print('B')

我将它设置为受保护的成员,因为它实际上并不是其他人需要在课堂之外使用的东西。它仍然保留您的公开check()呼吁以供自己使用。装饰器在调用目标方法之前简单地包装调用它。

于 2012-12-13T03:22:48.650 回答
1

If you have a need to modify how many or all methods on a class are called, but you only want to apply that change in behavior to that class and its subclasses, just use __getattr__() and/or __getattribute__() to perform your behavior instead.

于 2012-12-13T03:24:36.297 回答