第4章:分支与循环——让代码学会“思考”和“重复”

写代码这件事,说白了就是两件事:做判断做重复。你想想看,我们人每天不也是这样吗?看到红灯就停,看到绿灯就走——这是判断。每天刷牙洗脸吃饭——这是重复。计算机也一样,没有分支和循环,它就是个死脑筋的计算器。

这一章,我们就来搞定这两个核心能力。我保证,学完这章,你写的代码会从“流水账”变成“有逻辑的程序”。

4.1 if判断语句——让代码有“脑子”

先来个最简单的场景。你在写一个图像分类程序,模型返回了一个置信度分数。如果分数大于0.8,我们就认为识别成功。否则,就标记为“不确定”。

在Python里,用if就能搞定:

confidence = 0.85

if confidence > 0.8:
    print("识别成功,置信度较高")

嗯,这里要注意:if后面跟的是一个布尔表达式,说白了就是“真”或“假”。如果表达式为True,就执行缩进里的代码。缩进在Python里是命根子,千万别搞错。

⚠️ 我曾经见过一个新手,把缩进搞成了4个空格和1个Tab混用,结果程序死活跑不起来。 我建议你统一用4个空格,编辑器里设置一下,一劳永逸。

4.2 运算符——判断的“工具包”

判断离不开运算符。我把它分成三类,你记牢了:

类型 运算符 示例 说明
比较运算符 == != > < >= <= score >= 0.5 比较两个值的大小或相等
逻辑运算符 and or not conf > 0.8 and label == 'cat' 组合多个条件
成员运算符 in not in 'dog' in labels 检查是否在集合中

我个人习惯把逻辑运算符叫做“条件胶水”。比如在视觉项目里,我经常要判断“如果置信度大于0.7并且类别是行人,才触发报警”。这时候and就派上用场了。

💡 一个小坑: 千万别把=(赋值)和==(等于)搞混了。我在项目中遇到过有人写if score = 0.9,结果直接把score改成了0.9,判断永远为真。这种bug找起来特别头疼。

4.3 if-else语句——两条路,选一条

现实世界不是非黑即白,但很多时候只有两条路。比如:

confidence = 0.65

if confidence > 0.8:
    print("高置信度,直接输出结果")
else:
    print("置信度不足,需要人工复核")

你看,if条件不满足,就走else。这就是最基础的分支结构。

如果路不止两条呢?用elif

score = 0.72

if score >= 0.9:
    grade = "优秀"
elif score >= 0.7:
    grade = "良好"
elif score >= 0.5:
    grade = "及格"
else:
    grade = "需改进"

print(f"模型表现评级:{grade}")

为什么会这样?因为elif是按顺序检查的。一旦找到满足的条件,后面的就不再执行了。这有点像流水线上的质检员——第一个没通过,才轮到第二个。

🔧 我的经验: 写多分支时,把最严格的条件放在最前面。比如先判断score >= 0.9,再判断score >= 0.7。顺序反了,逻辑就全乱了。

4.4 while循环——重复到条件不满足为止

循环是什么?就是让计算机帮你干重复的活。你想想看,如果让你手动处理1000张图片,你肯定疯掉。但计算机不会,它乐此不疲。

while循环的套路很简单:只要条件为真,就一直执行

count = 0
while count < 5:
    print(f"正在处理第 {count + 1} 张图片")
    count += 1

这段代码会打印5次。每次循环,count加1,直到count等于5,条件count < 5变成False,循环结束。

⚠️ 我曾经犯过一个低级错误: 忘记在循环里更新条件变量,结果程序陷入了死循环。CPU飙到100%,电脑风扇呼呼响。所以记住:while循环一定要有“出口”,要么改变条件变量,要么用break跳出去。

4.5 for循环——遍历一切

for循环是我用得最多的。它比while更优雅,更适合遍历列表、元组、字典这些“容器”。

比如,遍历一个图片路径列表:

image_paths = ["img1.jpg", "img2.jpg", "img3.jpg"]

for path in image_paths:
    print(f"正在加载:{path}")
    # 这里可以调用你的图像处理函数

如果你想按序号来,配合range()函数:

for i in range(5):
    print(f"第 {i+1} 轮训练开始")

range(5)会生成0到4这5个数字。注意,是从0开始,到4结束。这是编程里的老规矩了,习惯就好。

💡 我个人习惯: 在视觉项目里,我经常用for img in dataloader:来遍历数据加载器。PyTorch的DataLoader配合for循环,简直是天作之合。你后面会学到的。

4.6 break和continue——循环的“刹车”和“跳过”

有时候,循环不需要跑完。比如你在1000张图片里找一张包含“猫”的图片,找到了就停。这时候用break

images = ["dog.jpg", "cat.jpg", "bird.jpg"]

for img in images:
    print(f"检查:{img}")
    if "cat" in img:
        print("找到猫了!停止搜索")
        break

输出结果:

检查:dog.jpg
检查:cat.jpg
找到猫了!停止搜索

你看,找到“cat.jpg”后,循环就停了。“bird.jpg”根本没被检查。这就是break的作用——立即跳出整个循环

continue呢?它是“跳过当前这一次,继续下一次”。

for i in range(5):
    if i == 2:
        print("跳过第3次")
        continue
    print(f"处理第 {i+1} 次")

输出结果:

处理第 1 次
处理第 2 次
跳过第3次
处理第 4 次
处理第 5 次

为什么会这样?因为continue只是跳过了i == 2那一次循环,后面的循环照常执行。说白了,break是“全剧终”,continue是“这一集跳过”。

🔧 避坑指南: 我曾经在嵌套循环里用break,以为能跳出所有循环。结果它只跳出了最内层的那一个。如果你想跳出多层循环,要么用标志变量,要么把循环封装成函数用return。这个坑,我替你踩过了。

4.7 综合小案例:图片质量筛选器

来,我们把今天学的串起来。假设你有一个图片列表,需要筛选出分辨率大于1000x1000的图片,并且只保留前3张:

images = [
    {"name": "img1.jpg", "width": 1920, "height": 1080},
    {"name": "img2.jpg", "width": 800, "height": 600},
    {"name": "img3.jpg", "width": 2560, "height": 1440},
    {"name": "img4.jpg", "width": 640, "height": 480},
    {"name": "img5.jpg", "width": 3840, "height": 2160},
]

qualified = []
count = 0

for img in images:
    # 判断:分辨率是否达标
    if img["width"] >= 1000 and img["height"] >= 1000:
        qualified.append(img["name"])
        count += 1
        print(f"合格:{img['name']}")
        
        # 够了3张就停
        if count >= 3:
            print("已收集足够的高质量图片,停止筛选")
            break
    else:
        print(f"不合格(分辨率不足):{img['name']}")
        continue

print(f"\n最终筛选结果:{qualified}")

这个例子包含了if判断、and逻辑运算符、for循环、breakcontinue。你仔细看一遍,应该能完全理解。

🎯 核心总结:

  • if/elif/else:让代码做选择,条件从上到下依次检查
  • while:条件为真就一直循环,记得要有出口
  • for:遍历容器,配合range()可以按序号循环
  • break:跳出整个循环
  • continue:跳过当前这一次,继续下一次

好了,这一章的内容就到这里。分支和循环是编程的“骨架”,你掌握了它们,就能写出有逻辑、能重复执行的程序了。下一章,我们会聊聊函数——把代码打包成“工具”,随用随取。

嗯,先消化一下今天的内容。动手敲一遍代码,比看十遍都管用。