Rap*_*ael 1 python decorator python-decorators
我有一个带有装饰方法 (my_method) 的 Django 模型 (MyModel)。我希望装饰器对 my_method 执行一些检查:
如果检查成功,my_method 应该返回一个字符串;
如果检查不成功,my_method 应该返回装饰器返回的失败消息。
逻辑如下:
# 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
Run Code Online (Sandbox Code Playgroud)
因此,如果decorator1返回失败,我期望 an_instance_of_my_model_instance.my_method(request) 返回('failure', 'message')。如果decorator1成功但decorator2失败,我会期望('另一个失败','消息')。如果所有测试都通过了,u'如果装饰器执行的所有检查都成功则必须返回的结果'
如果decorator1的检查成功通过,我不知道如何检查decorator2。我尝试通过检查decorator2中method_to_decorate的type()来做到这一点,但似乎type使用原始方法本身,而不是decorator1返回的结果(就好像装饰器不知道以前的装饰器执行的操作一样) 。
先感谢您!
装饰器将按照您将它们放在装饰方法上方的顺序进行调用,并且考虑到您的程序结构,如果失败decorator2则不会被调用decorator1,因此无需检查.decorator1decorator2
一个稍微简单一点的例子......
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)
Run Code Online (Sandbox Code Playgroud)
...打印...
failed in decorator 1
failed in decorator 2
success
Run Code Online (Sandbox Code Playgroud)
如果您想检查返回的内容,则需要交换和行:@decorator1@decorator2decorator2decorator1
@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'
Run Code Online (Sandbox Code Playgroud)
现在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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5845 次 |
| 最近记录: |