自我学习AI agent工程师的笔记vlog1
如果你是"看得懂教程但写不出代码"的初学者,这份笔记就是为你准备的。
核心内容:Python基础 → 文件I/O → 面向对象 → 命令行工具 → API调用 → 异步编程
每天读一遍,直到这些模板你能默写出来。
目录
- 万能骨架模板(任何程序从这里开始)
- 菜单循环模板(Day 1-2)
- 文件I/O模板(Day 3)
- 面向对象模板(Day 4)
- argparse模板(Day 5)
- Day 1-5完整串联——记账CLI全模板
- API调用模板(Day 6)
- 异步编程模板(Day 7)
- 你踩过的所有坑汇总
- 概念速查表
一、万能骨架模板
面对空白文件不知道写什么?永远先写这个骨架。 任何程序都可以从这里开始。
#!/usr/bin/env python # -*- coding: utf-8 -*- """这里写你的程序是干什么的""" import json, os, sys # 常用模块先导入 # import requests, argparse, ... # 按需要添加 def main(): """程序入口""" pass # 先占位,跑通了再填 if __name__ == "__main__": main()
💡 写完骨架先跑一次 python 文件名.py,没报错就有了地基,再往里填功能。
二、菜单循环模板
这是 Day 1-2 的核心结构。所有交互式程序(记账、学生管理、笔记CLI)都长这样。
# ── 用户交互菜单的通用结构 ── def main(): """主循环:显示选项 → 用户选择 → 执行功能""" while True: # 无限循环,直到用户选"退出" print("\n========= 功能菜单 =========") print("1. 功能一") print("2. 功能二") print("3. 退出") choice = input("请选择:") # input() 返回的是字符串! if choice == "1": func_one() # 调对应功能 elif choice == "2": func_two() elif choice == "3": print("再见!") break # break 跳出 while 循环 else: print("输入错误,请重新输入")
while 和 for 的选择
# 你知道循环次数 → 用 for for i in range(3): # 登录最多试 3 次 print(f"第 {i+1} 次尝试") # 你不知道循环次数 → 用 while while True: # 菜单不断显示,直到用户选退出 choice = input("> ") if choice == "q": break
⚠ input() 的常见错误
guess = input("猜一个数字:") if guess > 50: # ❌ 报错!字符串不能和数字比大小 guess = int(input("猜一个数字:")) # ✅ int() 转成数字 if guess > 50: # ✅ 正确
三、文件I/O模板
Day 3 的核心。I/O 再怎么变,永远就是"读"和"写"两个固定操作。背下这两个函数就行。
读取模板(背下来)
import json import os def load_data(filename="data.json"): """从 JSON 文件加载数据 → 返回 Python 字典/列表""" if os.path.exists(filename): # 先检查文件存不存在 with open(filename, "r", encoding="utf-8") as f: return json.load(f) # json.load = 文件 → 内存 return [] # 文件不存在,返回空(不报错)
写入模板(背下来)
def save_data(data, filename="data.json"): """把 Python 数据写回 JSON 文件""" with open(filename, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)
读写联动的标准流程
# 启动时 records = load_data() # 先在内存里建好数据 # 修改数据 records.append({"item": "午餐", "amount": 25}) # 注意:改了数据后,"立刻"调保存,否则数据留在内存,一关就没了 # 保存 save_data(records) # 把整个 records 写回文件
⚠ "w" 还是 "a"?—— 最常见的坑
# ❌ 错误:用 "a"(追加模式) with open("data.json", "a", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) # 第一次写:[{"a":1}] # 第二次写:[{"a":1}][{"b":2}] ← JSON 格式被破坏,读不回来了! # ✅ 正确:用 "w"(覆盖模式) with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) # data 里已经包含了旧+新数据,覆盖旧文件完全没问题
💡 直觉判断: JSON 整体存储 → 用 "w"。文本逐行追加 → 用 "a"。
json.dump 的方向记忆
# 加载(启动时做一次) json.load(f) = 文件 → 内存 # 保存(改完数据后做一次) json.dump(x, f) = 内存 → 文件
四、面向对象模板
Day 4 的核心。class 不是神秘的东西,它只是把一组相关的数据和函数打包在一起。
直观理解:class 是"饼干模具"
# class 是"饼干模具":一个模具可以压出无数个饼干(对象) class Student: # 定义模具 def __init__(self, n, c, m, e): # __init__ 是"压饼干"时自动调用的 self.name = n # self.name = "这个饼干的名称" self.scores = {"语文": c, "数学": m, "英语": e} def average(self): # 方法 = "这个饼干能做的事情" return sum(self.scores.values()) / 3 def __str__(self): # 决定 print(对象) 时显示什么 return f"{self.name}:{self.scores},均分{self.average():.1f}" # ── 使用 ── s1 = Student("韩立", 85, 92, 78) # 压出第一个饼干 s2 = Student("南宫婉", 90, 88, 95) # 压出第二个饼干 print(s1.name) # 取这个饼干的属性 print(s1.average()) # 调这个饼干的方法 print(s1) # 自动调 __str__
class 的核心要点
__init__是构造函数:创建对象时自动执行,用来初始化属性self代表"这个对象自己":调用时自动传入,你不需要写__str__用来控制打印显示:不加它print(对象)会显示<Student object at xxx>- 方法(如 average)的第一个参数永远是
self - 调用方法时不用传 self:
s1.average()就行,不是s1.average(self)
class 万能模板(直接复制改)
class XXX: """一句话描述这个类是干什么的""" def __init__(self, 参数1, 参数2): """初始化""" self.属性1 = 参数1 self.属性2 = 参数2 def 方法1(self): """功能描述""" pass def __str__(self): """控制打印显示""" return f"显示内容"
五、argparse模板
Day 5 的核心。argparse 让你的程序不仅能在交互模式下用,也能在命令行一次性传参。
import sys import argparse # ── 判断用户有没有传参 ── if len(sys.argv) > 1: # 如果用户传了额外参数 parser = argparse.ArgumentParser() # 1. 创建解析器 parser.add_argument("--action") # 2. 声明参数(双横线) parser.add_argument("--name") parser.add_argument("--amount", type=int) # 3. 指定类型 args = parser.parse_args() # 4. 解析参数 # 5. 用 args.xxx 取值 if args.action == "add": print(f"添加:{args.name}") elif args.action == "list": print("列出所有") else: # 没传参数 → 交互菜单 while True: print("1. 添加 2. 列出 3. 退出") choice = input("> ") if choice == "1": name = input("名字:") print(f"添加:{name}") elif choice == "3": break
参数类型对照
parser.add_argument("--name") # 字符串(默认) parser.add_argument("--age", type=int) # 整数 parser.add_argument("--price", type=float) # 小数 parser.add_argument("--verbose", action="store_true") # 开关(True/False)
⚠ argparse 不需要 class!
你之前问过"没有 class 怎么用 argparse"——答案:argparse 和 class 没任何关系!普通函数一样用。
def get_weather(city): """普通函数""" print(f"查询 {city} 的天气") if len(sys.argv) > 1: parser = argparse.ArgumentParser() parser.add_argument("--city") args = parser.parse_args() get_weather(args.city) # 直接调普通函数
sys.argv 的原理
# 终端输入: # python test.py --action add --name 韩立 # sys.argv 的值是: # ["test.py", "--action", "add", "--name", "韩立"] sys.argv[0] # "test.py"(程序自身的文件名) sys.argv[1] # "--action" sys.argv[2] # "add" len(sys.argv) # 5 # 所以:if len(sys.argv) > 1 → 用户传了额外参数吗?
六、Day 1-5 完整串联模板
前面所有内容的大集合:数据结构 + 文件 I/O + class + argparse + 菜单循环。
你以后写任何 CLI 工具都可以从这个模板改。复制就能用。
import json, os, sys, argparse """ 记账 CLI — 你可以用这个当万能起点 """ # ── 1. 类定义 ── class AccountBook: """账本类:封装所有记账操作""" def __init__(self): self.records = self._load() # 启动时加载数据 def _load(self): if os.path.exists("data.json"): with open("data.json", "r", encoding="utf-8") as f: return json.load(f) return [] def _save(self): with open("data.json", "w", encoding="utf-8") as f: json.dump(self.records, f, ensure_ascii=False, indent=2) def add(self, category, amount): self.records.append({"类别": category, "金额": amount}) self._save() # 改完立刻保存 print(f"已记录:{category} {amount}元") def show_all(self): for i, r in enumerate(self.records, 1): print(f"{i}. {r['类别']} — {r['金额']}元") def total(self): s = sum(r["金额"] for r in self.records) print(f"总支出:{s}元") # ── 2. 创建实例 ── book = AccountBook() # ── 3. 入口 ── if len(sys.argv) > 1: # 命令行模式 parser = argparse.ArgumentParser() parser.add_argument("--action") # add / list / total parser.add_argument("--category") parser.add_argument("--amount", type=int) args = parser.parse_args() if args.action == "add": book.add(args.category, args.amount) elif args.action == "list": book.show_all() elif args.action == "total": book.total() else: # 交互模式 while True: print("\n1. 记一笔 2. 查看所有 3. 总支出 4. 退出") choice = input("> ") if choice == "1": cat = input("类别:"); amt = int(input("金额:")) book.add(cat, amt) elif choice == "2": book.show_all() elif choice == "3": book.total() elif choice == "4": print("再见!"); break else: print("输入错误")
💡 这个文件是你的"万能起点"。每次写新 CLI 工具,复制这个文件,改 class 名和功能就行。
七、API调用模板
Day 6 的核心。让程序连上互联网从 API 拿数据。万物皆可套这个流程。
API 调用的完整流程
import requests, os from dotenv import load_dotenv # ── 1. 读取配置 ── load_dotenv() API_KEY = os.getenv("API_KEY") API_HOST = os.getenv("API_HOST") # ── 2. 发送请求(固定三步) ── headers = {"X-QW-Api-Key": API_KEY} # 认证信息 url = f"https://{API_HOST}/v7/weather/now?location=101010100" resp = requests.get(url, headers=headers) # 发 GET 请求 # ── 3. 解析响应 ── data = resp.json() # JSON → Python 字典 temp = data["now"]["temp"] text = data["now"]["text"] print(f"天气:{text},{temp}°C")
.env 文件格式
# .env 文件内容(和 main.py 放同一目录) API_KEY=你拿到的Key API_HOST=你拿到的Host # 注意:= 后面不要加空格,不要加引号
两个 API 的串联(城市名 → 天气)
def get_weather(city): headers = {"X-QW-Api-Key": API_KEY} # 第 1 步:城市名 → 城市代码 geo_url = f"https://{API_HOST}/geo/v2/city/lookup?location={city}" geo_data = requests.get(geo_url, headers=headers).json() city_id = geo_data["location"][0]["id"] # 第 2 步:城市代码 → 天气数据 weather_url = f"https://{API_HOST}/v7/weather/now?location={city_id}" weather_data = requests.get(weather_url, headers=headers).json() # 第 3 步:提取信息 temp = weather_data["now"]["temp"] text = weather_data["now"]["text"] feel = weather_data["now"]["feelsLike"] print(f"{city}:{text},{temp}°C(体感 {feel}°C)")
⚠ 区分大小写!
JSON 字段名严格区分大小写,写错了就 KeyError!
weather_data["now"]["feelsLike"] # ✅ 正确,L 大写 weather_data["now"]["feelslike"] # ❌ KeyError!全小写没有这个字段 # 不确定字段名时先 print 再写 print(weather_data) # 先打印看原始 JSON
八、异步编程模板
Day 7 的核心。异步 = "不干等,同时做别的事"。适合同时查多个城市、多个 API。
异步的三把钥匙
# 钥匙 1:async def —— 声明这是一个异步函数 async def get_weather(city): ... # 钥匙 2:await —— 等结果回来但不阻塞 async def get_weather(city): data = await client.get(url) # 去干别的了,结果回来再继续 # 钥匙 3:asyncio.run() —— 异步程序的启动器 asyncio.run(main()) # 一个程序只调一次
异步批量天气查询(完整模板,可复用)
import os, time, asyncio import httpx from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") API_HOST = os.getenv("API_HOST") async def get_weather(city, client): headers = {"X-QW-Api-Key": API_KEY} geo_url = f"https://{API_HOST}/geo/v2/city/lookup?location={city}" geo_resp = await client.get(geo_url, headers=headers) city_id = geo_resp.json()["location"][0]["id"] weather_url = f"https://{API_HOST}/v7/weather/now?location={city_id}" weather_resp = await client.get(weather_url, headers=headers) data = weather_resp.json() print(f"{city}:{data['now']['text']},{data['now']['temp']}°C") async def main(): cities = ["北京", "上海", "广州", "深圳"] async with httpx.AsyncClient() as client: tasks = [get_weather(c, client) for c in cities] await asyncio.gather(*tasks) if __name__ == "__main__": start = time.time() asyncio.run(main()) print(f"总耗时:{time.time() - start:.2f}秒")
同步 vs 异步速度对比
# 同步:一个一个来,总耗时 = 每个耗时相加 for city in cities: get_weather(city) # 等这个完,才开始下一个 # 5 个城市 ≈ 5 秒 # 异步:同时发请求,总耗时 ≈ 最慢那个城市 async with httpx.AsyncClient() as client: tasks = [get_weather(c, client) for c in cities] await asyncio.gather(*tasks) # 5 个城市 ≈ 0.6 秒(快 7 倍!)
⚠ 重要:只建一次客户端
不要把 AsyncClient 写在函数里面!否则每个城市查两次天气就建了 10 次客户端,速度浪费。
# ❌ 错误 async def get(city): async with httpx.AsyncClient() as c: # 每次都新建 resp = await c.get(url) # ✅ 正确 async def get(city, client): resp = await client.get(url) # 复用传入的 client async with httpx.AsyncClient() as client: # 只建一次 tasks = [get(c, client) for c in cities] await asyncio.gather(*tasks)
九、你踩过的所有坑汇总
这里记录了我从 Day 1 到 Day 7 实际出过的所有错误。如果你也遇到了类似的问题,直接对照看。
Day 1 — input() 忘了转 int
- 症状:TypeError: str 和 int 不能比较
- 原因:input() 返回字符串,不能直接和数字做运算
- 解决:
int(input("提示"))
guess = int(input("猜数字:")) # ✅
Day 1 — while 前忘了初始化变量
- 症状:NameError: name "guess" is not defined
- 原因:while 条件用的变量还没定义
- 解决:循环前先赋值
guess = 0
while guess != answer:
Day 3 — JSON 保存用了 "a" 模式
- 症状:JSONDecodeError,文件内容格式错乱
- 原因:"a" 追加模式破坏 JSON 格式
- 解决:永远用 "w"(覆盖)模式
with open("data.json", "w", encoding="utf-8") as f: # ✅
Day 3 — 忘了调 save_data()
- 症状:程序关了再打开,数据没了
- 原因:改了内存里的数据,没写回文件
- 解决:改完数据立刻调 save_data()
records.append(new) save_data(records) # ✅ 下一行就调
Day 4 — total 拼写错误
- 症状:看着不对劲,但不报错
- 原因:把 total 写成了 totle
- 解决:写完注意编辑器红色波浪线
def total(self): # 不是 totle
Day 5 — 以为 argparse 需要 class
- 症状:不知道怎么把 argparse 和函数连起来
- 原因:以为必须写成 对象.方法()
- 解决:argparse 直接调普通函数就行
def f(x): ... parser.parse_args() f(args.x)
Day 6 — 字典字段名大小写
- 症状:KeyError: "feelslike"
- 原因:Python 区大小写,和 JSON 里的字段不一样
- 解决:先 print(data) 看原始 JSON
data["now"]["feelsLike"] # ✅ 不是 feelslike
Day 6 — 忘了 cd 到文件目录
- 症状:can't open file
- 原因:终端路径不是文件所在目录
- 解决:先 cd 再 python
cd G:\PythonProject\xxx python main.py
Day 7 — AsyncClient 每次新建
- 症状:异步和同步速度差不多
- 原因:每次请求新建客户端,开销大
- 解决:建一次 client 传入函数
async with httpx.AsyncClient() as c: tasks = [f(x, c) for x in xs]
十、概念速查表
| 概念 | 一句话理解 |
|---|---|
| 列表 vs 字典 | 列表存多个东西(有顺序);字典存键值对(按名字查找) |
| json.load vs dump | load=文件→内存(读);dump=内存→文件(写) |
| "r" / "w" / "a" | r=读;w=写覆盖;a=写追加。JSON 永远用 w |
| 同步 vs 异步 | 同步=等一个做完再做下一个;异步=同时发,谁先回来谁处理 |
| def vs async def | def=普通函数;async def=异步函数(里面有 await) |
| = vs == | =赋值;==比较。写错不报错但逻辑错 |
| : 和缩进 | if/for/while/def/class 后面都有冒号,下一行缩进 |
| self | class 方法第一个参数,代表"我自己"。调用时不用传 |
| init vs str | init=创建时自动跑;str=print 时自动跑 |
| .env | 存 API Key,不写代码里。用 python-dotenv 读取 |
| if name==main | 只有直接运行本文件时才执行,被 import 时不执行 |
最后的话
这份笔记的核心就一句话:每次面对空白文件,先写骨架跑通,再一点一点往里填功能。
不要试图一次写完完整程序,先写 3 行跑一次,再写 3 行跑一次。
每天读一遍,读到这些模板能条件反射地写出来为止。
这是我的日常笔记,我感觉还行,每天都可以回来看一遍,感兴趣的小伙伴也可以去练练,实在不懂的,某seek,豆姐,某鸟教程看看就会了,反正做的时候没有模板我也是做不出来的,属于有想法,但是就差那临门一脚,只能看看能不能量变引起质变了,后面我每周都会把个人这周的学习笔记分享给大家的,大家觉得ok就点点赞留言留言,一起交流交流,或者有大佬(卖课的点击页面右上角谢谢~)能教教我提点我的最好了~~
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)