while else 和 for else break

循环else
break和循环else结合时,break语句通常可以忽略其他语言中所需要的搜索状态标志位。例如:下列程序搜索大于1的因子,来决定正整数y是否为质数

y=5
x=y//2
while x>1:
    if y%x==0:
        print(y,'has factor',x)
        break
    x-=1
else:
	print(y,'is prime')

除了设置标志位在循环结束时进行测试外,也可以在找到因子时插入break。这样一来,循环else分句可以视为只有当没有找到因子时才会执行。如果没碰到break,该数就是质数
如果循环主体从没有执行过,循环else分句也会执行,因为你没在其中执行break语句。在while循环中,如果首行的测试一开始就是假,就会发生这种问题,因此,在上面的例子中,如果x一开始就小于或等于1(例如,如果y是2),你还是会得到“is prime”的输出
循环else是python特有的,循环else分句提供了常见的编写代码的明确语法:这是编写代码的结构,让你铺捉到循环的“另一条”出路,而不是通过设定和检查标志位或者条件
例如:假设你要写个循环搜索列表的值,而且需要知道在离开循环后该值是否已经找到,可能会用这种方式进行编写

found=False
while x and not found:
    if match(x[0]):
        print('Ni')
        found=True
    else:
        x=x[1:]
if not found:
    print('not found')

在这里,对标志位进行初始化、设置以及稍后再进行测试,从而确认搜索是否成功,这是有效的python程序,也的确可以运行。然而这正是循环else分句要处理的结构种类,以下是else等价的版本

while x:
    if match(x[0]):
        print('Ni')
    x=x[1:]
else:
    print('not found')

这个版本更简洁一些。标志位不见了,问我们在循环末尾使用else(和while 这个关键字垂直对齐)取代了if测试,因为while主体内的break会离开循环并跳过else,因此可作为捕捉搜索失败的情况更为结构化的方式。
上一个例子中的else分句可以在循环后测试空x并将其取代,但else提供了这种编码样式的明确语法,和for循环结合,else分句会更有用,因为序列的迭代不是你能控制的
for和else
例子:在for中示范循环else分句以及语句嵌套。考虑到对象列表(元素)以及键列表(测试),这段代码会在对象列表中搜索每个键,然后报告其搜索结果。

items=['aaa',111,(4,5),2.01]
tests=[(4,5),3.14]
for key in tests:
    for item in items:
        if item==key:
            print(key,'was found')
            break
    else:
        print(key,'not found!')

这里嵌套if会在找到相符结果时执行break,而循环else分句是认定如果来到此处,搜索就失败了。注意这里的嵌套。当这段代码执行时,同时有两个循环在运行:外层循环扫描键列表,而内层循环为每个键扫描元素列表。循环else分句的嵌套是很关键的,其缩进到和内层for循环首行相同的层次,所以适合内层循环相关联的。
问题:一个循环的else分句何时执行
while或for循环中的else分句会在循环离开时执行一次,但前提是循环是正常离开(没有运行break语句)。如果有的话,break会立刻离开循环,跳过else部分。
程序逻辑替代方案,考虑下列代码,使用while循环以及found标志位来搜索2的幂值[列表到2的5次方(32)] 。它保存在名为power.py的模块文件内。

 L=[1,2,4,8,16,32,64]
X=5
found=False
i=0
while not found and i<len(L):
    if 2**X==L[i]:
        found=True
    else:
        i=i+1
    if found:
        print('at index',i)
    else:
        print(X,'not found')

a 首先,以while循环else分句重写这个代码来消除found标志位和最终if语句

L = [1, 2, 4, 8, 16, 32, 64]
X = 5
i = 0
while i < len(L):
    if 2 ** X == L[i]:
        print('at index', i)
        break
    i = i + 1
else:
    print(X, 'not found')

b
接着,使用for循环和else分句重写这个例子,去掉列表索引运算逻辑。 提示:要去的元素的索引,可以使用列表index方法(L.index(X) 返回列表L中第一个X的偏移值

 L = [1, 2, 4, 8, 16, 32, 64]
X = 5
i = 0
for p in L:
    if (2**X)==p:
        print((2**X),'was found at',L.index(p))
        break
else:
    print(X,'not found')

c
接着,重写这个例子,改用简单的in运算符成员关系表达式,从而完全移除循环

L = [1, 2, 4, 8, 16, 32, 64]
X = 5
for p in L:
    if (2 ** X) == p:
        print((2 ** X), 'was found at', L.index(p))
    else:
        print(X, 'not found')

d 最后,使用for循环和列表append方法来产生2列表(L),而不是通过列表常量硬编码

 X = 5
L = []
for i in range(7): L.append(2 ** i)
print(L)
if (2 ** X) in L:
    print((2 ** X), 'was found at', L.index(2 ** X))
else:
    print(X, 'not found')
L = [2 **x for x in range(7)]
L = list(map(lambda x: 2 ** x, range(7)))
print(L)
X = 5
if 2 ** 5 in L:
    print('at index', L.index(2 ** 5)) 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值