具有实例级信息的Python装饰器

具有实例级信息的Python装饰器,python,decorator,Python,Decorator,下面是一个不起作用的例子,它说明了我想要得到的东西 class TestClass(object): def require_debug_mode(self, f): def func_wrapper(*args, **kwargs): if self.debug_mode: return f(*args, **kwargs) return func_wrapper def __init_

下面是一个不起作用的例子,它说明了我想要得到的东西

class TestClass(object):

    def require_debug_mode(self, f):
        def func_wrapper(*args, **kwargs):
            if self.debug_mode:
                return f(*args, **kwargs)
        return func_wrapper

    def __init__(self, debug_mode):
        self.debug_mode = debug_mode

    @require_debug_mode
    def print_message(self, msg):
        print msg
您可以按照以下方式重新写入所需的
打印消息

def print_message(self, msg):
    if self.debug_mode:
        print msg

我基本上希望能够修饰将执行某些检查的方法(而不必在可能使用它的每个方法中重复该检查)。但这些检查需要访问实例级信息。这是可能的吗?

装饰器接收到与常规方法相同的参数,这意味着装饰器也可以使用
self
。代码的问题在于,您希望外部包装器也获得
self
参数,但事实并非如此(它在声明时被调用,此时没有实例)

例如:

import functools


class TestClass(object):

    def require_debug_mode(function):

        @functools.wraps(function)
        def _require_debug_mode(self, *args, **kwargs):
            assert self.debug_mode, 'Debug mode is required for %r' % function
            return function(self, *args, **kwargs)

        return _require_debug_mode

    def __init__(self, debug_mode):
        self.debug_mode = debug_mode

    @require_debug_mode
    def print_message(self, msg):
        print msg


test_class = TestClass(True)
test_class.print_message('ping')

test_class = TestClass(False)
test_class.print_message('pong')
输出:

ping
Traceback (most recent call last):
    ...
AssertionError: Debug mode is required for <function print_message at 0x...>
shell returned 1
ping
回溯(最近一次呼叫最后一次):
...
AssertionError:调试模式是必需的
壳返回1

装饰器是一个函数,给定一个函数作为输入,返回一个函数作为输出

您想输入一个函数
print\u message(self,msg)
。那很好

为了使decorator有效地工作,结果函数必须具有类似的行为。因此,您需要包装函数,对足够的参数进行解码,以启用“窥视”以查看所需内容:

def func_wrapper(self, *args, **kwargs):
    if self.debug_mode:
        return self.f(*args, **kwargs)

要将装饰器作为类的一部分,可以使用以下代码:

class TestClass(object):

    def require_debug_mode(f):
        def func_wrapper(self, *args, **kwargs):
            if self.debug_mode:
                return f(self, *args)
        return func_wrapper

    def __init__(self, debug_mode):
        self.debug_mode = debug_mode

    @require_debug_mode
    def print_message(self, msg):
        print(msg)

tc_obj = TestClass(True)
tc_obj.print_message("debug msg")
# debug msg

tc_obj = TestClass(False)
tc_obj.print_message("debug msg")
# no output
要将装饰器保持在类之外,可以使用以下方法

def require_debug_mode(f):
    def wrapper(*args):
        if args[0].debug_mode:
            return f(*args)
    return wrapper

class TestClass(object):
    def __init__(self, debug_mode):
        self.debug_mode = debug_mode

    @require_debug_mode
    def print_message(self, msg):
        print(msg)

tc_obj = TestClass(True)
tc_obj.print_message("debug msg")
# debug msg

tc_obj = TestClass(False)
tc_obj.print_message("debug msg")
# no output

是的,很容易做到。您刚刚将
self
参数放错了位置。内部函数需要
self
参数。