我有一个方法,它接受一个列表并返回一个对象:
# input a list, returns an object
def map_to_obj(lst):
a_list = f(lst)
return a_list[0] if a_list else None
我想得到一个包含所有非None
的Map元素的列表。
就像这样:
v_list = [v1, v2, v3, v4]
[map_to_obj(v) for v in v_list if map_to_obj(v)]
但是在列表解析中调用map_to_obj
方法两次似乎不太好。
有没有一种方法可以让列表解析中包含局部变量,从而使其具有更好的性能?
还是编译器会自动优化它?
这是我想要的
(sml like)
[let mapped = map_to_obj(v) in for v in v_list if mapped end]
8条答案
按热度按时间gc0ot86w1#
使用嵌套列表解析:
或者更好的是,围绕生成器表达式的列表解析:
e1xvtsh32#
从
Python 3.8
开始,引入了assignment expressions (PEP 572)(:=
运算符),可以在列表解析中使用局部变量,以避免两次调用同一个函数。在我们的示例中,我们可以将
map_to_obj(v)
的求值命名为变量o
,同时使用表达式的结果来过滤列表;并因此使用o
作为Map值:23c0lvtd3#
变量赋值只是一个单一的绑定:
这是一个更一般的答案,也更接近你提出的问题,所以你可以这样写:
aiazj4mn4#
使用python内置的
filter
可以避免重新计算:mgdq6dx15#
一个局部变量可以在一个理解中通过欺骗一个比特和使用一个额外的'for'来设置,这个额外的. for'通过一个包含局部变量所需值的1元素元组来“迭代”。
这里,
o
是局部变量,对于每个v
被设置为等于map_to_obj(v)
。在我的测试中,这比Laying Dog的嵌套生成器表达式稍快一些(也比OP对
map_to_obj(v)
的两次调用快,令人惊讶的是,如果map_to_obj
函数不是太慢的话,它可能比嵌套生成器表达式快)。zqry0prt6#
列表解析对于简单的情况来说是很好的,但是有时候简单的
for
循环是最简单的解决方案:现在,如果你真的想要一个列表组件,而不想构建一个临时列表,你可以使用
filter
和map
的迭代器版本:或者更简单地说:
迭代器版本不构建临时列表,它们使用惰性求值。
ljsrvy3e7#
我已经找到了使用
reduce
的方法:这个的性能怎么样?
2vuwiymt8#
我发现的最好的方法是这样的,它是神秘的,但简洁: