【发布时间】:2016-12-08 22:10:26
【问题描述】:
我有一个功能
def f():
# whatever
yield (a,b)
现在我想收集所有a 但不是b。另外我希望结果aa 是一个列表而不是迭代器。现在我用
aa, _ = zip(*f())
就空间/时间效率而言,这是最好的吗?
【问题讨论】:
标签: python tuples generator yield
我有一个功能
def f():
# whatever
yield (a,b)
现在我想收集所有a 但不是b。另外我希望结果aa 是一个列表而不是迭代器。现在我用
aa, _ = zip(*f())
就空间/时间效率而言,这是最好的吗?
【问题讨论】:
标签: python tuples generator yield
zip(*seq) 必须摄取整个生成器,然后才能输出列。这效率不高。
只要坚持列表理解即可。你可以使用元组赋值:
aa = [a for a, _ in f()]
或使用索引:
aa = [tup[0] for tup in f()]
如果您没有必须让所有值可用于随机访问或其他必须具有列表的操作,则可以使用生成器表达式来保持内存效率:
aa = (a for a, _ in f())
【讨论】:
您可以使用获取第一个返回项目的列表推导
aa = [result[0] for result in f()]
【讨论】:
如果不修改f,你不能让它只产生元组的一个元素。但是,您可以轻松地链接生成器,例如使用生成器表达式:
just_a_please = (a for a,b in f())
要一次性使用所有 a,您应该更喜欢列表推导:
all_a = [a for a,b in f()]
如果你只想要其中一个,有next:
give_me_an_a, _b = next(f())
【讨论】:
很简单,你可以使用列表推导得到一个包含全部内容的列表
aa = [ a for a,_ in f() ]
【讨论】:
对于使用operator 模块的解决方案:
from operator import itemgetter
get_first = itemgetter(0)
aa = [get_first(x) for x in f()]
编辑:我最初声明“使用operator 模块的有效解决方案”,但我找不到任何证据表明它比标准列表理解方法更有效。
一些轶事%timeit观察:
def f():
for i in xrange(0, 10000):
yield (i, i ** i)
def operator_way():
return [get_first(x) for x in f()]
def tuple_unpack_way():
return [a for a, _ in f()]
def indexing_way():
return [a[0] for a in f()]
def map_way():
return map(get_first, f())
%timeit operator_way() # 100 loops, best of 3: 9.25 ms per loop
%timeit tuple_unpack_way() # 100 loops, best of 3: 9.28 ms per loop
%timeit indexing_way() # 100 loops, best of 3: 9.17 ms per loop
%timeit map_way() # 100 loops, best of 3: 9.07 ms per loop
【讨论】:
[x[0] for x in f()]。