放暑假了,重拾之前学的半半拉拉的python,刷题时发现了一道在C语言中做过很多遍的题目——找100以内的质数,脑子里肌肉记忆般冒出来的想法就是通过双层嵌套循环来解决这道题目,但是却在真正编写程序时出现了一些问题。
这是我写的第一版代码:
a=[];
for i in range(2,100):
j = 2
for j in range(2,i):
if (i%j == 0):
break
else:
a.append(i)
print(a)
看起来好像没什么问题,思路非常简单粗暴,首先创建一个空列表 a,排除1,所以 i 从2到100迭代 i 循环内部又嵌套一个从2到 i 迭代的 j 循环,若 i 对 j 取余等于0(即 i 可被 j 整除),那么则直接用break打断循环,反之则 i 为质数,使用append方法将 i 添加进列表,最后输出列表a。但是最后得到的结果却是:
我一时想不明白,开始胡乱修改缩进来试图解决问题,还真让我改对了。第二版代码如下:
a=[];
for i in range(2,100):
j = 2
for j in range(2,i):
if (i%j == 0):
break
else:
a.append(i)
print(a)
几乎没有变动,只是修改了else的缩进,为什么会导致结果产生这么大的变化呢?而且没有对应的if ,这个莫名其妙的else与for对应使用又是什么含义呢?带着这样的疑问,我搜索了相关的资料,得到了答案:原来与c语言的if-else搭配不同,python中的else还有另外3种使用场景,分别是for - else、while - else 以及 try - except - else。下面我仅针对这道例题对for-else场景说说我的理解,对其他组合的使用感兴趣的朋友们可以参考我查找到的资料:https://blog.csdn.net/hzblucky1314/article/details/121205355
我们可以看到for - else的执行顺序为:
1、当迭代对象完成所有迭代后且此时的迭代对象为空时,
2、如果存在else子句则执行else子句,没有则继续执行后续代码;
3、如果迭代对象因为某种原因(如带有break关键字)提前退出迭代,则else子句不会被执行,程序将会直接跳过else子句继续执行后续代码。
体现在这道例题就是当第一层的 i 循环完成,其中没有满足二层 j 循环中的if 条件(迭代对象完成所有迭代后且此时的迭代对象为空),于是不执行break语句,所以继续迭代,执行else语句中的列表元素添加。
至此这道题的原理总算是弄清楚了,可是这道题就做完了吗?有没有另外的方法能够解决呢?我想起了之前在c语言学习中老师教授的算法,稍加修改诞生了我的第三版代码:
import math
a=[];
for i in range(2,100):
x = math.sqrt(i)
y = int(x)
for j in range(2,y+1):
if i%j==0:
break
else:
a.append(i)
print(a)
编写完成后搜索发现了写成函数的形式会更加简短。
值得一提的是在编写的过程中也遇到了例如强制类型转换、range的范围修改等等问题,但最终都顺利地解决,这次的这道看似简单的例题让我懂得了学习编程语言需要刻苦钻研的精神,也需要做到融会贯通,灵活迁移。若内容有不恰当的地方请大家指正,祝大家学习进步,生活愉快!