Day 04 / 共 68 天 · 阶段 1 编程地基

Python 极速入门②

昨天(Day 03)学了变量和 if/循环——单个盒子和基本流程。今天升级:把一段常用代码打包成可复用的函数,用列表/字典这类"大容器"装一堆数据,还会把结果写进文件存下来。函数 + 字典是写 Agent 的绝对核心;明天(Day 05)会学类、模块和虚拟环境,补齐地基最后一块。

📍 你在阶段 1(编程地基 D3-9)的位置
D03 Python① D04 Python② D05 Python③ D06 命令行&Git D07 调 API
💡 用一个类比兜住今天(今天全程沿用「开一家小餐馆」的世界观) 写程序 = 经营一家小餐馆函数 = 厨房里一台料理机(投进原料→吐出成品,想用几次用几次,不用每次手工现做);列表 list = 排队上菜的托盘(有先后顺序);字典 dict = 带姓名标签的储物柜(靠"名字"秒取,不用一个个翻);元组/集合 = 封死的套餐盒 / 会自动去重的会员名单;文件 = 冰箱(关机断电,存进去的东西还在)。今天你从"打杂"升级成"会用设备的大厨"。
L01

函数:把常用步骤打包成一台机器

🤔 痛点昨天算成绩评语,如果三个地方都要算,难道 if/elif/else 抄三遍?抄多了不但累,改规则时还得处处改、极易漏。
💡 本质把一段常用步骤打包起来、起个名字,就是函数。以后要用,喊一声名字就行——像餐馆买了台豆浆机,按一下就出豆浆,不用每次从泡豆开始。"写一次,到处调用"
# def = define(定义),后面跟函数名和括号,冒号+缩进写机器内部做什么
def greet():
    print("欢迎光临本店!")

# 定义好只是"造好机器",要用得"按按钮"——调用:函数名 + 括号
greet()      # → 欢迎光临本店!
greet()      # 想用几次用几次 → 欢迎光临本店!
👶 定义 ≠ 执行def 那几行只是"造机器",写完不会自己跑;必须写一句 greet()(带括号)按下按钮,机器才真正干活。新手常忘了调用,然后纳闷"为啥没反应"——检查有没有那对括号。
L02

参数 & 返回值:机器的"进料口"和"出料口"

🤔 痛点豆浆机总得能放不同的豆(黄豆/黑豆),还得把豆浆倒出来给别的环节用。函数怎么"收料"和"交货"?
💡 本质参数 = 进料口(调用时塞进去的原料);return = 出料口(把结果吐出来,给后面接着用)。没有 return 的函数只"干活不交货"(像只会吆喝的 greet)。
# 参数 name、price 是进料口;return 把总价吐出来
def make_bill(name, price, count):
    total = price * count           # 内部计算
    return f"{name} x{count} = {total}元"   # 交货:把这句吐出去

# 调用时按顺序塞原料,用变量接住吐出来的结果
bill = make_bill("拿铁", 30, 2)
print(bill)          # → 拿铁 x2 = 60元

# 参数可以给默认值:不传就用默认(count 默认 1)
def make_bill2(name, price, count=1):
    return f"{name} x{count} = {price*count}元"
print(make_bill2("美式", 25))        # 只传两个 → 美式 x1 = 25元
print(make_bill2("美式", 25, 3))     # 传三个 → 美式 x3 = 75元
函数 = 一台料理机:进料 → 加工 → 出料 参数(进料) "拿铁",30,2 make_bill() 内部计算 return(出料) "拿铁 x2 = 60元" 以后每个"工具"(查天气、算账、调模型)都是这样一台机器
图注:记住"进料口=参数、出料口=return"。后面给 Agent 写的每个"工具",本质就是这样一台函数机器。
📝 举个例子:函数就是 Agent 的"工具" 以后让 AI"查天气",你会写个函数 def get_weather(city): ... return "晴 25℃"——参数是城市名,返回是天气。大模型决定"要查北京天气"时,就相当于喊 get_weather("北京")今天的函数,就是后面 function calling 的地基。
L03

列表 list:一排有序的托盘

🤔 痛点要存"一批"东西——10 个用户、一串对话记录——总不能开 10 个变量 u1,u2,...u10 吧?
💡 本质列表用中括号 [],把一堆东西按顺序装一块儿,像餐厅排队的托盘。靠"位置编号"(下标)取东西,编号从 0 开始(第一个是 0 号!)。
menu = ["拿铁", "美式", "卡布奇诺"]
print(menu[0])        # 取第 1 个(编号从 0 开始!)→ 拿铁
print(menu[-1])       # -1 表示倒数第一个 → 卡布奇诺
print(len(menu))      # 一共几个 → 3

menu.append("摩卡")   # append = 在末尾加一个
print(menu)           # → ['拿铁', '美式', '卡布奇诺', '摩卡']

menu[1] = "冰美式"    # 按编号改掉某个
for item in menu:     # 配合 for 挨个处理(回忆 Day03)
    print("供应:", item)
0 号起步是新手第一大坑:三个元素的编号是 0、1、2,没有 3 号。想取 menu[3] 会报 IndexError(越界)。记住:"第 N 个"的编号是 N-1
L04

字典 dict:带标签的储物柜(最重要!)

🤔 痛点列表靠"第几个"取,可数据一多谁记得"用户年龄在第 3 个"?我想直接按"名字"取:给我 name、给我 age。
💡 本质字典用大括号 {},存成"键:值"一对对(key: value),靠"键"(名字标签)秒取"值",像带姓名牌的储物柜。这是整个 AI 开发里出现频率最高的数据结构——调模型的消息、API 返回的数据,全是字典。
# 键(key)是标签,值(value)是内容,用冒号连,逗号隔开
user = {"name": "小明", "age": 25, "vip": True}

print(user["name"])        # 按键取值(用中括号+键名)→ 小明
print(user["age"])         # → 25

user["age"] = 26           # 改值
user["city"] = "北京"      # 加一对新的键值
print(user)                # → {'name': '小明', 'age': 26, 'vip': True, 'city': '北京'}

# 安全取值:用 get,键不存在时返回 None 而不报错
print(user.get("phone"))   # 没有这个键 → None(不会崩)

# 遍历字典
for key, value in user.items():
    print(f"{key} = {value}")
📝 举个例子:你调大模型的第一段代码,就长这样 以后给大模型发消息,格式就是一串字典:
messages = [{"role": "user", "content": "你好"}]
这是"一个列表,里面装着字典"——列表管顺序(多轮对话),字典管"这条消息是谁说的(role)、说了啥(content)"。今天的 list + dict 组合,就是你第 11 天调 LLM 的原材料。

👶 小白:list 和 dict 我到底该用哪个?老是选择困难。

👨‍🏫 老师:一句口诀——在乎"顺序、第几个"用 list,在乎"按名字找"用 dict。排队的托盘(谁先谁后重要)→ list;储物柜(靠姓名牌找)→ dict。而且它俩常常套着用:一个 list 里装很多 dict(比如"一堆用户,每个用户是一个字典")——这是最常见的组合,记牢。

L05

元组 tuple & 集合 set(了解即可)

🤔 痛点有时想要"定死了不许改"的一组数据,或者想"自动去掉重复"的名单。list/dict 不太顺手。
💡 本质两个补充容器:元组 tuple(圆括号 ())=封死的套餐盒,做好就不许改;集合 set(大括号但只有值)=会员名单,自动去重、不许重复。
容器写法特点什么时候用
列表 list[1, 2, 3]有序、能改大多数"一堆东西"
字典 dict{"a": 1}键值对、按名取结构化数据(最常用)
元组 tuple(1, 2, 3)有序、不能改一组固定值(如坐标 x,y)
集合 set{1, 2, 3}无序、自动去重去重、判断"在不在里面"
# 集合去重:一批有重复的标签,一秒去重
tags = ["AI", "Agent", "AI", "RAG", "Agent"]
unique = set(tags)              # 变集合,自动去重
print(unique)                   # → {'AI', 'Agent', 'RAG'}(顺序不保证)
print("AI" in unique)           # 判断在不在里面 → True

# 元组:定了就不许改(改了会报错)
point = (3, 5)
print(point[0])                 # 能读 → 3
# point[0] = 9                  # 这行会报错!元组不可修改
👶 现在的心态元组和集合先混个脸熟就行,不用背。90% 的日常用 list 和 dict 就够了。等真遇到"需要去重"或"这组值不许被改"的场景,回来查这张表即可。学习不用一次吃成胖子。
L06

读写文件:把东西存进"冰箱"

🤔 痛点程序一关,变量里的数据全没了(内存像案板,关机就擦干净)。怎么把结果永久存下来,下次还能读?
💡 本质把数据写进文件=放进冰箱,断电还在。Python 用 open() 打开文件,配 with 用完自动关好门(不浪费电、不忘关)。"w"=写(覆盖),"a"=追加,"r"=读。
# 写文件:with open(...) as f 打开,用完自动关闭
# "w" = write 写模式(文件不存在会新建,存在会清空重写)
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("第 4 天学完了\n")     # \n 是换行
    f.write("学了函数和字典\n")
# 出了 with 这块,文件自动关好 —— 冰箱门自动合上

# 读文件:"r" = read 读模式
with open("notes.txt", "r", encoding="utf-8") as f:
    content = f.read()             # 一次读全部内容
    print(content)
两个必带的习惯:① 中文一定加 encoding="utf-8",否则可能乱码或报错;② 永远用 with open(...) 这种写法,它保证文件用完自动关闭——不然可能丢数据。照抄这个模板就对了,原理以后慢慢懂。
📝 举个例子:文件就是 Agent 的"记忆"雏形 以后做 Agent,"记住之前聊过啥"就可以先用最土的办法——把对话写进一个文件,下次启动先读回来。Day 36 讲的"记忆 Memory"、Day 19 讲的"把 prompt 存文件管版本",底层动作都是今天这几行读写。别小看它。
L07

今日小结 + 动手 10 分钟

🧠 今天你应该能回答

  • 函数是什么?def 和"调用"的区别?参数和 return 各是啥?
  • list 靠什么取值?为什么第一个元素编号是 0?
  • dict 靠什么取值?为什么说它是 AI 开发里最重要的结构?
  • list 和 dict 怎么选?它俩最常见的组合是什么?
  • 怎么把数据永久存进文件?为什么要 withencoding="utf-8"?

✋ 动手 10 分钟:做一个"点单小账本"

新建 day04.py,把函数 + list + dict + 文件全用上。先跑通,再改改菜单和数量:

# 一份订单:一个 list,里面装很多 dict(最常见的组合!)
orders = [
    {"name": "拿铁", "price": 30, "count": 2},
    {"name": "美式", "price": 25, "count": 1},
    {"name": "摩卡", "price": 35, "count": 3},
]

# 一台"算单行小计"的机器(函数)
def line_total(item):
    return item["price"] * item["count"]   # 按键取值再相乘

# 逐单处理 + 累加总额
grand_total = 0
lines = []
for o in orders:
    sub = line_total(o)
    grand_total = grand_total + sub        # 变量累加
    lines.append(f"{o['name']} x{o['count']} = {sub}元")

lines.append(f"合计:{grand_total}元")

# 把账本写进文件存起来
with open("account.txt", "w", encoding="utf-8") as f:
    for line in lines:
        print(line)                        # 屏幕也打印一份
        f.write(line + "\n")               # 同时写入文件

# 期望:拿铁 x2=60、美式 x1=25、摩卡 x3=105、合计 190元

进阶(选做):再写个函数 most_expensive(orders),返回小计最高的那一单名字。练习"函数里用循环 + 返回值"的组合。

明日预告 · Day 05:Python③ 收尾编程语法——用 class 把"数据 + 相关函数"捆成一个对象、用 import 借用别人的模块、用 try/except 优雅地接住报错不让程序崩,还有最实用的虚拟环境 venv + pip 依赖管理(每个项目一间独立厨房,互不污染)。学完这些,你就有资格开始碰真正的 AI 代码了。
← Day 03 · Python 极速入门① Day 05 · Python 极速入门③ →