英文:
Filter on exception from generator
问题
我想要遍历一个生成器/迭代器并将生成的值传递给函数。
这个函数可以返回一个新值,也可以引发错误。
然后我需要返回这个值或者在出现错误时跳过。
我想出了以下的代码:
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
skip_on_errors = set(skip_on_errors)
for item in iter_:
try:
yield func(item)
except Exception as e:
if type(e) in skip_on_errors:
continue
raise
它似乎有效,但我想知道是否有更好的方法?
注意:它必须是一个迭代器/生成器,我不能将结果收集到列表中。
英文:
I would like to iterate over a generator/iterator and pass the value produced to the function.
The function can either return a new value or raise an error.
I then need to return the value or skip on error.
I came up with the following code:
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
skip_on_errors = set(skip_on_errors)
for item in iter_:
try:
yield func(item)
except Exception as e:
if type(e) in skip_on_errors:
continue
raise
It seems to work, but I was wondering if there is a better way to do this?
Note: it has to be an iterator/generator, I can't gather results in a list.
答案1
得分: 1
也许是suppress?
from contextlib import suppress
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
skipper = suppress(*skip_on_errors)
for item in iter_:
with skipper:
yield func(item)
演示:
for y in yield_or_skip([2, 0, 3], lambda x: 1/x, [ZeroDivisionError]):
print(y)
print()
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
print(y)
输出 (在线尝试!):
0.5
0.3333333333333333
0.5
Traceback (most recent call last):
File "/ATO/code", line 26, in <module>
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
File "/ATO/code", line 19, in yield_or_skip
yield func(item)
File "/ATO/code", line 26, in <lambda>
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
ZeroDivisionError: division by zero
英文:
Maybe suppress?
from contextlib import suppress
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
skipper = suppress(*skip_on_errors)
for item in iter_:
with skipper:
yield func(item)
Demo:
for y in yield_or_skip([2, 0, 3], lambda x: 1/x, [ZeroDivisionError]):
print(y)
print()
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
print(y)
Output (Attempt This Online!):
0.5
0.3333333333333333
0.5
Traceback (most recent call last):
File "/ATO/code", line 26, in <module>
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
File "/ATO/code", line 19, in yield_or_skip
yield func(item)
File "/ATO/code", line 26, in <lambda>
for y in yield_or_skip([2,0,3], lambda x: 1/x, [ValueError]):
ZeroDivisionError: division by zero
答案2
得分: 0
more_itertools.map_except 执行该任务。您可以使用它,或使用它来实现自己的版本(在线尝试!):
from more_itertools import map_except
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
return map_except(func, iter_, *skip_on_errors)
或者调整其源代码:
for item in iterable:
try:
yield function(item)
except exceptions:
pass
英文:
more_itertools.map_except does that job. You can use it instead, or use it to implement yours (Attempt This Online!):
from more_itertools import map_except
def yield_or_skip(iter_: Iterable, func: Callable, skip_on_errors: Iterable[Type[Exception]]) -> Iterator:
return map_except(func, iter_, *skip_on_errors)
Or adapt its source code:
for item in iterable:
try:
yield function(item)
except exceptions:
pass
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论