悟夕导航

🐍 Python 第二课:让程序有脑子——控制流与函数

15 0 0

课程目标:

  • 让程序学会做判断(if/else):不再是傻乎乎地从上往下执行
  • 让程序学会循环(for/while):重复的事情交给它,你去喝咖啡
  • 学会写函数:把代码打包,一次编写,到处使用
  • 认识基本数据结构:列表、字典、元组——数据的"收纳盒"
  • 学会处理错误:让程序优雅地崩溃(或者不要崩溃)

1) 回顾上节课

上节课我们学会了:

  • 安装 Python(如果还没装好,请回去补课)
  • 写第一个程序 print("Hello, Python!")
  • 变量和数据类型(int、float、str、bool)
  • 输入输出(input() 和 print())

常见问题解答:

Q:为什么我的 input() 得到的数字不能加减?
A:因为 input() 得到的是字符串!需要用 int()float() 转换。就像你问朋友"你多大了",他回答"二十",这是文字;你要做算术,得把它理解成数字 20。

Q:运行程序时提示 "IndentationError" 是什么意思?
A:缩进错误!Python 用缩进表示代码块,就像用括号表示段落。缩进不一致,Python 会抓狂。检查你是不是混用了空格和 Tab。


2) 条件判断:if/else——让程序有脑子

现实生活中,我们经常要做判断:

  • 如果下雨,就带伞;否则,就不带
  • 如果年满 18 岁,可以投票;否则,回家写作业

程序也需要这种能力!

基本语法

age = int(input("请输入你的年龄:"))

if age >= 18:
    print("你已经成年了,可以投票!")
else:
    print("未成年,回家写作业去吧!")

注意:

  • if 后面加冒号 :,表示"我要开始说条件成立时要做的事了"
  • 下一行要缩进(4 个空格),表示这些是"条件成立时"的代码
  • else 后面也要加冒号 :,表示"否则的话"

多条件判断:elif

如果不止两种情况呢?用 elif(else if 的缩写):

score = int(input("请输入你的成绩:"))

if score >= 90:
    print("优秀!")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格,准备补考吧...")

执行逻辑:

  1. 先检查 score >= 90,成立就打印"优秀",然后跳过其他所有条件
  2. 不成立,检查 score >= 80,成立就打印"良好",然后跳过其他
  3. 以此类推...
  4. 如果都不成立,执行 else

比较运算符

运算符含义例子
==等于5 == 5True
!=不等于5 != 3True
>大于5 > 3True
<小于5 < 3False
>=大于等于5 >= 5True
<=小于等于3 <= 5True

注意: == 是两个等号,表示"判断是否相等";= 是一个等号,表示"赋值"。写错的话,Python 会报错或者产生奇怪的结果。

逻辑运算符:and、or、not

有时候需要组合多个条件:

age = 25
income = 5000

# 申请信用卡的条件:年满 18 且收入超过 3000
if age >= 18 and income > 3000:
    print("信用卡申请通过!")
else:
    print("抱歉,条件不满足")

# 或者:VIP 用户或者消费满 1000 可以打折
is_vip = True
spent = 800

if is_vip or spent >= 1000:
    print("可以享受折扣!")
else:
    print("原价支付")

# not:取反
is_raining = False
if not is_raining:
    print("今天不下雨,可以出去玩")

优先级: not > and > or,不确定就加括号!

嵌套 if:if 里面套 if

is_member = True
purchase_amount = 200

if is_member:
    if purchase_amount >= 100:
        print("会员且满 100,打 8 折")
    else:
        print("会员但不满 100,打 9 折")
else:
    print("非会员,原价")

建议: 嵌套不要超过 3 层,否则代码会像迷宫一样难读。如果逻辑太复杂,考虑拆分或者优化。


3) 循环:重复的事情,让程序干

while 循环:当...的时候,就一直做

# 倒计时程序
count = 5

while count > 0:
    print(count)
    count = count - 1  # 或者写成 count -= 1

print("发射!🚀")

执行过程:

  1. 检查 count > 0,5 > 0 成立,执行循环体
  2. 打印 5,count 变成 4
  3. 检查 count > 0,4 > 0 成立,执行循环体
  4. 打印 4,count 变成 3
  5. ...直到 count 变成 0,0 > 0 不成立,退出循环

⚠️ 警告: 如果忘记写 count = count - 1,count 永远是 5,循环永远不停,这就是死循环!程序会卡死,需要按 Ctrl+C 强制终止。

for 循环:遍历神器

while 适合"不知道要循环多少次"的情况,for 适合"遍历一堆东西":

# 遍历字符串
for char in "Python":
    print(char)

# 输出:
# P
# y
# t
# h
# o
# n

range() 函数:生成数字序列

# 打印 0 到 4
for i in range(5):
    print(i)

# 打印 1 到 5
for i in range(1, 6):
    print(i)

# 打印 0, 2, 4, 6, 8(步长为 2)
for i in range(0, 10, 2):
    print(i)

range() 的三种用法:

  • range(5):0, 1, 2, 3, 4(从 0 开始,到 5 结束,不包括 5)
  • range(1, 6):1, 2, 3, 4, 5(从 1 开始,到 6 结束,不包括 6)
  • range(0, 10, 2):0, 2, 4, 6, 8(从 0 开始,到 10 结束,步长为 2)

循环控制:break 和 continue

break:立即退出循环

# 找第一个能被 7 整除的数
for i in range(1, 100):
    if i % 7 == 0:  # % 是取余数
        print(f"找到了:{i}")
        break  # 找到了,不找了,退出循环

continue:跳过当前这次,继续下一次

# 打印 1-10 中的奇数
for i in range(1, 11):
    if i % 2 == 0:  # 如果是偶数
        continue    # 跳过,不执行下面的 print
    print(i)

区别:

  • break:循环结束,彻底走人
  • continue:这次算了,继续下一轮

循环嵌套:循环里面套循环

# 打印乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}×{i}={i*j}", end="\t")
    print()  # 换行

输出:

1×1=1    
1×2=2    2×2=4    
1×3=3    2×3=6    3×3=9    
...

注意: 嵌套循环效率较低,大数据量时要小心。另外,内层循环的变量名不要和外层重复(虽然 Python 允许,但容易混淆)。


4) 函数:代码的打包艺术

为什么要用函数?

场景一: 你需要在程序的 10 个不同地方计算圆的面积。不写函数的话,你要复制粘贴 10 次同样的代码。万一要改公式(比如从 πr² 改成 3.14*r*r),你要改 10 处,漏改一处就 bug 了。

场景二: 你的主程序有 200 行,读起来像天书。如果把功能拆成函数,主程序可能只有 20 行,清晰明了。

定义函数

def greet(name):
    """
    这是一个打招呼的函数
    name: 对方的名字
    """
    print(f"你好,{name}!很高兴认识你!")

# 调用函数
greet("张三")
greet("李四")

语法解析:

  • def:define 的缩写,表示"我要定义一个函数了"
  • greet:函数名,要小写,用下划线连接多个单词(Python 风格)
  • (name):参数,函数需要的外部数据
  • """...""":文档字符串(docstring),说明函数是干嘛的,好习惯!
  • 函数体要缩进

返回值:return

函数可以处理数据,然后把结果"交出来":

def add(a, b):
    """计算两个数的和"""
    result = a + b
    return result  # 把结果返回给调用者

# 使用返回值
sum = add(3, 5)
print(sum)  # 输出 8

# 或者直接
print(add(10, 20))  # 输出 30

重要: return 执行后,函数立即结束,后面的代码不会执行:

def test():
    print("这行会执行")
    return "结束了"
    print("这行不会执行")  # 永远不会执行

test()

多个参数和默认参数

def make_coffee(coffee_type, size="中杯", sugar=True):
    """
    制作咖啡
    coffee_type: 咖啡类型(必填)
    size: 杯型,默认中杯
    sugar: 是否加糖,默认 True
    """
    sugar_str = "加糖" if sugar else "不加糖"
    print(f"制作完成:{size}的{coffee_type},{sugar_str}")

# 调用方式
make_coffee("拿铁")  # 中杯拿铁,加糖
make_coffee("美式", "大杯")  # 大杯美式,加糖
make_coffee("卡布奇诺", "小杯", False)  # 小杯卡布奇诺,不加糖
make_coffee("摩卡", sugar=False)  # 中杯摩卡,不加糖(指定参数名)

参数传递方式:

  • 按位置传:make_coffee("美式", "大杯")
  • 按名字传:make_coffee("摩卡", sugar=False)
  • 混合传:位置参数在前,命名参数在后

变量作用域:全局 vs 局部

# 全局变量:在函数外面定义的
global_var = "我是全局的"

def test():
    # 局部变量:在函数里面定义的,外面访问不到
    local_var = "我是局部的"
    print(global_var)  # 可以访问全局变量
    print(local_var)

test()
print(global_var)  # 正常
# print(local_var)  # 报错!NameError: name 'local_var' is not defined

如果想在函数里修改全局变量:

count = 0

def increment():
    global count  # 声明:我要用全局的 count,不是新建一个局部变量
    count += 1
    print(f"当前计数:{count}")

increment()  # 输出:当前计数:1
increment()  # 输出:当前计数:2

建议: 尽量少用 global,容易混乱。可以通过参数传递和返回值来交换数据。


5) 数据结构:数据的"收纳盒"

列表(List):有序、可变、啥都能装

# 创建列表
fruits = ["苹果", "香蕉", "橙子"]
mixed = [1, "hello", 3.14, True, [1, 2, 3]]  # 啥类型都能放,甚至列表里套列表

# 访问元素(索引从 0 开始!)
print(fruits[0])   # 苹果
print(fruits[1])   # 香蕉
print(fruits[-1])  # 橙子(-1 表示最后一个)

# 修改元素
fruits[1] = "葡萄"
print(fruits)  # ['苹果', '葡萄', '橙子']

# 常用操作
fruits.append("西瓜")      # 末尾添加
fruits.insert(1, "芒果")   # 在索引 1 处插入
fruits.remove("葡萄")      # 删除第一个匹配的元素
popped = fruits.pop()      # 删除并返回最后一个元素
print(len(fruits))         # 获取长度

# 切片:获取子列表
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5])   # [2, 3, 4](从索引 2 到 5,不包括 5)
print(numbers[:3])    # [0, 1, 2](从头开始到 3)
print(numbers[7:])    # [7, 8, 9](从 7 到末尾)
print(numbers[::2])   # [0, 2, 4, 6, 8](步长为 2)
print(numbers[::-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转!)

遍历列表:

for fruit in fruits:
    print(f"我喜欢吃{fruit}")

# 带索引的遍历
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

字典(Dictionary):键值对,查东西快

列表是按位置找元素,字典是按"名字"找:

# 创建字典
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机",
    "gpa": 3.8
}

# 访问
print(student["name"])  # 张三
print(student.get("phone", "未知"))  # 安全获取,不存在返回默认值"未知"

# 修改和添加
student["age"] = 21           # 修改
student["phone"] = "13800138000"  # 添加新键值对

# 删除
del student["gpa"]

# 遍历
for key in student:
    print(f"{key}: {student[key]}")

# 或者同时遍历键和值
for key, value in student.items():
    print(f"{key}: {value}")

使用场景: 存储对象信息、配置项、计数统计等。

元组(Tuple):不可变的列表

# 创建元组(圆括号)
coordinates = (10, 20)
rgb = (255, 128, 0)

# 可以访问,不能修改
print(coordinates[0])  # 10
# coordinates[0] = 15  # 报错!TypeError: 'tuple' object does not support item assignment

什么时候用元组?

  • 数据不应该被修改(比如坐标、RGB 颜色)
  • 作为字典的键(列表不能当键,因为可变)
  • 函数返回多个值(其实就是返回元组)
def get_min_max(numbers):
    return min(numbers), max(numbers)  # 返回元组

minimum, maximum = get_min_max([3, 1, 4, 1, 5, 9])
print(minimum, maximum)  # 1 9

集合(Set):去重和交集并集

# 创建集合(花括号,或者 set())
s = {1, 2, 3, 3, 3, 3}  # 自动去重
print(s)  # {1, 2, 3}

# 常用操作
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a & b)  # 交集:{3, 4}
print(a | b)  # 并集:{1, 2, 3, 4, 5, 6}
print(a - b)  # 差集:{1, 2}
print(a ^ b)  # 对称差集(只在其中一个集合中的元素):{1, 2, 5, 6}

6) 错误处理:让程序优雅地犯错

常见错误类型

错误类型说明例子
SyntaxError语法错误漏了冒号、括号不匹配
NameError名字错误使用了未定义的变量
TypeError类型错误字符串和整数相加
ValueError值错误int("abc")
IndexError索引错误访问列表不存在的索引
KeyError键错误访问字典不存在的键
ZeroDivisionError除零错误10 / 0

try/except:捕获错误

try:
    num = int(input("请输入一个数字:"))
    result = 10 / num
    print(f"10 除以 {num} 等于 {result}")
except ValueError:
    print("输入的不是有效数字!")
except ZeroDivisionError:
    print("不能除以零!")
except Exception as e:
    print(f"发生了未知错误:{e}")

执行流程:

  1. 先执行 try 块里的代码
  2. 如果出错,根据错误类型匹配 except
  3. 匹配成功,执行对应的 except 块,然后继续
  4. 没有错误,跳过所有 except

else 和 finally

try:
    f = open("data.txt", "r")
    content = f.read()
except FileNotFoundError:
    print("文件不存在")
else:
    print("文件读取成功!")
    print(content)
finally:
    print("无论成功与否,这行都会执行")
    # 通常用来关闭文件、释放资源等

7) 综合练习

练习 1:猜数字游戏

计算机随机生成一个 1-100 的数字,用户来猜,告诉用户猜大了还是小了,直到猜中。

提示:random.randint(1, 100) 生成随机数,需要 import random

参考答案:

import random

target = random.randint(1, 100)
attempts = 0

print("猜数字游戏!我想了一个 1-100 之间的数字。")

while True:
    try:
        guess = int(input("请输入你的猜测:"))
        attempts += 1
        
        if guess < target:
            print("太小了!")
        elif guess > target:
            print("太大了!")
        else:
            print(f"恭喜你猜中了!答案就是 {target},你用了 {attempts} 次。")
            break
    except ValueError:
        print("请输入一个有效的数字!")

练习 2:学生成绩管理系统

用字典存储学生信息(姓名、成绩),实现以下功能:

  1. 添加学生
  2. 删除学生
  3. 查询学生成绩
  4. 显示所有学生
  5. 计算平均分

提示: 用字典存储,key 是学生姓名,value 是成绩。用循环显示菜单。

参考答案(框架):

students = {}

def add_student():
    name = input("请输入学生姓名:")
    try:
        score = float(input("请输入成绩:"))
        students[name] = score
        print(f"已添加学生:{name},成绩:{score}")
    except ValueError:
        print("成绩必须是数字!")

def show_all():
    if not students:
        print("暂无学生数据")
        return
    print("\n学生成绩列表:")
    print("-" * 20)
    for name, score in students.items():
        print(f"{name}: {score}")
    print("-" * 20)

# 主循环
while True:
    print("\n1. 添加学生  2. 删除学生  3. 查询成绩  4. 显示全部  5. 计算平均分  6. 退出")
    choice = input("请选择操作:")
    
    if choice == "1":
        add_student()
    elif choice == "4":
        show_all()
    # ... 其他选项自己实现
    elif choice == "6":
        print("再见!")
        break
    else:
        print("无效的选择")

8) 下节课预告:从白银到黄金

下节课我们将学习:

  • 文件操作:读写文件,数据持久化
  • 模块和包:组织代码,使用第三方库
  • 面向对象编程(OOP):类与对象,封装继承多态
  • 常用标准库:os、sys、datetime、json 等
  • 实战小项目:综合运用所学知识

9) 学习建议

  1. 多写代码,少看视频:看懂了不等于会了,手指会了才是真的会
  2. 从模仿到创新:先抄示例代码,理解后尝试修改,最后独立写
  3. 善用百度:复制报错信息搜索,99% 的问题都有答案
  4. 读别人的代码:GitHub 上有很多优秀项目,学习别人的写法
  5. 坚持打卡:每天写一点,保持手感

记住: 编程是一门手艺,熟能生巧。你现在觉得难的,三个月后回头看会觉得"就这?"。

遇到问题? 百度一下,或者放一放,明天再看。有时候大脑需要后台编译。

祝编程愉快!Keep calm and code on! 🐍


课后作业:

  1. 完成上面的两个练习
  2. 用循环打印各种图案(金字塔、菱形等)
  3. 写一个函数,判断一个数是否是素数
  4. 尝试用列表推导式重写一些循环(进阶)

下节课见!

0
快来点个赞吧

发表评论

隐私评论

评论列表

来写一个评论吧