Use decorators to wrap all functions with “if func returned false, return false”
我正在编写一个基于
我要做的是将从
1 2 3 | result = func(*some_args): if (result != True): return result |
例如,对于此代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def func1(arg1 , arg2): if (some_cond): return False #Or some err_val return True def func2(arg1): if (some_cond): return False return True def main(): func1(val1 , val2) func2(val3) return True if __name__ =="__main__": import sys result = main() if (result == err_val1): # Do something. Maybe print. Maybe call some function. sys.exit(1) |
我希望如果其中一个函数失败,
这正是在Python中构建异常的原因。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # imports belong at the *top* of the file import sys class SomeDescriptiveError(Exception): pass class SomeOtherSpecialError(Exception): pass def func1(arg1 , arg2): if (some_cond): raise SomeDescriptiveError('Cannot frobnosticate the fizzbuzz') return arg1 + arg2 # or skip the return statement altogether def func2(arg1): if (some_cond): raise SomeOtherSpecialError('The frontobulator is no longer cromulent') return ''.join(reversed(arg1)) def main(): print(func1(val1 , val2)) print(func2(val3)) if __name__ =="__main__": try: result = main() except SomeDescriptiveError as e: print('Oh dear') sys.exit(e.args[0]) except SomeOtherSpecialError as e: print('Oh no') sys.exit(e.args[0]) else: print('All systems are fully operational') finally: print('I really should clean up all these bits.') |
我认为最好的解决方案是使用异常。如果这绝对不是你想要的,你可以做一些短路:
1 | return func1() and func2() |
要将此扩展到更多功能,而不需要大量的EDOCX1[1]s:
1 2 3 4 5 6 7 8 | from functools import partial def main(): funcs = (partial(func1, arg1, arg2), partial(func2, arg1)) if any(!f() for f in funcs): return False |
虽然这不会返回"its error"(失败函数的错误),但它只返回
既然您确实希望程序在其中一个错误发生时死掉,那么您也可以提高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | flag = 2 def die_on_not_True(func): def wrapper(*args): rc = func(*args) if rc is not True: fmt = 'Function {} failed with return value {!r}' print(fmt.format(func.__name__, rc)) raise SystemExit(1) return True return wrapper @die_on_not_True def func1(arg1 , arg2): if arg1 == flag: return 'error 1' return True @die_on_not_True def func2(arg1): if arg1 == flag: return 'error 2' return True def main(): val1, val2, val3 = 1, 2, 3 print(func1(val1, val2)) print('one') print(func2(val3)) print('two') if __name__ == '__main__': main() |
输出
1 2 3 4 | True one True two |
如果我们设置
1 | Function func1 failed with return value 'error 1' |
如果我们设置
1 2 3 | True one Function func2 failed with return value 'error 2' |
当
如果要在打印错误消息后进行进一步的处理,则引发一个自定义异常而不是
我猜,您真正想要的是一个通用的异常捕捉器,它可以捕捉并返回任何包装函数的异常。你可以很容易地这样做。
1 2 3 4 5 6 7 | def return_exception(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: return e return wrapper |
例子
1 2 3 4 5 6 7 | In [3]: @return_exception ...: def div(a, b): ...: return a / b ...: In [4]: div(1, 0) Out[4]: ZeroDivisionError('division by zero') |
因此,您可以按照您想要的方式处理返回异常对象,尽管很难说为什么需要它。
正如其他人所指出的,更新通常只捕获特定的异常。您可以稍微修改装饰器。
1 2 3 4 5 6 7 8 9 | def return_exception(*exception_types): def build_wrapper(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except exception_types as e: return e return wrapper return build_wrapper |
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | In [6]: @return_exception(ZeroDivisionError) ...: def div(a, b): ...: return a / b ...: In [7]: div(0, 1) Out[7]: 0.0 In [8]: div(1, 0) Out[8]: ZeroDivisionError('division by zero') In [9]: div(1,"a") --------------------------------------------------------------------------- TypeError Traceback (most recent call last) ... TypeError: unsupported operand type(s) for /: 'int' and 'str' In [10]: @return_exception(ZeroDivisionError, TypeError) ....: def div(a, b): ....: return a / b ....: In [11]: div(1, 0) Out[11]: ZeroDivisionError('division by zero') In [12]: div(1,"a") Out[12]: TypeError("unsupported operand type(s) for /: 'int' and 'str'") |
如您所见,您只捕获指定的异常(不过,您仍然可以指定通用