Alc*_*ott 76 python list-comprehension
加入清单:
>>> ''.join([ str(_) for _ in xrange(10) ])
'0123456789'
Run Code Online (Sandbox Code Playgroud)
join 必须采取迭代.
显然,join这个论点是[ str(_) for _ in xrange(10) ],这是一个列表理解.
看这个:
>>>''.join( str(_) for _ in xrange(10) )
'0123456789'
Run Code Online (Sandbox Code Playgroud)
现在,join这个论点只是str(_) for _ in xrange(10),不[],但结果是一样的.
为什么?是否str(_) for _ in xrange(10)也会产生一个列表或一个可迭代?
Ray*_*ger 125
其他受访者回答您发现了一个生成器表达式(其表达式类似于列表推导但没有周围的方括号)是正确的.
通常,genexps(因为它们被亲切地知道)比列表推导更有效且更快.
但是,在这种情况下''.join(),列表理解更快,内存效率更高.原因是join需要对数据进行两次传递,因此它实际上需要一个真实的列表.如果你给它一个,它可以立即开始工作.如果你给它一个genexp代替它,它就无法开始工作,直到它通过运行genexp到耗尽来在内存中建立一个新的列表:
~ $ python -m timeit '"".join(str(n) for n in xrange(1000))'
1000 loops, best of 3: 335 usec per loop
~ $ python -m timeit '"".join([str(n) for n in xrange(1000)])'
1000 loops, best of 3: 288 usec per loop
Run Code Online (Sandbox Code Playgroud)
比较itertools.imap与map时,结果相同:
~ $ python -m timeit -s'from itertools import imap' '"".join(imap(str, xrange(1000)))'
1000 loops, best of 3: 220 usec per loop
~ $ python -m timeit '"".join(map(str, xrange(1000)))'
1000 loops, best of 3: 212 usec per loop
Run Code Online (Sandbox Code Playgroud)
NPE*_*NPE 60
>>>''.join( str(_) for _ in xrange(10) )
Run Code Online (Sandbox Code Playgroud)
这称为生成器表达式,在PEP 289中进行了解释.
生成器表达式和列表推导之间的主要区别在于前者不在内存中创建列表.
请注意,第三种方法是编写表达式:
''.join(map(str, xrange(10)))
Run Code Online (Sandbox Code Playgroud)
您的第二个示例使用生成器表达式而不是列表推导。不同之处在于,通过列表理解,可以完全构建列表并将其传递给.join()。使用生成器表达式,项将被一一生成并被消耗.join()。后者使用较少的内存,并且通常更快。
碰巧的是,列表构造函数将愉快地使用任何可迭代的函数,包括生成器表达式。所以:
[str(n) for n in xrange(10)]
Run Code Online (Sandbox Code Playgroud)
只是“语法糖”的意思:
list(str(n) for n in xrange(10))
Run Code Online (Sandbox Code Playgroud)
换句话说,列表理解只是生成器表达式,它变成了列表。