[英]Python Try Catch Block inside lambda
是否可以在 lambda 函数中使用 try catch 块。 我需要 lambda 函数将某个变量转换为整数,但并非所有值都能够转换为整数。
不。 Python lambda 只能是单个表达式。 使用命名函数。
写一个泛型函数来转换类型很方便:
def tryconvert(value, default, *types):
for t in types:
try:
return t(value)
except (ValueError, TypeError):
continue
return default
然后你可以写你的lambda:
lambda v: tryconvert(v, 0, int)
您也可以编写tryconvert()
以便它返回一个接受要转换的值的函数; 那么你不需要 lambda:
def tryconvert(default, *types):
def convert(value):
for t in types:
try:
return t(value)
except (ValueError, TypeError):
continue
return default
# set name of conversion function to something more useful
namext = ("_%s_" % default) + "_".join(t.__name__ for t in types)
if hasattr(convert, "__qualname__"): convert.__qualname__ += namext
convert.__name__ += namext
return convert
现在tryconvert(0, int)
返回一个函数convert_0_int
,该函数接受一个值并将其转换为整数,如果无法完成,则返回0
。
在这个特定的例子中,你可以避免使用像这样的try
块:
lambda s: int(s) if s.isdigit() else 0
如果s
所有字符都是数字,则isdigit()
字符串方法返回 true。 (如果您需要接受负数,则必须进行一些额外的检查。)
我将这段小代码放在一起,以演示在 lambda 中捕获异常并对其做出反应的可能性。 它相当初级,或多或少地用作概念证明。
>>> print_msg = lambda msg, **print_kwargs: \
... begin(
... print, msg, end='... ', **print_kwargs
... ).\
... rescue(
... (TypeError, AttributeError),
... lambda exc: print(f'just caught "{exc}"! how fun!')
... ).\
... ensure(print, 'ok done.')()
>>> print_msg('check')
check... ok done.
>>> print_msg('check', file=1)
just caught "'int' object has no attribute 'write'"! how fun!
ok done.
>>> print_msg('check', sep=1)
just caught "sep must be None or a string, not int"! how fun!
ok done.
modules = filter(None, (
begin(importlib.import_module, modname).rescue(lambda exc: None)()
for modname in module_names
))
from typing import Iterable
class begin:
def __init__(self, fun, *args, **kwargs):
self.fun = fun
self.args = args
self.kwargs = kwargs
self.exception_types_and_handlers = []
self.finalize = None
def rescue(self, exception_types, handler):
if not isinstance(exception_types, Iterable):
exception_types = (exception_types,)
self.exception_types_and_handlers.append((exception_types, handler))
return self
def ensure(self, finalize, *finalize_args, **finalize_kwargs):
if self.finalize is not None:
raise Exception('ensure() called twice')
self.finalize = finalize
self.finalize_args = finalize_args
self.finalize_kwargs = finalize_kwargs
return self
def __call__(self):
try:
return self.fun(*self.args, **self.kwargs)
except BaseException as exc:
handler = self.find_applicable_handler(exc)
if handler is None:
raise
return handler(exc)
finally:
if self.finalize is not None:
self.finalize()
def find_applicable_handler(self, exc):
applicable_handlers = (
handler
for exception_types, handler in self.exception_types_and_handlers
if isinstance(exc, exception_types)
)
return next(applicable_handlers, None)
根据您的需要,另一种方法可能是将 try:catch 保留在 lambda fn 之外
toint = lambda x : int(x)
strval = ['3', '']
for s in strval:
try:
print 2 + toint(s)
except ValueError:
print 2
输出:
5
2
虽然在 lambda 表达式中没有处理异常的通用方法,但您可以以受限的方式实现至少一种异常; 从表达式的一部分StopIteration
并在另一部分捕获它是可以实现的; 看:
from random import randrange
list((lambda:(yield from (randrange(0,2) or next(iter(())) for _ in (None,))))())
其中next(iter(()))
引发StopIteration
而yield from
将捕获它; 上面的表达式根据内部随机值随机返回[]
或[1]
( 0
将引发异常,而1
将正常评估)。
你可以在http://baruchel.github.io/python/2018/06/20/python-exceptions-in-lambda/阅读更多关于它的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.