= 98
price if price <100:
print ('buy')
buy
我们的程序到目前为止大多是“一条道走到黑”,从上到下顺序执行每一行代码。
完成本章学习后,你将能够:
if
, elif
, else
语句,让你的程序根据特定条件执行不同的代码路径,实现决策逻辑。while
循环,在满足特定条件时重复执行一段代码。for
循环,遍历序列(如列表、字符串、元组)或其他可迭代对象中的每一个元素,并对它们进行操作。range()
函数如何与 for
循环结合,方便地执行固定次数的重复任务。break
和 continue
语句来更精细地控制循环的流程。掌握了条件和循环,你的程序将不再是简单的线性执行,而是能够根据输入和中间结果展现出“智能”行为,能够自动化处理大量重复工作。这是从编写简单脚本到构建复杂应用程序的关键一步。
(推荐) 使用vscode的插件 indent-rainbow (或者类似的其他插件),可以用不同颜色显示缩进的层级。忘记怎么安装插件的可以看前面的章节。
if 语句:
= 98
price if price <100:
print ('buy')
buy
if-else语句:
= 102
price if price <100:
print ('buy')
else:
print('not buy')
not buy
if-elif语句:
= 102
price if price <100:
print ('buy')
elif price < 110:
print ('hold')
elif price < 120:
print ('think about it')
else:
print ('sell')
hold
= 70
price if price<80: print('buy')
buy
= 85
price 'buy' if (price<80) else 'don\'t buy'
"don't buy"
练习1:小明身高1.75m,体重80.5kg。请根据BMI公式(体重除以身高的平方)帮小明计算他的BMI指数,并根据BMI指数:
用if-elif判断并打印结果:
小提示:
= 1.75
height = 80.5
weight
# 计算BMI指数
# 用 if-elif 判断,并打印结果
练习2:判断闰年:从year, 判断是否为闰年?
提示1: 闰年: 年份能被4整除但不能被100整除的 或者 能被400整除
提示2: 判断一个数字能否被某个数整除,可以判断其余数(取余运算是%
)是否为0,如a % 2 == 0
如果为True
则为偶数。
注:可以用多层的条件语句,或者用多个逻辑运算来写。
= 2005 # 或者任何一年 year
例子:用if-else求a、b、c 3个数中最大的一个
思路:
= 4
a = 9
b = 2
c
if a>b:
if a>c:
=a
max_valueelse:
=c
max_valueelse:
if b>c:
=b
max_valueelse:
=c
max_value
print(f"最大值是{max_value}")
最大值是9
对一个变量number,判断是否能被2或者3整除
按具体的情况,请输出:
思路:
前面讲过,布尔型有2种,真True
和假False
。
实际上,这2个符号,是布尔型变量的值,和1,2,3,4
是整型的值,'apple'
是字符串的值类似。但布尔型的值只有2种。
例如,有一个变量,用于表示“现在是否下雨”。这个问题只有2个答案,是或者否,显然这就可以用布尔型来表示:True
就表示下雨,False
就表示没下雨。我们就定义一个布尔型变量is_raining
。
注意:为了达到顾名思义的效果,布尔型的变量,可以考虑用is_
,has_
等等开头,显示这是个“是否”问题的答案。
# 表示现在正在刮风下雨
= True
is_raining = True is_blowing
判断是否同时在刮风和下雨
print(is_raining and is_blowing)
True
布尔运算,其结果,也是一个布尔类型的变量:因此可以赋值给另一个变量。
bad_weather
= is_raining and is_blowing # 布尔运算的结果,也是一个布尔型,并且可以赋值给另一个变量
bad_weather print(bad_weather)
True
换一种理解,你可以把and
运算,看成一个函数。类似于:
bool_and(x, y)
就可以视为一个函数调用,返回的结果,就是与操作
= bool_and(is_raining, is_blowing) # 这是随便写的,无法执行 bad_weather
回到我们的if
语句。if
语句接受的判断条件,本质上一个布尔型变量
if is_raining and is_blowing:
print('don\'t go outside!')
don't go outside!
等价于:
if bad_weather:
print('don\'t go outside!')
don't go outside!
所以,你在if
后面跟一个布尔型变量bad_weather
,或者一个条件is_raining and is_blowing
,是等价的。但后者可以少进行一次赋值的操作,并且节约一个变量名。
回看前面的例子:
= 2
a = 3
b if a > b:
print('a > b')
else:
print('a <= b')
a <= b
可以把a > b
看成是“一个布尔型的变量”,这个变量,保存了a > b
的结果,只是我们没有把这个结果赋值给一个变量名(没有绑定一个标签),而是直接放进了if
语句中。
这等价于:
= 2
a = 3
b
= a > b
is_a_bigger
if is_a_bigger:
print('a > b')
else:
print('a <= b')
a <= b
小结,布尔运算,实际上会返回一个新的布尔值,可以和任何变量一样进行操作,比如绑定名字,放进if里等等
while循环比较直观,“只要条件成立,就重复执行某块代码块”
或者说,“重复执行某块代码块,直到条件不成立为止”
while 判断条件(condition):
执行语句(statements)
思想:
+=
例如 i += 2
即让i
自增2,等价于 i = i + 2
= 1
i += 999
i print(i)
1000
设计一个从1到5的循环
= 1
i while i <= 5:
print(i)
+=1
i
print("循环结束")
1
2
3
4
5
循环结束
小提示:如何判断一个数是否是偶数?取余的操作符是%
小提示:你可以建立一个新的变量,用来存放累加的结果
例如,有一个班级同学姓名的列表,我们要打印每一个同学姓名的最后一个字母。
= ["Alex", "Bob", "Clare"]
students print(students)
['Alex', 'Bob', 'Clare']
没有循环的时候,我们怎么做?
我们可能会尝试,把students这个列表,按索引号,逐一取出,然后再打印首字母
len(students)
3
知道students里有3个同学,我们就知道,索引号(index)是0,1,2。
现在我们用最笨的办法,逐一取出,逐一打印
= students[0] # 取0号元素
s print(s[-1]) # 打印最后一个字母
# 对其他2个元素,手动重复一次
= students[1]
s print(s[-1])
= students[2]
s print(s[-1])
x
b
e
x
b
e
显然,
我们前面学了while循环,我们尝试用while来做完成
len(student) - 1
= 2students[i]
来取出对应的元素= 0
i
while i < len(students): # 注意,这里是 i < 3
= students[i] # 即i = 0, 1, 2
s print(s[-1])
+= 1 i
x
b
e
for s in students:
print(s[-1])
x
b
e
比较for循环,和手动操作
#%% do it yourself
= students[0] # 取0号元素
s print(s[-1]) # 打印最后一个字母
# 对其他2个元素,手动重复一次
= students[1]
s print(s[-1])
= students[2]
s print(s[-1])
x
b
e
#%% for
for s in students:
print(s[-1])
x
b
e
上述for循环完成的事:
for循环一般用于遍历一个可迭代对象(简单理解,就是如 List、Tuple和Dict这样具有序列结构的数据)
其作用是“对其中的每一个元素都做点什么”。
如果你要对一个List中的每一个元素都做点什么,此时就应该用for循环。
例如,我们要打印a = [1,2,3,4,5]
中的每一个元素
或者说,我们要对a = [1,2,3,4,5]
中的每一个元素,执行打印这个动作。
= [1,2,3,4,5]
a_list
for i in a_list:
print(i)
1
2
3
4
5
解释
a = [1,2,3,4,5]
中的每一个元素,执行打印这个动作。a_list
是一个列表的名字for i in a_list:
:我们把中的每一个元素,按顺序,逐个过一遍。轮到哪个元素,我们就用i
来指向它。print(i)
:由上一句,i
可以看作每一个元素代称,我们打印它。注意,前面由“1个缩进”。range(起点, 终点, 步长)
:快速生成一个序列:惰性的(lazy)可迭代序列
range(0,10)
:生成一个0 ~ 9的自然数序列(包括起点,不包括终点)range(0,10,2)
:生成一个0 ~ 8的偶数序列(包括起点,不包括终点)print(range(0,10))
print(list(range(0,10)))
range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
在for循环中,我们往往用range来快速生成一个数字序列,避免手动输入非常多的数字。
print('打印奇数序列:')
for i in range (1,20,2): # 替代手动输入 [1,3,5 ...]
print (i)
打印奇数序列:
1
3
5
7
9
11
13
15
17
19
我们就可以:
注意: break和continue,在for和while循环中都可以使用。
# break 的范例
# for语句试图执行1000次循环
# 但中途被break语句中断
for i in range(1000):
print (i)
if i >= 3:
print('如果i大于等于3,则中断循环。')
break
print('循环结束')
0
1
2
3
如果i大于等于3,则中断循环。
循环结束
# continue 的范例
# 每次遇到偶数,就会直接开始下一次迭代
# 因此i为偶数时,print将不会被执行
# 只打印列表中的奇数
= [1, 2, 3, 4, 5, 6]
numbers for num in numbers:
if num % 2 == 0: # 如果是偶数
continue # 跳过本次循环中后续的print语句,直接开始下一次迭代
print(num) # 这行只在num是奇数时执行
1
3
5
当使用 while
循环时,我们需要特别注意循环的终止条件。如果 while
后面的条件判断永远为 True
,那么循环体内的代码就会被无限次地执行下去,程序就会“卡住”,这就是所谓的无限循环。
注意: 如果陷入无限循环,可以直接关闭vscode!
一个容易犯的错误导致无限循环的例子:
# 警告:下面的代码会导致无限循环,执行时可能需要手动停止程序!
= 0
count while count < 5:
print("这是一个循环...")
# 糟糕!忘记更新 count 的值了 (比如写 count += 1) # 所以 count 永远是 0,count < 5 永远是 True
在上面的例子中,因为 count
的值没有在循环体内被修改以最终使 count < 5
这个条件变为 False
,所以 print
语句会不停地执行。
如何避免?
确保你的循环体内部有某些操作,能够最终影响到 while
的判断条件,使其在某个时刻变为 False
,从而让循环能够正常结束。
while True:
与 break
有时,我们确实需要一个循环持续运行,直到某个特定的内部事件发生才停止。在这种情况下,一种常见的模式是使用 while True:
来创建一个表面上的无限循环,然后在循环体内部使用 if
语句来检查某个条件,一旦条件满足,就用 break
语句来强行跳出循环。
示例:等待用户特定输入
while True:
= input("请输入 'quit' 来结束程序: ")
user_input if user_input == "quit":
print("程序已结束。")
break # 如果用户输入了 "quit",跳出循环
else:
print(f"你输入了: {user_input},请继续输入或输入 'quit' 退出。")
在这个例子中: 1. while True:
开始了一个循环,它自己永远不会停止。 2. 循环内部,我们获取用户输入。 3. if user_input == "quit":
检查用户是否输入了 “quit”。 4. 如果是,break
语句就会执行,立即终止 while
循环。 5. 否则,循环会继续,等待下一次输入。
这种 while True:
结合 break
的方式,为我们提供了一种灵活控制循环何时退出的方法,特别适用于那些退出条件不方便直接放在 while
判断里的情况。
求1~100之间能被7整除,但不能同时被5整除的所有整数。分别写For和While版本
求以下列表平均值。分别写For和While版本。
= [70, 90, 78, 85, 97, 94, 65, 80] score
对于一个排序的List,找到某一个元素的位置
思路
= [ 5,8,15,20,30,45,78,100,120,200 ]
a = 30 target
列表推导式可以让我们从一个可迭代的对象(典型的就是List本身)生成一个List。最常见的情况是从一个List生成另一个List。
例如,把a = [1,2,3,4,5]
中的所有数乘以2.
用循环我们可以这样做:
# 循环的版本
= [1,2,3,4,5]
a = []
b
for i in a:
*2)
b.append(i
print(b)
[2, 4, 6, 8, 10]
如果用列表推导式,可以更为简单:
= [1,2,3,4,5]
a = [i*2 for i in a]
b print(b)
[2, 4, 6, 8, 10]
一般的结构大概是这样的:
[do_something(i) for i in a_list]
遍历a_list中的每个元素(称之为i),做一个操作,然后结果保存形成一个新的列表。
显然,两端是中括号意味着我们会得到一个新的List。
另一个例子,把列表中的所有字符变为大写。
= ['abc','abcd','bcde','bcdee','cdefg']
s for x in s] [x.upper()
['ABC', 'ABCD', 'BCDE', 'BCDEE', 'CDEFG']
也可以结合筛选:遍历list中的元素,选出符合条件的,进行某个操作,形成新的列表。
[do_something(i) for i in a_list if condition(i)]
比如选出a中大于等于3的数,乘以2,再形成一个新的列表。
= [1,2,3,4,5]
a = [i*2 for i in a if i >=3 ]
b print(b)
[6, 8, 10]
当然,如果只是要筛选,不做其他操作,上面i*2
改成i
即可。
= range(1,6) # 迭代时会产生 1, 2, 3, 4, 5。回忆前文中range和list的区别
a = [i for i in a if i >=3 ]
b print(b)
[3, 4, 5]
['apple', 'banana', 'ant', 'animal', 'astronaut', 'airplane']
.
前面讲过,字典本身也是序列结构,因此我们也可以遍历字典。
我们可以用.keys()和.values()获得所有的key和list,那么我就可以按循环list的方法来做。
= {'x': 1, 'y': 3, 'z': 5}
d for key in d:
# 或者用 for key in d.keys()
print(key, d[key])
x 1
y 3
z 5
= {'x': 1, 'y': 3, 'z': 5}
d for value in d.values():
# 或者用 for key in d.keys()
print(value)
1
3
5
我们也介绍过dict可以看出一系列key-value的元组,因此可以遍历items。
回顾:d.items()可以返回 [(key,value),(key,value),...]
的结构。
d.items()
返回一系列 (键, 值) 对(元组)。在 for
循环中,我们使用 key, value
这种形式来自动地将每个元组中的两个元素分别赋值给 key
和 value
变量,这称为序列解包。
# 遍历每一个(key,value)对,进行某些操作
for key, value in d.items():
print(key,value)
x 1
y 3
z 5
和列表推导式类似,字典推导式也可以从一个可迭代对象(比如List,Dict或者任何别的),生成一个字典。
大概的结构如下:
{key:value for i in a_list}
比如,从a = ['Alex','Bob','Clare']
生成一个字典,其中key是元素(人名),value是人名的字符长度。
= ['Alex','Bob','Clare']
a = {s:len(s) for s in a}
len_a print(len_a)
{'Alex': 4, 'Bob': 3, 'Clare': 5}
或者从字典生成一个新字典,key不变,value*2。
= {'x': 1, 'y': 3, 'z': 5}
d = {key:value*2 for key,value in d.items()}
e print(e)
{'x': 2, 'y': 6, 'z': 10}
ages = {'Alice': 30, 'Bob': 25, 'Charlie': 40, 'Diana': 22}
请使用字典循环遍历,打印出所有年龄大于30的人名。
学会使用条件判断和循环,这意味着你的程序现在可以“思考”并“重复工作”了。
核心要点回顾:
if
、while
、for
等结构至关重要。if
, elif
, else
):
if condition:
: 如果条件为 True
,执行其下的代码块。elif another_condition:
: 在前一个 if
或 elif
条件为 False
时,检查此条件。else:
: 如果以上所有条件都为 False
,执行此代码块。while condition:
: 只要条件为 True
,就持续执行其下的代码块。注意避免无限循环,并确保有明确的退出条件或使用 break
。for item in iterable:
: 遍历可迭代对象(如列表、元组、字符串、range()
对象、字典的键/值/项)中的每一个元素。break
: 立即终止并跳出当前所在的整个循环。continue
: 立即跳过当前迭代中循环体内的剩余代码,并开始下一次迭代。else
子句: 当循环正常结束(即不是通过 break
跳出)时执行。range(start, stop, step)
: 生成一个数字序列,常用于 for
循环中控制迭代次数。记住“包含起点,不含终点”。if
和 while
的条件本质上都是布尔表达式,其结果决定了程序的执行路径。[expr for item in iterable if cond]
) 和字典推导式 ({k_expr: v_expr for item in iterable if cond}
): 提供了一种简洁、高效的方式来从一个可迭代对象创建新的列表或字典。常见错误提示 (本章相关):
IndentationError
: 缩进不正确或不一致。while
循环的条件永远为 True
,且没有 break
。if
条件的判断逻辑不符合预期,或比较运算符使用错误(如把 ==
写成 =
)。TypeError
/ NameError
: 在循环或条件判断中使用了未定义或类型不兼容的变量。通过条件和循环,你可以让程序自动化地处理更复杂的逻辑和数据。这是构建任何有实际用途的程序的基础。在接下来的学习中,我们将把这些控制流结构与函数结合起来,构建更模块化、更可重用的代码。