我有一个对象列表,它们有一个称为process的方法。在Python 2中,可以做到这一点
string(/testng-results/suite/test/class/test-method[@name='test']/@status)
在Python 3中,这将不起作用,因为map直到遍历了iterable时才调用该函数。一个可以做到这一点:
map(lambda x: x.process, my_object_list)
但是随后,您浪费了内存,浪费了一个废弃的列表(如果列表很大,就会出现问题)。我也可以使用两行显式循环。但是这种模式对我来说是如此普遍,以至于我不想或者认为我应该每次都编写一个循环。
在Python 3中是否有更惯用的方式做到这一点?
答案 0 :(得分:4)
既然您正在寻找Pythonic解决方案,为什么还要费心尝试为Python 3改编map(lambda x: x.process, my_object_list)
呢?
一个简单的for循环还不够吗?
for x in my_object_list:
x.process()
我的意思是,这简洁,可读,并且如果不需要返回值,请避免创建不必要的列表。
答案 1 :(得分:3)
不要使用map
或简单的for
循环就能完成的列表理解:
for x in list_of_objs:
x.process()
它并没有比您用来抽象它的任何函数长很多,但是它明显更清晰了。
当然,如果process
返回有用的值,则一定要使用列表推导。
results = [x.process() for x in list_of_objs]
或map
:
results = list(map(lambda x: x.process(), list_of_objs))
有一个可用的函数可以使map
不再那么笨拙,特别是如果您要重用调用者的话:
from operator import methodcaller
processor = methodcaller('process')
results = list(map(processor, list_of_objs))
more_results = list(map(processor, another_list_of_objs))
如果要为包装循环的函数寻找一个好名字,Haskell有一个很好的约定:以下划线结尾的函数名将放弃其“返回值”。 (实际上,它丢弃了单声道操作的结果,但出于此答案的目的,我宁愿忽略该区别。)
def map_(f, *args):
for f_args in zip(*args):
f(*f_args)
# Compare:
map(f, [1,2,3]) # -- return value of [f(1), f(2), f(3)] is ignored
map_(f, [1,2,3]) # list of return values is never built