列表生成器是python语言一个非常有特色的功能,灵活且强大。《流畅的Python》第二章中有个例子:
>>> x='ABC''
>>> dummy=[ord(x) for x in x] #1
>>> x
'ABC'
>>>dummy
[65,66,67]
这个例子中,一连出现了三个名为x的变量,看得着实让人眼花撩乱。下面我们逐次来分析。
1、如果把#1一句改为:
dummy=[ord(i) for i in x] #2
会发现执行效果和之前没有任何区别,显然#1中最后一个x引用的就是前一句x='ABC'中的那个变量。而#2一句因为使用了另一个变量名(i),使语句更清晰易读,可以想见,这里连用三个同名变量,是作者有意为之的。那么前两个x如何理解呢?
2、如下的错误提示,是不是已经能说明问题了
>>> x='ABC''
>>> dummy=[ord(i) for i in x] #2
>>> i
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
i
NameError: name 'i' is not defined
可以看到,当我们引用列表生成器中的变量i时,提示此变量未定义,那就说明,在我们引用它时,已经超出了其作用域范围!
这是python3区别于2的新功能,作者在书中已有提及。
3、再进一步,我们作如下操作:
>>> x='ABC'
>>> k=[id(i) for i in x]
>>> k
[20365056, 20270176, 20269952]
>>> id(x[0]),id(x[1]),id(x[2])
(20365056, 20270176, 20269952)
可以发现,列表生成器中的变量i,每次遍历取得的值其实就是x的各个元素。
结论:列表生成器中的循环变量(如#2句中的i,我不知道这么说是否规范,书中作者称其作“表达式内部的变量”,但窃以为如此并不能确指)是列表生成器的局部变量,作用域仅限于列表生成器内部。这与函数的内部变量有点类似,在函数之外是无法访问函数的内部变量的。另外,为了使源代码更清晰易读,当使用列表生成器时,其中的循环变量,应该命名为一个更清晰的独立变量名。