Python列表理解:跳过引发异常的元素

Python列表理解:跳过引发异常的元素,python,exception,list-comprehension,Python,Exception,List Comprehension,我想在列表理解中应用一个函数,它对某些值不起作用。 一个简单的例子是[1/x代表[-2,-1,0,1,2]]。 我想写一些跳过0并返回以下列表的内容:[-0.5,-1.0,1.0,0.5] 到目前为止,我最好的办法是用try语句将部门包装起来: def try_div(x): try: return 1/x except ZeroDivisionError: pass result_with_none = [try_div(x) for x in

我想在列表理解中应用一个函数,它对某些值不起作用。 一个简单的例子是
[1/x代表[-2,-1,0,1,2]]
。 我想写一些跳过
0
并返回以下列表的内容:
[-0.5,-1.0,1.0,0.5]

到目前为止,我最好的办法是用
try
语句将部门包装起来:

def try_div(x):
    try:
        return 1/x
    except ZeroDivisionError:
        pass

result_with_none = [try_div(x) for x in [-2, -1, 0, 1, 2]]
result = [x for x in result_with_none if x is not None]
这似乎有点不方便。我是否可以重写
try\u div
,使列表理解跳过
0
元素

备注:在这个简单的示例中,我当然可以编写
[如果x!=0,请在[-2,-1,0,1,2]中为x尝试div]
。这在我的实际用例中是不可行的,因为事先检查哪些值会引发异常并不容易


备注2:与之相反,我可以在函数中显式处理异常(如
try\u div
)。我的问题主要是关于如何将最后两个步骤(
result\u with_none=…
result=…
)组合成一个步骤。

我认为您的第一个解决方案很清楚,这是python中最重要的一点。或者,用生成器代替理解器怎么样

def try_div_itr(itr):
    for elem in itr:
        try:
             yield 1 / elem
        except ZeroDivisionError:
             pass

result = list(try_div_itr([-2, -1, 0, 1, 2]))

你甚至可以将其概括

def try_itr(func, itr, *exceptions, **kwargs):
    for elem in itr:
        try:
            yield func(elem, **kwargs)
        except exceptions:
            pass


您的代码中有什么不一致之处?看起来很经典(也许是用生成器来转换理解,也可以用过滤器,但这只是小事)。更确切地说,你能解释一下你认为什么“方便”吗?看起来不错。kabanus陈述了进一步可能的改进。在下一行中引入
None
值只是为了删除它们感觉很复杂。我想有一种方法可以直接跳过这些元素。可能的重复会像列表理解一样快吗?更快——见上文
x = [random.choice([0, 1]) for _ in range(100_000)]

%timeit [i for i in (try_div(i) for i in x) if i is not None]
42.6 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit [i for i in [try_div(i) for i in x] if i is not None]
36.3 ms ± 154 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit list(try_div_itr(x))
25.3 ms ± 85.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit list(try_itr(lambda i: 1/i, x, ZeroDivisionError))  
34.7 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# but expect generic method to be slower anyway

%timeit list(try_itr((1).__truediv__, x, ZeroDivisionError))
28.7 ms ± 118 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# remove lambda abstraction for speed