详解Python中for循环的使用
for循环
本系列前面“探索Python,第5部分:用Python编程”一文讨论了if语句和while循环,讨论了复合语句以及适当缩进Python语句来指示相关Python代码块。该文的结尾介绍了Pythonfor循环。但就其使用和功能来说,for循环更值得关注,所以本文单独讲述该循环。
for循环有一个简单的语法,使您可以从容器对象中提取单个项目并对其进行某些操作。简单地说,使用for循环,可以迭代中对象集合的项目。对象集合可以是任何Python容器类型,包括前面文章中讨论的tuple、string和list类型。但是容器metaphor的功能比这三种类型更强大。metaphor包括其他序列类型,如dictionary和set,将来的文章中将对它们进行讨论。
但是请稍等!还有更多信息:for循环可以用于迭代支持迭代metaphor的任何对象,这使for循环非常有用。
清单1中显示了for循环的基本语法,还演示了如何在for循环中使用continue和break语句。
清单1.for循环的伪代码
foritemincontainer: ifconditionA:#Skipthisitem continue elifconditionB:#Donewithloop break #actiontorepeatforeachiteminthecontainer else: #actiontotakeoncewehavefinishedtheloop.
本系列中的第二篇文章“探索Python,第2部分:探索Python类型的层次结构”介绍了Pythontuple。如文中所述,tuple类型是不可变的异构容器。这主要是说tuple可以存放不同类型的对象,但是它一旦创建,就无法更改。清单2演示了如何使用for循环迭代tuple的元素。
清单2.for循环和tuple
>>>t=(0,1,2,3,4,5,6,7,8,9) >>>count=0 >>>fornumint: ...count+=num ...else: ...printcount ... 45 >>>count=0 >>>fornumint: ...ifnum%2: ...continue ...count+=num ...else: ...printcount ... 20
本例首先创建了名为t的tuple,存放整数0至9(包含9)。第一个for循环迭代此tuple,在count变量中累计tuple中数值的和。一旦代码已经迭代了tuple中的所有元素,它将进入for循环的else子句,打印count变量的值。
清单2中显示的第二个for循环也迭代tuple中的所有元素。但是,它仅累计容器中能够被2整除的那些项的值(请记住如果表达式为非零,if语句将确定为真,num不能被2整除时使用%运算符会返回非零值)。此限制通过使用适当的if语句和continue语句来完成。如前面的文章中所述,continue语句使包含它的循环开始下一次迭代。实现相同结果的另一种方法是测试tuple中的当前项是否是偶数(使用ifnotnum%2:),如果为真,那么将当前项添加到运行总和中。一旦代码完成tuple中的迭代,将调用else子句,打印总和。
本系列中的第三篇文章“探索Python:第3部分:探索Python类型的层次结构”讨论了Pythonstring。string是不可变的同构容器,这意味着它仅能存放字符且一旦建立将无法修改。清单3演示了如何使用Pythonstring作为for循环的容器。
清单3.for循环和string
>>>st="PythonIsAGreatProgrammingLanguage!" >>>forcinst: ...printc, ... PythonIsAGreatProgrammingLanguage! >>>count=0 >>>forcinst: ...ifcin"aeiou": ...count+=1 ...else: ...printcount ... 10 >>>count=0 >>>forcinst.lower(): ...ifcin"aeiou": ...count+=1 ...else: ...printcount ... 12
本例提供了三个不同的for循环,它们都迭代同一string。第一个for循环迭代string“PythonIsAGreatProgrammingLanguage!”并一次打印string中的一个字符。在此例中,print语句变量c后加了一个逗号。这使print语句打印字符值时后面跟着空格字符,而不是换行字符。如果没有后面的逗号,字符将全部打印在单独的行中,会很难读。
下两个for循环迭代该字符串并计算其包含多少个元音字母(“a”、“e”、“i”、“o”或“u”)。第二个for循环在迭代原始string时仅查找小写元音字母。第三个for循环迭代通过调用string对象的lower方法返回的临时string。lower方法将string中的所有字符转换为小写。因此,第三个for循环可找到另外两个元音字母。
本系列中的第四篇文章“探索Python,第4部分:探索Python类型的层次结构”介绍了Pythonlist。list是异构可变容器,这意味着它可以存放不同类型的对象且创建后可以修改。清单4演示了如何使用list和for循环。
清单4.for循环和list
>>>mylist=[1,1.0,1.0j,'1',(1,),[1]] >>>foriteminmylist: ...printitem,"\t",type(item)) ... 1<type'int'> 1.0<type'float'> 1j<type'complex'> 1<type'str'> (1,)<type'tuple'> [1]<type'list'>
既然list是很灵活的Python容器类型(您将在本系列其余的文章中多次看到它),本例看起来可能过于简单了。但是,这是一部分要点:使用for循环使处理容器中的每个项目非常简单,甚至处理包含各种不同对象的list也是如此。本例迭代Pythonlist中的所有项目,并在单独的行中打印每一项及其相对应的Python类型。
迭代和可变容器
Pythonlist是一个可变序列,提供了一种令人好奇的可能性:for循环主体可以修改其正在迭代的list。正如您可能认为的,这样并不好,如果进行此操作,Python解释器将无法很好地工作,如清单5所示。
清单5.在for循环中修改容器
>>>mylist=[0,1,2,3,4,5,6,7,8,9] >>>foriteminmylist: ...ifitem%2: ...mylist.insert(0,100) ... ^CTraceback(mostrecentcalllast): File"<stdin>",line3,in? KeyboardInterrupt >>>printmylist [100,....,100,100,0,1,2,3,4,5,6,7,8,9]#Manylinesdeletedforclarity >>>mylist=[0,1,2,3,4,5,6,7,8,9] >>>foriteminmylist[:]: ...ifitem%2: ...mylist.insert(0,100) ... >>>printmylist [100,100,100,100,100,0,1,2,3,4,5,6,7,8,9]
本例中的第一个for循环只要在原始list中发现奇数,它就在list的开始插入数值100。当然,这是一种演示此问题的不同寻常的方式,但却非常好。一旦在三个点的Python提示后按Enter键,Python解释器就处于无限循环的混乱中。要停止这种混乱,必须通过按Ctrl-C(其在Python输出中显示为^C)来中断进程,然后会出现KeyboardInterrupt异常。如果打印出修改的list,将看到mylist现在包含大量的值为100的元素(新元素的准确数量取决于您中断循环的速度)。
本例中的第二个for循环演示了如何避免此问题。使用切片运算符创建原始list的副本。现在for循环将迭代该副本,而对原始list进行修改。最终的结果是修改后的原始list,它现在以五个值为100的新元素开始。
for循环和序列索引
如果您用过其他编程语言,Pythonfor循环可能看起来有点儿古怪。您可能认为它更像foreach循环。基于C的编程语言具有for循环,但它的设计目的是对一系列操作执行特定次数。Pythonfor循环可以通过使用内置的range和xrange方法来模拟该行为。清单6中演示了这两种方法。
清单6.range和xrange方法
>>>r=range(10) >>>printr [0,1,2,3,4,5,6,7,8,9] >>>type(r) <type'list'> >>>xr=xrange(10) >>>printxr xrange(10) >>>type(xr) <type'xrange'>
本例首先演示了range方法,它创建一个包含一系列整数的新list。调用range方法的一般形式是提供单个值,用作整数list的上限。零为起始值。因此,调用range(10)将创建包含整数0至9(包含9)的list。range方法接受起始索引以及步长。所以,调用range(11,20)将创建从11至19(包含19)的整数list,而调用range(12,89,2)将创建从12至88的偶数list。
由于xrange方法也创建整数list(其使用相同参数),所以它与range方法非常相似。但是,xrange方法仅在需要时才在list中创建整数。例如,在清单6中,尝试打印出新创建的xrange时除了xrange的名称,不会显示任何数据。当需要迭代大量整数时,xrange方法更适用,因为它不会创建极大的list,那样会消耗大量计算机内存。
清单7演示了如何在for循环内使用range方法来创建整数1至10(包含10)的乘法表。
清单7.创建乘法表
>>>forrowinrange(1,11): ...forcolinrange(1,11): ...print"%3d"%(row*col), ...print ... 12345678910 2468101214161820 36912151821242730 481216202428323640 5101520253035404550 6121824303642485460 7142128354249566370 8162432404856647280 9182736455463728190 102030405060708090100
本例使用两个for循环,外面的for循环关注乘法表中的每一行,嵌套的for循环关注每行内的列。每个循环都迭代包含整数1至10(包含10)的list。最里面的print语句使用了一个名为字符串格式化的新概念来创建格式设置精美的表。字符串格式化是一种非常有用的技术,用于以格式设置精美的布局创建由不同数据类型组成的string。现在详细信息并不重要,将来的文章中将讲述这些内容(了解C编程语言的printf方法的任何人都会很熟悉这些内容)。在本例中,字符串格式化指定将从整数创建新string且需要保留三个字符来存放该整数(如果该整数小于三个字符,将在左边用空格填补,从而使数据排列整齐)。第二个print语句用于打印新行,从而使乘法表中的下一行被打印在新的行中。
range方法还可用于迭代容器,通过使用适当的索引访问序列中的每一项。要进行此操作,需要包含容器的允许范围索引值的整数list,这可以通过使用range方法和len方法来轻松实现,如清单8所示。
清单8.在for循环内索引容器
>>>st="PythonIsAGreatProgrammingLanguage!" >>>forindexinrange(len(st)): ...printst[index], ... PythonIsAGreatProgrammingLanguage! >>>foriteminst.split(''): ...printitem,len(item) ... Python6 Is2 A1 Great5 Programming11 Language!9
这个最后的示例演示了如何使用len方法作为range方法的参数,创建可用于单独访问string中每个字符的整数list。第二个for循环还显示了如何将string分割为子字符串的list(使用空格字符来指示子字符串的边界)。for循环迭代子字符串list,打印每个子字符串及其长度。
结束语
本文讨论了Pythonfor循环并演示了它的一些使用方式。可以将for循环与提供迭代器的任何Python对象结合使用,这些对象包括tuple、string和list等内置序列类型。for循环和list序列一起使用时具有强大的功能,您会发现自己在许多情况中都要使用它们。Python提供了用于组合这两个概念的简单机制,称为列表理解,将来的文章中将讲述该内容。