Python中for循环详解
与其它大多数语言一样,Python也拥有for循环。你到现在还未曾看到它们的唯一原因就是,Python在其它太多的方面表现出色,通常你不需要它们。
其它大多数语言没有像Python一样的强大的list数据类型,所以你需要亲自做很多事情,指定开始,结束和步长,来定义一定范围的整数或字符或其它可重复的实体。但是在Python中,for循环简单地在一个列表上循环,与list解析的工作方式相同。
1.for 循环介绍
>>>li=["a","b","e"]
>>>forsinli: (1)
... prints (2)
a
e
>>>print"\n".join(li) (3)
a
e
(1) for循环的语法同list解析相似。li是一个list,而s将从第一个元素开始依次接收每个元素的值。
(2) 像if语句或其它任意缩进块,for循环可以包含任意数目的代码行。
(3) 这就是你以前没看到过for循环的原因:至今我们都不需要它。太令人吃惊了,当你想要的只是一个join或是list解析时,在其它语言中常常需要使用for循环。
要做一个“通常的”(VisualBasic标准的)计数for循环也非常简单。
2.简单计数
>>>foriinrange(5): (1)
... printi
0
1
2
3
4
>>>li=["a","b","c","d","e"]
>>>foriinrange(len(li)): (2)
-104-DiveIntoPythonhttp://diveintopython.org/
... printli[i]
a
c
d
e
(1) range生成一个整数的list,通过它来控制循环。我知道它看上去有些奇怪,但是它对计数循环偶尔(我只是说偶尔)会有用。
(2) 我们从来没这么用过。这是VisualBasic的思维风格。摆脱它吧。正确遍历list的方法是前面的例子所展示的。
for循环不仅仅用于简单计数。它们可以遍历任何类型的东西。下面的例子是一个用for循环遍历dictionary的例子。
3.遍历 dictionary
>>>importos
>>>fork,vinos.environ.items(): (1)(2)
... print"%s=%s"%(k,v)
USERPROFILE=C:\DocumentsandSettings\mpilgrim
OS=Windows_NT
COMPUTERNAME=MPILGRIM
USERNAME=mpilgrim
[...略...]
>>>print"\n".join(["%s=%s"%(k,v)
... fork,vinos.environ.items()])(3)
USERPROFILE=C:\DocumentsandSettings\mpilgrim
OS=Windows_NT
COMPUTERNAME=MPILGRIM
USERNAME=mpilgrim
[...略...]
(1) os.environ是在你的系统上所定义的环境变量的dictionary。在Windows下,这些变量是可以从MS-DOS访问的用户和系统变量。在UNIX下,它们是在你的shell启动脚本中所export(输出)的变量。在MacOS中,没有环境变量的概念,所以这个dictionary为空。
(2) os.environ.items()返回一个tuple的list:[(key1,value1),(key2,value2),...]。for循环对这个list进行遍历。第一轮,它将key1赋给k,value1赋给v,所以k=USERPROFILE,v=C:\DocumentsandSettings\mpilgrim。第二轮,k得到第二个键字OS,v得到相应的值Windows_NT。
(3) 使用多变量赋值和list解析,你可以使用单行语句来替换整个for循环。在实际的编码中是否这样做只是个人风格问题;我喜欢它是因为,将一个dictionary映射到一个list,然后将list合并成一个字符串,这一过程显得很清晰。其它的程序员宁愿将其写成一个for循环。请注意在两种情况下输出是一样的,然而这一版本稍微快一些,因为它只有一条print语句而不是许多。
现在我们来看看在第5章介绍的样例程序fileinfo.py中MP3FileInfo的for循环。
(1) tagDataMap是一个类属性,它定义了我们正在一个MP3文件中搜索的标记。标记存储为定长字段,只要我们读出文件最后128个字节,那么第3到32字节总是歌曲的名字,33-62总是歌手的名字,63-92为专辑的名字,等等。请注意tagDataMap是一个tuple的dictionary,每个tuple包含两个整数和一个函数引用。
tagDataMap={"title" :( 3, 33,stripnulls),
"artist" :(33, 63,stripnulls),
"album" :(63, 93,stripnulls),
"year" :(93, 97,stripnulls),
"comment":(97,126,stripnulls),
"genre" :(127,128,ord)} (1)
.
.
.
iftagdata[:3]=="TAG":
fortag,(start,end,parseFunc)inself.tagDataMap.items():(2)
self[tag]=parseFunc(tagdata[start:end]) (3)
(2) 这个看上去复杂一些,但其实并非如此。这里的for变量结构与items所返回的list的元素的结构相匹配。记住,items返回一个形如(key,value)的tuple的list。list第一个元素是("title",(3,33,<functionstripnulls>)),所以循环的第一轮,tag为"title",start为3,end为33,parseFunc为函数stripnulls。
(3) 现在我们已经从一个单个的MP3标记中提取出了所有的参数,将标记数据保存起来挺容易。我们从start到end对tagdata进行分片,从而得到这个标记的实际数据,调用parseFunc对数据进行后续的处理,接着将
parseFunc的返回值作为值赋值给伪字典self中的键字tag。在遍历完tagDataMap中所有元素之后,self拥有了所有标记的值,你知道看上去是什么样。相关文章