Python学习笔记:04 循环


本篇介绍Python的while循环和for循环。可以在如下位置下载代码文件:
https://code.csdn.net/snippets/188632/master/LoopTest.py/raw

基本while循环

print '###############'
print 'Basic while loop:'
i = 0
while i < 5:
    print 'i =', i
    i += 1
print ''


C风格的“整型做为循环条件”

print '################'
print 'Integer as boolean:'
i = 5
while i:
    print 'i =', i
    i -= 1
print ''


while带多个条件

while后面可以是任意的布尔表达式,只要确保整个表达式最后能返回一个布尔值就可以了:
print '######################################'
print 'While loop with multiple conditions:'
i, j = 0, 0
while i < 3 or j < 5:
    print 'i =', i, ', j=', j
    i += 1
    j += 1
print ''

用for循环遍历数组等对象

在其它很多语言中,如果我们定义了一个形如“myArr = {10, 11, 12, 13 ,14}”这样的数组,当用for循环来遍历这个数组时,必须引入一个控制变量(例如下面例子中的“i”):
for (int i; i = 0; i < myArr.length){
    currItem = myArr[i]
    process(currItem)
    i++
}
变量i被用于控制循环次数,同时用来取当前位置的数组元素。

不同于其它语言,Python中的for循环并非while循环的一种替代。Python中的for循环是专门用于遍历iterable(数组的一种),而不需要引入专门的控制变量。
for循环必须与“in”关键字连用。样例代码如下:
myArr = (10, 11, 12, 13, 14)
for currNum in myArr:
    print currNum

注:
* for ... in ... 语句是用于遍历一个iterable类型的对象,和直接的 ... in ... 语句是不同的,后者是查找“in”前面的值是否在“in”后面的iterable对象中存在,并返回布尔值。

使用for循环时,同时获取当前的循环位置

Python的for循环虽然省去了引入控制变量,但有时候我们确实需要获取当前循环到第几次,可以使用内置的“enumerate”对象来包装:
print '#########################################################'
print 'Get current index when using for loop:'
myArr = (10, 11, 12, 13, 14)
for idx, currNum in enumerate(myArr):
    print "Current index: %s, current item: %s" % (idx, currNum)
print ''

注:
* 关于enumerate,将在以后介绍
* 关于for后面带2个变量,在紧接着的下面介绍。

快速遍历已知列数的“矩阵”形式的二维数组

print '#######################################'
print 'Get all value of a matrix:'
myArr = ((10, 11), (20, 21), (30, 31))
for var1, var2 in myArr:
    print "arg1: %s, arg2: %s" % (var1, var2)
print ''

注:
* “((10, 11), (20, 21), (30, 31))”定义了一个3行2列的二维数组(确切地讲,是二维“元组”)
* for语句后面跟的参数个数,必须小于或等于每一个内层数组的个数,否则,运行时将会出现数组越界的错误

遍历String中的每一个字符
事实上,不仅是数组,所有可进行Iterate的对象,都可以用for ... in ... 语句来遍历。如下就展示了如何遍历一个String:
print '#################################'
print 'Get each character of a String:'
myStr = "This is my String"
for char in myStr:
    print 'Current char:', char

在以后的使用中,可能还会遇到各种可Iterate的对象,它们都可以与类似上面的形式来操作。

跳转(break、continue)

这一部分和其它语言基本类似,熟悉的话可以跳过。

使用continue跳过循环块中所有的剩余代码,立即重新回到循环块的开始(即下面例子中,立即执行“while i < 4:”这行代码)
print '#########################'
print 'Test of continue:'
print 'Loop start'
i, j = -1, -1
while i < 4:
    j += 1
    i += 1
    if j == 2:
        print 'j =', j
        continue
    print 'i =', i, ', j =', j
print 'Loop finish'
print ''

使用break跳过循环中所有的剩余代码,立即执行循环块后的代码(即下面例子中,立即执行“print 'Loop finish'”这行代码)
print '#######################'
print 'Test of break:'
print 'Loop start'
i, j = -1, -1
while i < 4:
    j += 1
    i += 1
    if j == 2:
        print 'j =', j
        break
    print 'i =', i, ', j =', j
print 'Loop finish'
print ''

话题:多层嵌套的跳转

在这个问题上,可能很多人要失望了。Python不仅不支持goto,连使用label来直接跳出一个多重循环都不允许。考虑这个场景:检查一个不定长的二维数组中,是否存在至少1个“python”字符串。这种情况下只要发现第一个目标字符串,剩下来的循环就都不需要执行了。假设该数组为:
(('Now', 'we', 'are'), ('going', 'to'), ('introduce', 'you', 'the', 'python', 'programming', 'language.'))

如下代码可以实现该需求:
print '################################################################################'
print 'Test of nesting break:'
print 'First test:'
myArr = (('Now', 'we', 'are'), ('learning', 'the', 'Python', 'programming', 'language'),
         ('which', 'is', 'very', 'powerful.'))
for each_tuple in myArr:
    for each_str in each_tuple:
        print 'Now checking string:', each_str
        if each_str == 'Python':
            print 'Found!'
print 'finished!'

观察运行发现,尽管找到了'Python'之后,程序已经达到了目的,但是它仍继续对后续字符串进行了判断——而这完全是在浪费时间。

按照传统语言,可以使用goto来避免这种浪费(如下代码在Python中不可执行):
myArr = (('Now', 'we', 'are'), ('learning', 'the', 'Python', 'programming', 'language'),
         ('which', 'is', 'very', 'powerful.'))
for each_tuple in myArr:
    for each_str in each_tuple:
        print 'Now checking string:', each_str
        if each_str == 'Python':
            print 'Found!'
            goto: end
end: print 'finished!'

即使像Java这种不支持goto的语句,也支持为代码块打标签,配合continue、break这类跳转语句来实现,例如(如下代码在Python中不可执行):
myArr = (('Now', 'we', 'are'), ('learning', 'the', 'Python', 'programming', 'language'),
         ('which', 'is', 'very', 'powerful.'))
check: for each_tuple in myArr:
    for each_str in each_tuple:
        print 'Now checking string:', each_str
        if each_str == 'Python':
            print 'Found!'
            break: check
print 'finished!'

然而,令人失望的是,Python对上述2种方式都不支持。曾经有人建议Python支持这种方式,但是被拒绝了。在现有条件下,有一些替代的方法可以来实现

添加控制语句

print '2. Break with control variable:'
found = False
for each_tuple in myArr:
    for each_str in each_tuple:
        print 'Now checking string:', each_str
        if each_str == 'Python':
            found = True
            print 'Found!'
        if found:
            break
    if found:
        break

这里,我们引入了一个控制变量“found”,赋初值为False。并在每个循环体的最后都添加一个判断,一旦发现它为真,则break。然后在程序执行中,任何地方只要想结束本次循环,就直接讲其置为True即可。
它的问题在于如果你的循环很深,你需要添加很多个这种if语句来判断。并且添加太多的重复语句,容易导致代码在后续修改时容易出错,不易维护。不过这种方法目前看来是最好的方法。

使用异常

print '3. Break with exception:'
try:
    for each_tuple in myArr:
        for each_str in each_tuple:
            print 'Now checking string:', each_str
            if each_str == 'Python':
                found = True
                print 'Found!'
                raise ValueError("Found!")
except ValueError:
    pass
print 'finished!'
print ''

注:
* 这种方式是最接近label break的方式。
* 一般在Python界认为这种方式是“不够文雅”的,因为异常用于非预期的情况,而实际上此处代码是正常处理的。
* 如果确实要用异常来处理,应该建立一个自定义的异常类而不要像本代码中展示的使用系统的“ValueError”,因为这可能导致确实出现这种异常时没有正确处理。关于自定义异常,可以参考后面的说明。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值