我发现自己一遍又一遍地拥有这种模式:
variable = ""
try:
variable = ... do some file loading stuff ...
except:
variable = ""
有没有办法将它压缩成单个表达式?与if-else语句一样,您可以转向:
variable = ""
if something:
variable = somethingelse
else:
variable = ""
到
variable = somethingelse if something else ""
try-catch有没有相同的东西?
答案 0 :(得分:18)
由于agf已经提供了我推荐的方法,这里是他的例程的一个版本,有一些小的改进:
def try_except(success, failure, *exceptions):
try:
return success()
except exceptions or Exception:
return failure() if callable(failure) else failure
此版本:
允许您准确指定将作为附加可选参数捕获的异常。您应始终捕获将执行此任务的最小异常集,并让您无法处理的异常冒泡到调用方。
支持使用普通值以及故障值的函数。这可以节省您在很多情况下使用lambda的麻烦。 (当然,您可以使用lambda: ''
代替str
。)
答案 1 :(得分:14)
def try_except(success, failure):
try:
return success()
except:
return failure()
variable = try_except(do_some_file_loading_stuff, lambda: '')
我认为代码是自我解释的。它返回success
返回的值,除非出现错误,然后返回failure
返回的值。如果do_some_file_loading_stuff
是表达式而不仅仅是函数调用,那么也将它包装在lambda
中。
编辑: @kindall和我改进了他的版本,所以它和我一样快,如果你想要的话可以完全相同,有更多的功能,并且行数相同。使用它!
def try_except(success, failure, *exceptions):
try:
return success()
except exceptions or Exception:
return failure() if callable(failure) else failure
答案 2 :(得分:12)
这是一个提供一点快捷方式的上下文管理器:
from contextlib import contextmanager
@contextmanager
def catch(*exceptions, **kwargs):
try:
yield kwargs.get("default", None)
except exceptions or Exception:
pass
用法:
with catch(ZeroDivisionError, default=0) as x:
x = 3 / 0 # error
print x # prints 0, the default
这里的基本思想是上下文管理器返回您传递的任何默认值,然后将其分配给您在with
语句的as
子句中指定的变量。然后,在上下文中,执行一个尝试分配给同一个变量的语句。如果它引发异常,则上下文管理器会捕获并静默忽略它,但由于分配没有发生,因此默认值仍然存在。
对于多行计算可能特别有用,但仍会产生单个值。
答案 3 :(得分:3)
不幸的是,不,没有语言构造,我也不知道任何真正清晰简洁的习语。我一直想要那样的东西。前段时间有人给我理由,Python没有类似variable = function_cal() except ""
的东西,但它们不是很有说服力,我仍然想念这种语言结构:)
答案 4 :(得分:1)
显然,后一种做法更加简洁,是像你这样的许多程序员的首选。
虽然语言本身没有提供“一线尝试 - 除了捕获”,无论出于什么原因,一切都是好的和必要的,我认为,你通常可以通过改变程序来做到这一点;例如:
try:
a_var = a_dict.get('abcd')
except a_dict.KeyError:
a_var = ''
成:
a_var = a_dict.get('abcd',default='')
,类似于数据库查询;
try:
a_qs = Model.objects.get(id=42)
except Model.DoesNotExist:
a_qs = Model.objects.create(id=42)
与
a_qs = Model.objects.get_or_create(id=42,**kwargs)
并尽可能将类似的API添加到您自己的程序中。 try-except在Python中相当“便宜”,并且由于异常处理的昂贵性质,基于异常的编程比Java语言中通常建议的“先检查”方法更受欢迎。所以,你应该在方法/函数中包装这个“捕捉事物”并在每个地方调用它,例如dict和其他结构。
答案 5 :(得分:0)
没有简单的方法来简化try / catch语句,比如if / else示例,但是我想指出python2.5中引入的python的“with”语句使得很多接口到文件/ db io试试catch语句更简单,异常安全。 IO操作往往是使用大量try / catch语句的地方。
with open("myfile.txt", "r") as f:
# Do stuff with f
而不是
try:
f = open("myfile.txt", "r")
# Do stuff with f
except:
pass
finally:
if f: f.close
答案 6 :(得分:0)
def with_handlers(handlers: Dict[Type[Exception], Callable[[Exception], S]], f: Callable[[], T]) -> Union[S, T]:
try:
return f()
except tuple(handlers.keys()) as err:
return handlers[type(err)](err)
handlers
包含所有预期的异常及其相应的处理程序。
这是一个catch
函数,它还支持else和final子句:
def catch(
try_clause: Callable[[], T],
except_clauses: Dict[Type[Exception], Callable[[Exception], S]],
else_clause: Optional[Callable[[T], R]] = None,
final_clause: Optional[Callable[[Union[T, S]], None]] = None) -> Union[R, S, T]:
try:
ret = try_clause()
except tuple(except_clauses.keys()) as err:
handled = except_clauses[type(err)](err)
return handled
else:
return ret if else_clause is None else else_clause(ret)
finally:
if final_clause is not None:
try:
final_clause(ret)
except NameError:
final_clause(handled)
在Python中,try语句不会引入自己的作用域,
但是这里try_clause
是一个函数,因此else_clause
需要一个参数来接收来自try_clause
的信息。
同样,final_clause
需要两个参数。