Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多个python装饰器_Python_Decorator_Python Decorators - Fatal编程技术网

多个python装饰器

多个python装饰器,python,decorator,python-decorators,Python,Decorator,Python Decorators,我有一个Django模型MyModel和一个修饰方法my_方法。 我希望装饰师对我的方法执行一些检查: 如果检查成功,my_方法应该返回一个字符串 如果检查没有成功,my_方法应该返回装饰程序返回的失败消息 逻辑如下: # models.py class MyModel(models.Model): @decorator1 @decorator2 def my_method(self, request, *args, **kwargs): return u

我有一个Django模型MyModel和一个修饰方法my_方法。 我希望装饰师对我的方法执行一些检查:

如果检查成功,my_方法应该返回一个字符串

如果检查没有成功,my_方法应该返回装饰程序返回的失败消息

逻辑如下:

# models.py
class MyModel(models.Model):
    @decorator1
    @decorator2
    def my_method(self, request, *args, **kwargs):
        return u'The result that must be returned if all the checks performed by the decorator succeed'


# decorators.py
from functools import wraps

# decorator1 checks if certain conditions are met. If yes, it returns the decorated method (method_to_decorate); if not, it returns a tuple
def decorator1(method_to_decorate):
    @wraps(method_to_decorate)
    def wrapper1(self, request, *args, **kwargs):
        if a_condition :
            return method_to_decorate(self, request, *args, **kwargs)
        else:
            # we return a failure message
            return ('failure', 'message') 
    return wrapper1

# in decorator2, we want to know if the check performed by decorator1 was successful
# in case of success, we perform decorator2's check
# in case of failure, decorator2 should simply pass the failure message returned by decorator1   
def decorator2(method_to_decorate):
    @wraps(method_to_decorate)
    def wrapper2(self, request, *args, **kwargs):

        # if the first decorator succeeded
        if decorator1_s_test_was_successful:
            # we check if the conditions of the second decorator are met
            if decorator2_s_test_was_successful:
                # we return the method
                return method_to_decorate(self, request, *args, **kwargs)
            else:
                # we return a failure message
                return ('another failure', 'message')
    # if the first decorator did not succeed
        else: # decorator1 returned a tuple : ('failure', 'message') 
            return the_failure_that_decorator1_returned  
    return wrapper2
因此,如果decorator1返回一个失败,我希望我的模型实例的实例返回“failure”,“message”。如果decorator1成功了,但decorator2没有成功,那么我将看到“另一个失败”,“消息”。如果所有的测试都通过了,那么u'如果装饰程序执行的所有检查都成功,那么必须返回的结果'

如果decorator1的检查成功通过,我不知道如何签入decorator2。我试图通过在decorator2中检查方法的类型来实现这一点,但是类型似乎使用了原始方法本身,而不是decorator1返回的结果,就好像decorators不知道以前的decorator执行的操作一样

提前谢谢你

如果希望decorator2检查decorator1返回的任何内容,则需要交换@decorator1和@decorator2行:

@decorator2
@decorator1
def my_method(self, request, *args, **kwargs):
    return u'The result that must be returned if all the checks performed by the decorator succeed'
现在decorator2将封装decorator1返回的任何方法,因此您可以检查该方法返回的内容

def decorator2(method_to_decorate):
    @wraps(method_to_decorate)
    def wrapper2(self, request, *args, **kwargs):

        result = method_to_decorate(self, request, *args, **kwargs)

        if isinstance(result, tuple) and result and result[0] == 'failure':
            # decorator1 returned a failure
            return result
        else:
            # decorator1 passed through the wrapped method call
            if decorator2_s_test_was_successful:
                return result
            else:
                return ('another failure', 'message')

    return wrapper2
如果希望decorator2检查decorator1返回的任何内容,则需要交换@decorator1和@decorator2行:

@decorator2
@decorator1
def my_method(self, request, *args, **kwargs):
    return u'The result that must be returned if all the checks performed by the decorator succeed'
现在decorator2将封装decorator1返回的任何方法,因此您可以检查该方法返回的内容

def decorator2(method_to_decorate):
    @wraps(method_to_decorate)
    def wrapper2(self, request, *args, **kwargs):

        result = method_to_decorate(self, request, *args, **kwargs)

        if isinstance(result, tuple) and result and result[0] == 'failure':
            # decorator1 returned a failure
            return result
        else:
            # decorator1 passed through the wrapped method call
            if decorator2_s_test_was_successful:
                return result
            else:
                return ('another failure', 'message')

    return wrapper2

decorator将按照您将它们放在decorator方法之上的顺序被调用,并且给定您的程序结构,如果decorator1失败,则不会调用decorator2,因此无需检查decorator1在decorator2中是否成功

一个稍微简单的例子

from functools import wraps


def decorator1(f):
    @wraps(f)
    def wrapper(a):
        if a >= 1:
            return f(a)
        return 'failed in decorator 1'
    return wrapper

def decorator2(f):
    @wraps(f)
    def wrapper(a):
        if a >= 2:
            return f(a)
        return 'failed in decorator 2'
    return wrapper

@decorator1
@decorator2
def my_func(a):
    return 'success'


print my_func(0)
print my_func(1)
print my_func(2)
…它打印

failed in decorator 1
failed in decorator 2
success

decorator将按照您将它们放在decorator方法之上的顺序被调用,并且给定您的程序结构,如果decorator1失败,则不会调用decorator2,因此无需检查decorator1在decorator2中是否成功

一个稍微简单的例子

from functools import wraps


def decorator1(f):
    @wraps(f)
    def wrapper(a):
        if a >= 1:
            return f(a)
        return 'failed in decorator 1'
    return wrapper

def decorator2(f):
    @wraps(f)
    def wrapper(a):
        if a >= 2:
            return f(a)
        return 'failed in decorator 2'
    return wrapper

@decorator1
@decorator2
def my_func(a):
    return 'success'


print my_func(0)
print my_func(1)
print my_func(2)
…它打印

failed in decorator 1
failed in decorator 2
success

好的,谢谢你,Martijn,这很有效。我害怕颠倒装饰师的顺序,但这确实奏效了。好的,谢谢你,Martijn,这很有效。我害怕改变装潢师的顺序,但这确实奏效了。