Python中不带[]的列表理解
加入名单:Python中不带[]的列表理解,python,list-comprehension,Python,List Comprehension,加入名单: >>> ''.join([ str(_) for _ in xrange(10) ]) '0123456789' join必须采用iterable >>>''.join( str(_) for _ in xrange(10) ) 显然,join的参数是[str(u)表示xrange(10)],它是一个 看看这个: >>>''.join( str(_) for _ in xrange(10) ) '0123456789' 现在
>>> ''.join([ str(_) for _ in xrange(10) ])
'0123456789'
join
必须采用iterable
>>>''.join( str(_) for _ in xrange(10) )
显然,join
的参数是[str(u)表示xrange(10)]
,它是一个
看看这个:
>>>''.join( str(_) for _ in xrange(10) )
'0123456789'
现在,join
的参数只是xrange(10)中的u的str(u),没有[]
,但结果是一样的
为什么??xrange(10)
中的str(uuu)是否也生成一个列表或一个iterable?如果它在括号中,但不在括号中,从技术上讲它是一个生成器表达式。生成器表达式最初是在Python 2.4中引入的
联接后的部分,(str()表示xrange(10)中的uu))
本身就是一个生成器表达式。你可以这样做:
mylist = (str(_) for _ in xrange(10))
''.join(mylist)
它的意思和你在上面第二个案例中写的完全一样
生成器有一些非常有趣的属性,其中最重要的一点是,当您不需要一个列表时,它们不会分配整个列表。相反,像join这样的函数一次从生成器表达式中“泵”出一个项,对微小的中间部分执行其工作
在您的特定示例中,list和generator的性能可能并没有太大的不同,但总的来说,我更喜欢尽可能使用generator表达式(甚至是generator函数),主要是因为很少有生成器比完整的list具体化慢。这是一个生成器,而不是列表理解。生成器也是可重用的,但它不是先创建整个列表然后将其传递给join,而是逐个传递xrange中的每个值,这可能会更有效。第二个
join
调用的参数是生成器表达式。它确实产生了一个可移植的
>>>''.join( str(_) for _ in xrange(10) )
这称为生成器表达式,并在中进行了说明
生成器表达式和列表理解之间的主要区别在于前者不会在内存中创建列表
请注意,还有第三种编写表达式的方法:
''.join(map(str, xrange(10)))
第二个示例使用生成器表达式而不是列表。不同之处在于,通过列表理解,可以完全构建列表并将其传递给
.join()
。使用生成器表达式,项目将逐个生成,并由.join()
使用。后者使用更少的内存,通常更快
碰巧,列表构造函数将愉快地使用任何iterable,包括生成器表达式。因此:
[str(n) for n in xrange(10)]
只是“语法糖”的意思:
换句话说,列表理解只是一个生成器表达式,它被转换成一个列表。如前所述,它是一个
从文件中:
只有一个参数的调用可以省略括号。有关详细信息,请参见第节
其他受访者的回答是正确的,即您发现了a(其符号类似于列表理解,但没有周围的方括号) 一般来说,genexps(人们亲切地称之为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
在比较itertools.imap和map时,同样的结果也适用:
我想,
join
很可能是用C编写的,因此运行速度比列表理解快得多。。。测试时间!显然,我把你的问题看错了。它似乎为我返回了一个生成器…只是一个注释:\u
没有特殊意义,它是一个常规变量名。它通常用作一次性名称,但事实并非如此(您使用的是变量)。我会避免在代码中使用它(至少以这种方式)。据我所知,生成器可以通过类似元组的表达式生成,如(str(u)for uuxrange(10))
。但是我感到困惑的是,为什么()
可以在join
中省略,这意味着代码应该像`'''.join((str())代表xrange(10)中的`),对吗?@Alcott我对元组的理解是,它们实际上是由逗号分隔的表达式列表定义的,而不是括号;括号仅用于直观地对赋值中的值进行分组,或者在元组进入其他逗号分隔列表(如函数调用)时实际对值进行分组。这通常通过运行tup=1,2,3;打印(tup)
。考虑到这一点,使用for
作为表达式的一部分将创建生成器,括号正好用于将其与写入错误的循环区分开。您确定它们在引擎盖下是等效的吗?时间显示:[str(x)代表x范围(1000)]
:262 usec,列表(str(x)代表x范围(1000))
:304 usec。@lazyr你说得对。列表理解速度更快。这就是为什么列表理解在Python2.x中泄漏的原因。GVR写道:“这是列表理解最初实现的产物;这是Python多年来“肮脏的小秘密”之一。它一开始是一种有意的妥协,让列表理解速度快得令人眼花缭乱,虽然这对初学者来说不是一个常见的陷阱,但它确实偶尔会刺痛人们。”@ovgolovin listcomp之所以更快,是因为join必须在开始工作之前创建一个列表“您所指的不是速度问题——它只是意味着循环归纳变量暴露在listcomp之外。@RaymondHettinger那么这些词是什么意思“它一开始是故意妥协,让列表理解速度盲目加快”?正如我所说
~ $ 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