根据设定的条件判断式,运行代码,在符合条件的情况下,会重复运行同一段代码,直到不符合条件,才会停止,所以称为循环结构

循环的分类:

  • while...循环
  • for...in...循环

while...循环

语法结构:

while 条件表达式:
----条件执行体循环体)(前面的----代表缩进的空格)

流程演示图:

while循环流程图

选择结构的if...语句和循环结构的while...语句有什么区别:

if...语句是判断一次,条件为True执行一次

while...语句是判断1+N次,条件为True执行N

a = 0
while a < 10:
    a += 1
    print(a)

运行结果:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

分解流程:

  • 0赋值给变量a
  • 判断a<10也就是0<10,结果为True,执行循环体
  • 整数1通过参数赋值符+=赋值给变量a(相当于a+1,等于0+1
  • 输出变量a为整数1(这时变量a的值就变为1了)
  • 回到条件表达式while a < 10:继续判断,a<10也就是1<10,结果为True,执行循环体
  • 整数1通过参数赋值符+=赋值给变量a(相当于a+1,等于1+1
  • 输出变量a为整数2(这时变量a的值就变为2了)
  • 一直循环,直到a的值变为10,条件表达式while a < 10:判断a<10也就是10<10结果为False,则不再执行循环体,此段循环结构代码结束运行

运用案例:

求整数1 - 4的累加和

a = 0
b = 0
while a < 4:
    a += 1
    b += a
print(b)

运行结果:

  • 10

简单流程分解:

  • 变量a的值为0,变量b的值为0
  • a < 4 等于 0 < 4 判断值为True
  • a += 1 等于 0 + 1 a的值变为1
  • b += a 等于 0 + 1 b的值变为1
  • 变量a的值为1,变量b的值为1
  • a < 4 等于 1 < 4 判断值为True
  • a += 1 等于 1 + 1 a的值变为2
  • b += a 等于 1 + 2 b的值变为3
  • 变量a的值为2,变量b的值为3
  • a < 4 等于 2 < 4 判断值为True
  • a += 1 等于 2 + 1 a的值变为3
  • b += a 等于 3 + 3 b的值变为6
  • 变量a的值为3,变量b的值为6
  • a < 4 等于 3 < 4 判断值为True
  • a += 1 等于 3 + 1 a的值变为4
  • b += a 等于 6 + 4 b的值变为10
  • 变量a的值为4,变量b的值为10
  • a < 4 等于 4 < 4 判断值为False
  • 结束运行此段循环代码
  • 输出变量b的值为10

while...循环的四个部分:

  • 初始化变量,例如:a = 0 b = 0
  • 条件判断,例如:while a < 4:
  • 条件执行体(循环体),例如:b += a
  • 改变变量,例如:a += 1(也是循环体的一部分)

注意:

初始化的变量和条件判断的变量和循环体中改变的变量是同一个变量,这个变量如果不随着循环体改变,就会进入死循环,永远不会自动结束运行

a = 0
while a < 4:
    a += 0
    print(a)

运行结果:

  • 0
  • 0
  • 0
  • ...

会一直循环下去,只能手动停止,因为条件判断的变量没有被改变,值一直为True

求整数1 - 100之间偶数的累加和

a = 0
b = 0
while a < 100:
    a += 1
    if a % 2 == 0:
        b += a
print(b)

运行结果:

  • 2550

既然是求偶数相加,初始化变量a = 3b = 2是最节省运算次数的方法,后面可以直接从2+4开始运算,在不考虑运算次数的情况下,还是建议都初始化为整数0,方便观察。只要变量a小于100,就重复运行循环体,也就是变量a的值最多只能是99才能通过while a < 100:条件表达式,然后a += 1改变变量,变量a的值变成100100是偶数,会与变量b相加,然后回到while a < 100:条件表达式,100 < 100的运算值为False,这时会结束运行此段循环结构代码,这样可以保证最后求和的是100以内最后一个偶数,为什么会加一个选择结构的单分支if...语句呢,因为要保证与变量b相加的整数必须为偶数,才符合我们的选题,偶数累加和,通过if a % 2 == 0:条件表达式的判断,与2取余后等于0的很定是偶数,是偶数才和变量b相加,最后输出变量b的值为2550

还有一种写法:

# 求奇数累加和
a = 0
b = 0
while a < 100:
    a += 1
    if a % 2:  # 奇数和2取余的值为1,1的布尔值是True,所以这是求奇数累加和的
        b += a
print(b)
# 求偶数累加和
a = 0
b = 0
while a < 100:
    a += 1
    if not a % 2:  # 偶数和2取余的值为0,0的布尔值是False,not False为True,所以这是求偶数累加和的
        b += a
print(b)

运行结果:

  • 2500
  • 2550

这种方法是直接用对象的布尔值来判断,奇数和2取余必定为11的布尔值为True,偶数和2取余必定为00的布尔值为False,求偶数累加和直接用not把布尔值反过来就好了(例如:变量a的值为44 % 2等于00的布尔值为Falsenot False就变成了True,这样就可以运行下面的条件执行体,把变量a和变量b相加了)

当我们不确定while...循环需要的循环次数,可以用True来代替条件表达式,但这样会进入死循环,所以我们需要用到改变变量和流程控制语句break(流程控制语句break后面会学到)配合if...语句分支结构,来实现while...循环在合适的时机停止运行

a = 1  # 初始化变量a的值为1
while True:  # 用True代替条件表达式,实现不限次数循环
    a += 1  # 改变变量:每循环一次,变量a的值加1
    if a > 99:  # 设置合适的条件表达式,值为True的时候运行下列代码
        print('停止运行')  # 提示停止运行
        break  # 停止整个循环结构的运行

运行结果:

  • 停止运行

适用于不知道该设置多少次循环才合适的选题,但要注意流程控制语句breakif..语句分支结构的搭配使用,以免进入死循环

for...in...循环

语法结构:

for 自定义变量 in 可迭代对象:
----循环体(前面的----代表缩进的空格)

in代表从可迭代对象(字符串,序列等,目前学了这两个可迭代对象,后面会学到什么叫可迭代对象)中从左到右按顺序依次取值(又称为遍历),取的值依次赋值给for的自定义变量,每一次取值赋值后会运行一次循环体,直到可迭代对象中没有值可取了,此段循环结构代码结束运行

流程演示图:

for-in循环流程图

for bl in 'Python':  # 第一次取的值是P,将P赋值给变量bl,第二次取的值是y...直到无值可取
    print(bl)  # 第一次输出变量bl的值是P,第二次是y...上面无值可取,下面结束运行

运行结果:

  • P
  • y
  • t
  • h
  • o
  • n

可以看出,字符串'Python'中的字符从左到右,被依次赋值给了变量bl,然后通过print()函数依次打印输出

for bl in 'Python':
    print(bl)
print('-------------分割线--------------')
print(bl)

运行结果:

  • P
  • y
  • t
  • h
  • o
  • n
  • -------------分割线--------------
  • n

我们可以看到,最终变量bl的值为可迭代对象的最后一个字符n,也就是bl = 'n',和while...循环不同的是,无需提前声明变量bl(声明变量就是提前赋值给这个变量一个值,例如:上面while...循环中的a = 0 b = 0),因为for...in...循环本身可以声明一个自定义变量

可迭代对象range()函数(序列)

for bl in range(10):  # range(10)代表的整数序列为0 - 9,步长为1
    print(bl)

运行结果:

  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

可以看出,整数序列0 - 9从左到右,被依次赋值给了变量bl,然后通过print()函数依次打印输出

如果循环体中的代码不需要访问自定义变量,那么上面声明的自定义变量可以用 _ 下划线代替

for _ in range(5):  # _ 下划线代替自定义变量
    print('人生苦短,我用Python')  # 循环体没有访问自定义变量

运行结果:

  • 人生苦短,我用Python
  • 人生苦短,我用Python
  • 人生苦短,我用Python
  • 人生苦短,我用Python
  • 人生苦短,我用Python

range(5)代表的整数序列为0 - 4,步长为1,也就是[0, 1, 2, 3, 4]五个整数,所以循环体会被运行五次,可以用可迭代对象range()函数来控制循环体的运行次数,而循环体是我们需要重复输出的内容

运用案例:

求整数1 - 100之间偶数的累加和

b = 0  # 提前声明变量b,而变量a可以在for...in...循环中声明
for a in range(2, 101, 2):
    b += a
print(b)

运行结果:

  • 2550

整数1 - 100之间第一个偶数为2,所以设置开始数为2,步长为2,可以保证每两个相邻整数之间相差为整数2,也就是全为偶数,例如2,4,6,8....等等,为什么停止数设为101而不是100呢,因为整数1 - 100之间最后的偶数为100,而range()函数创建的整数序列是不包含停止数的,所以要设置为101,才能保证最后一个偶数为100,一步步把获得的偶数通过循环体存储进变量b,最后打印输出变量b2550

求整数100 - 999之间的水仙花数

什么是水仙花数:

水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number),水仙花数是指一个3位数,它的每个位上的数字的3次方之和等于它本身(例如:1**3 + 5**3 + 3**3 = 153)(来自百度,了解下就好)

for i in range(1, 10):
    for j in range(0, 10):
        for k in range(0, 10):
            if i * 100 + j * 10 + k == i ** 3 + j ** 3 + k ** 3:
                print(i * 100 + j * 10 + k)

运行结果:

  • 153
  • 370
  • 371
  • 407

水仙花数是固定的,只有这四个,下面看解读

  • 第一行:声明自定义变量i,取值范围是range(1, 10)代表的整数序列为1 - 9
  • 第二行:声明自定义变量j,取值范围是range(0, 10)代表的整数序列为0 - 9
  • 第三行:声明自定义变量k,取值范围是range(0, 10)代表的整数序列为0 - 9
  • 第四行:变量i * 100,代表百位,变量j * 10,代表十位,变量k,代表个位,如果百位十位个位相加后获得的三位数整数与这三个数字的3次方之和相等,那么判定这个三位数整数为水仙花数(例如:1 * 100 + 5 * 10 + 3 == 1 ** 3 + 5 ** 3 + 3 ** 3,这个判断式的值为True
  • 第五行:打印输出水仙花数

首先第一行变量i取值整数1,第二行变量j取值整数0,第三行变量k取值整数0,第四行代码左边的表达式其实就定义了第一行的取值是百位数,第二行的取值是十位数,第三行的取值是个位数,这样就形成一个三位数整数100,计算后判断式的值为False,回到第三行,变量k取值整数1,三位数整数变成101,判断式的值还是False,继续回到第三行取值,直到变量k取值完整数9后,无值可取,再回到第二行,变量j取值整数1,第三行因为是第二行的循环体,所以重新开始取值,变量k取值整数0,这样三位数整数变成了110,就这样循环取值下去,只有三位数整数变成153,第四行判断式的值为True后,才会打印输出此次的三位数整数,这样可以保证只会输出水仙花数,第三行的取值范围是个位数的0 1 2 3 4 5 6 7 8 9,第二行的取值范围是十位数的0 1 2 3 4 5 6 7 8 9,所以第二行第三行加起来的取值范围是0 - 99,当三位数整数变成199后,第二行第三行都无值可取,这时候再回到第一行,变量i取值整数2,因为第二行第三行是第一行的循环体,第三行又是第二行的循环体,所以每一次回到上面后,下面的循环体又会重新开始计算取值,这样三位数整数变成了200,因为第一行的取值范围是百位数的1 2 3 4 5 6 7 8 9,所以第一行第二行第三行加起来的取值范围是100 - 999,而第四行第五行的单分支结构if...语句是循环体的最末端,也就是每一次生成一个新的三位数整数后,都要经过第四行的判断式看值是否为True,是才会运行第五行代码输出这个三位数整数,这样就形成了一个完整的循环判断流程

另一种写法:

c, i = 0, 0
for a in range(100, 1000):
    for b in str(a):
        c += int(b) ** 3
    if c == a:
        c *= 0
        print(a, '是水仙花数')
        i += a
    else:
        c *= 0
print('整数100 - 999之间的水仙花数总和为:', i)

# 简化后

c, i = 0, 0
for a in range(100, 1000):
    c *= 0
    for b in str(a):
        c += int(b) ** 3
    if c == a:
        print(a, '是水仙花数')
        i += a
print('整数100 - 999之间的水仙花数总和为:', i)

# 极致简化不求水仙花数总和

for a in range(100, 1000):
    c = 0
    for b in str(a):
        c += int(b) ** 3
    if a == c: print(a, '是水仙花数')

运行结果:

  • 153 是水仙花数
  • 370 是水仙花数
  • 371 是水仙花数
  • 407 是水仙花数
  • 整数100 - 999之间的水仙花数总和为: 1301

我的思路:

  • 获取一个三位数整数
  • 分解成单独的三个数字
  • 分别进行3次方幂运算
  • 一步步存储这三个数字的3次方幂运算的总和
  • 比较这个总和是否跟获取的三位数整数相等
  • 相等则判断为水仙花数

详细分解:

  • 第一行:系列解包赋值声明两个变量c = 0 i = 0
  • 第二行:获取一个三位数整数赋值到变量a
  • 第三行:因为必须是可迭代对象,所以用str()函数把变量a的值(三位数整数)转换成字符串,分解这个可迭代对象轮流赋值到变量b,这时变量b的值为字符串类型
  • 第四行:因为变量b要和整数进行运算,所以用int()函数把变量b的值转换为整数类型,变量b获得的值的3次方幂运算结果通过参数赋值符+=来存储到变量c
  • 第五行:条件判断式判断变量c所储存的三个数字各自的3次方幂运算的总和,与获得的三位数整数是否相等,相等则这个三位数整数为水仙花数
  • 第六行:通过参数赋值符*=来清零变量c所储存的值以便进行下一次储存和比较
  • 第七行:打印输出水仙花数
  • 第八行:储存水仙花数计算水仙花数的总和
  • 第九行:第五行的条件判断式值为False的话,执行else:后面的代码
  • 第十行:通过参数赋值符*=来清零变量c所储存的值以便进行下一次储存和比较
  • 第十一行:打印输出水仙花数的总和

变量c是用来临时储存获得的三个分解数字的幂运算之和的,所以不管最后三位数整数是否为水仙花数,变量c都必须通过c *= 0来清零,不然变量c的值会一直积累下去,再也得不到正确的值进行对比(例如:获得的三位数整数是152,三个位置上的数3次方幂运算之和为134,这时候变量c的值是134,然后获得三位数整数153,三个位置上的数3次方幂运算之和为153,符合水仙花数的要求,但是因为变量c的值没有提前清零,所以变量c的值变成了287,第五行的条件判断式值为False153也就被判定为不是水仙花数,这样判断是错误的,但这在计算机看来是正确的判断,所以我们的逻辑思维很重要),变量i是用来储存水仙花数的总和的,所以要在if...语句条件判断式的值为True的时候,才去储存那个符合的三位数整数,这样可以保证储存进去的都是水仙花数,第二行的for...in...循环语句负责生成一个个按顺序来的三位数整数(例如:100,101,102...等等,直到999结束),第三行的for...in...循环语句负责将获得的三位数整数分解成单独的三个位置上的数字轮流赋值到变量b,变量c来储存幂运算之和,if...语句来判断这个三位数整数是不是水仙花数,是的话,清零变量c的值,打印输出这个三位数整数,并且将这个三位数整数储存进变量iif...语句条件判断式的值为False的话,也要清零变量c的值,第三行的for...in...循环语句属于第二行for...in...循环语句的循环体,所以每次获得一个新的三位数整数的时候,第三行for...in...循环语句都会重新从左到右取值赋值给变量b,无值可取了才会回到第二行for...in...循环语句获取新的三位数整数,从100 - 999之间的三位数整数都判断完的话,这个for...in...循环结构代码结束运行,打印输出最终获取到的水仙花数的总和

第三种写法:

for i in range(100, 1000):  # 从100开始取值100,101,102...等等到999为止,例如:153
    a = i % 10  # 算出个位:153 % 10 = 3
    b = i // 10 % 10  # 算出十位:153 // 10 = 15,15 % 10 = 5
    c = i // 100  # 算出百位:153 // 100 = 1
    if i == a ** 3 + b ** 3 + c ** 3:  # 153 == 27 + 125 + 1,值为True,执行下面代码
        print(i)  # 输出打印水仙花数153

# 简化后

for i in range(100, 1000):
    a, b, c = i % 10, i // 10 % 10, i // 100
    if i == a ** 3 + b ** 3 + c ** 3: print(i)

运行结果:

  • 153
  • 370
  • 371
  • 407

这个方法非常简洁明了,直接看上面代码注释

最后修改:2021 年 07 月 01 日 12 : 38 PM