跳转至

5.2 程序结构——分支语句

内容梗概

本课讲分支语句 if / elif / else。通过一个“输入年龄判断是否成年”的小例子引入内置函数 input(),并现场纠正了一个易错点:input() 返回的永远是字符串,比较前必须手动 int() 转换。随后用同学在群里提出的“表白程序”(“不喜欢”按钮永远点不到)作为综合案例,用 Python 内置的 tkinter 和 random 库实现了一个带界面的程序,借此讲解了窗口程序的消息循环/事件驱动机制、按钮的 command 回调与 <Enter> 事件绑定,以及如何用复杂的组合分支条件保证按钮随机移动后不压在鼠标下。

知识点详解

if / elif / else 基本结构

  • if-else 很好理解,前面讲布尔逻辑时已大量使用 (约 00:00)。
  • elif 是 "else if" 的缩写,为了让代码短一点(且 elif 与 else 正好同宽,对齐美观)(约 04:02)。
  • 答疑:raw_input 是 Python 2 的函数,Python 3 中没有,留待课后确认 (约 04:34)。

input() 内置函数(重点纠错)

  • input("提示语"):先输出参数中的提示语,然后等待用户在命令行输入内容,回车结束 (约 00:34)。
  • 关键易错点(老师现场“直播事故”后纠正,约 02:11–03:34):input() **不会**自动把输入转成数字,返回值永远是 str 字符串类型。要当数字比较必须先手动转换:int(input(...))。可用 type() 查看类型验证。
  • 变量命名规范:变量名要有意义(如这里该叫 age 而不是 condition),不要用 a/b/c 这类名字,这也是上次作业批改时给很多同学提的要求 (约 03:34)。

窗口程序与消息循环(结合表白程序讲解)

  • 带界面的程序(窗口程序)背后是一套**消息循环**机制 (约 16:15):
  • 用户在界面上的所有操作(移动鼠标、点击、输入、缩放窗口)都是消息/事件(event),被放入**消息队列**。
  • 程序有一个大循环不断从队列中取出消息,交给对应的**消息处理函数**处理。
  • window.mainloop() 就是开启这个主消息循环。
  • tkinter 要点:
  • 用 import tkinter as tk 起别名减少打字量 (约 09:52)。
  • tk.Tk() 创建窗体对象;window.title(...) 设标题;window.geometry('800x600') 设分辨率(800×600 像素)。
  • tk.Button(window, text='不喜欢', command=hitme) 创建按钮:第一个参数指明属于哪个窗口;text 是按钮上显示的文本;command 传入一个**函数名**,按钮被点击时执行该函数(回调)。
  • 按钮创建后必须调用 .pack() 才会显示在窗口上。
  • 按钮.bind('<Enter>', escape) 为按钮绑定“鼠标进入”事件:鼠标一碰到按钮就调用 escape 函数——这是按钮“乱跑”的关键;去掉这行代码按钮就能被点到 (约 12:07–15:09)。

复杂组合分支条件的设计

  • 按钮随机移动的逻辑:escape 函数获取按钮位置(左上角坐标 x, y)和宽高,捕获鼠标位置 MouseX/MouseY,然后在窗口范围(x: 0–800,y: 0–600)内随机新坐标 (约 19:11–24:56)。
  • 为什么不能无脑随机:随机坐标可能正好盖住鼠标,按钮就“自投罗网”了。所以每次随机后要用组合条件判断新位置是否会压到鼠标:
  • 横向:x < MouseX 时还需 x + 宽度 < MouseX;若 x 本身就在鼠标右侧(x > MouseX)则无需考虑宽度。
  • 纵向同理。只有 x、y 两个方向都避开鼠标,新位置才合法。
  • 这个案例放在“分支”一节的原因:展示了用多个条件组合出复杂判断条件的实际用途。

示例与演示

  • 年龄判断示例:age = int(input("请输入你的年龄")),配合 if age >= 18: ... else: ... 判断是否成年(演示了 input 不转 int 会出错的“直播事故”及修复)。
  • 表白程序综合演示:
  • 结构:两个消息处理函数(hitme 点击回调打印“不喜欢”;escape 鼠标进入时移动按钮)+ 很短的程序主体(建窗体、建按钮、pack、绑定事件、mainloop)。
  • 演示去掉 <Enter> 绑定后按钮可点击、打印“不喜欢”;加上绑定后按钮永远点不到。
  • 白板上画图讲解消息循环/消息队列,以及坐标判断条件的几何含义。

重点与难点

  • input() 永远返回字符串,数字比较前必须 int() 转换——老师自己都会讲错,务必牢记。
  • 变量命名要有意义,从短代码开始养成习惯。
  • 理解事件驱动模型:消息循环 + 消息队列 + 消息处理函数(回调),这是所有 GUI 程序的通用逻辑。
  • 复杂分支条件来自多个简单条件的组合(and/or),要结合几何/业务含义逐一分析。
  • command= 和 bind() 传的是函数名(不是函数调用,不加括号)。

关联内容

  • 前置:5.1 布尔逻辑(判断条件、短路运算、比较运算)是本课分支条件的直接基础;type() 来自数据类型章节。
  • 本课的函数回调(hitme、escape)在 5.4 函数一节继续被用作 lambda 匿名函数的例子。
  • 表白程序中的死循环 + break 用法在 5.3 循环语句一节被回顾;pass 占位符也以本课的 hitme 函数为例讲解。
  • tkinter 只用了 Python 内置库,呼应课程“不装第三方库也能写界面程序”的理念;后续实践部分会讲更多实例(如发邮件)。