当前位置:首页>python>零基础 Python 速成:Agent 开发必备语法,第一次写代码也不怕

零基础 Python 速成:Agent 开发必备语法,第一次写代码也不怕

  • 2026-08-21 22:24:50
零基础 Python 速成:Agent 开发必备语法,第一次写代码也不怕

第一次写代码,你最怕什么?

想象一下这个场景:你决定进入 AI Agent 开发这个岗位,兴冲冲地打开第一个教程,结果满屏都是英文单词、括号、冒号和看不懂的符号,像在看天书。三分钟后,你默默关掉了页面,心里冒出一个念头:"我真的学得会吗?"

如果你有过这种感觉,别慌。今天这篇文章,就是写给此刻的你——零基础、没写过一行代码,但想往 AI Agent 开发走的人。

先给你吃颗定心丸:Python 是公认最适合新手的第一门语言,没有之一。它的语法接近自然语言,读起来像在读英文句子。你不需要先啃三个月底层原理再碰 AI,Python 可以直接上手。

更重要的是:Python 是 AI Agent 开发的"母语"。你要用到的 LangGraph、OpenAI 官方 SDK、各大模型 API,全都是 Python 生态。换句话说,你绕不开它,但也不用怕——它恰恰是最容易跨过的那道门槛。

这篇的目标很明确:学完之后,你能读懂并写出 Agent 开发中最常见的 Python 代码。我们只讲高频语法,不讲冷门技巧;每讲一个知识点,都会告诉你"它在 Agent 里到底怎么用"。

看完这一篇,你将拥有:搭好环境、写出第一个程序、玩转变量与容器类型、让代码学会判断和循环、用函数和类组织代码、让程序出错不崩溃、让多任务并发执行、解析大模型的 JSON 返回——最后还能亲手跑通一个"简易智能客服"。

阅读建议:准备好电脑,跟着每节的示例动手敲一遍。只看不练,等于白学。


01 环境准备:10 分钟搭好你的"厨房"

写代码就像做饭,得先把锅灶备好。你的"厨房"只需要两样东西:Python 解释器和编辑器。

Python 解释器 负责"听懂"你写的代码并执行它。先说 Windows:去 python.org 下载 Python 3.10 或更高版本,双击安装包后,注意第一屏最下方有一个复选框"Add Python to PATH",一定要勾上。PATH 相当于系统用来"找命令"的地址簿,不勾的话,之后在终端里敲 python 会提示"不是内部或外部命令"。勾选后一路点"Install Now"即可。

再说 Mac:Mac 不预装完整的 Python,首次在终端使用 python3 时系统会提示安装 Command Line Tools,按提示装完即可;更推荐的做法是直接去 python.org 下载官方安装包,一路下一步。装完后有个小区别:终端里要用 python3 而不是 python 启动命令,这是 Mac 的惯例,记住就行,不用纠结。

编辑器(VS Code) 是你写代码的地方。去 code.visualstudio.com 下载免费版本,安装后打开左侧的扩展商店,搜索"Python",安装微软官方插件。装完打开任意一个 .py 文件,VS Code 右下角会提示选择解释器,选你刚装的那个版本。有了插件,写代码时就有语法高亮、自动补全和错误提示,体验完全不同,强烈建议配好。

装完后打开终端(Mac 叫终端,Windows 叫 PowerShell),输入下面这行验证:

python --version

看到类似 Python 3.12.x 的输出,说明环境就绪。如果提示命令找不到,八成是 PATH 没配好:Windows 可以重新运行安装包勾选 PATH,或者手动把 Python 安装目录加进系统环境变量;Mac 直接用 python3 试试。

新手常见坑:电脑里可能同时存在 Python 2 和 Python 3,或者你装过 Anaconda,多版本共存时命令可能指向旧版本。遇到这种情况,用 python3(Mac/Linux)或 py -3.12(Windows)指定版本号即可。

一个让学习效率翻倍的建议:多用交互式环境(REPL)。 在终端直接输入 python 回车,就进入一个"即输即得"的界面,提示符变成 >>>,敲一行代码立刻出结果,最适合边学边试。想退出就输入 exit() 回车。后面几节的内容,建议你一边读一边在里面敲一遍,比只看不敲强十倍。

环境就绪,写第一个程序。新建一个 hello.py 文件,输入:

print("Hello, AI Agent!")

然后运行:

python hello.py

屏幕上出现 Hello, AI Agent!,你的编程生涯正式开始了。print() 是 Python 最常用的函数,作用就是把内容打印到屏幕上,调试代码时全靠它。

顺便学会写注释。单行注释用 # 开头,解释器会直接忽略它,是写给"未来的自己"看的说明:

# 这是单行注释,解释器不会执行它print("你好,AI Agent!")   # 也可以在代码后面加注释

多行说明可以用三引号包裹,这叫文档字符串(docstring),通常放在文件、函数或类的开头,描述这段代码是干什么的:

"""这是文档字符串,用于说明下面这段代码的用途。"""print("Hello, World!")   # 编程界的传统:第一个程序

新手常见坑:注释里的中文没问题,但代码里的引号、括号必须是英文符号。很多人第一次报错,就是因为不小心输入了中文的括号或冒号,报错信息还看不懂。记住:代码用英文符号,注释随便。

02 变量与数据类型:一切从"盒子"开始

编程的第一步,是理解变量。把变量想象成一个贴了标签的盒子:标签是变量名,盒子里装的是值,想换随时换。

name = "小明"# 字符串:一串文字age = 28# 整数height = 1.75# 浮点数:带小数is_student = False# 布尔值:True/False

注意,Python 不需要声明类型——你直接赋值,它自己会判断。这种特性叫"动态类型",对新手极其友好,能少写很多废话。

变量命名有讲究。 名字只能由字母、数字、下划线组成,且不能以数字开头,也不能用 if、for 这类关键字。惯例是用小写字母加下划线分隔,比如 user_input、api_key,这叫 snake_case。给变量起个能看懂的名字,比任何注释都管用——三个月后回来看代码,api_key 一看就懂,a1、x2 会让你抓狂。

数字类型:int(整数)和 float(浮点数)。 运算和数学课一样:+ - * /,另有整除 // 和取余 %。Agent 开发里最典型的用法是算成本:大模型按 token 计费,你要把返回的 token 数换算成钱。

total_tokens = 1024cost = total_tokens / 1000 * 0.002# 算一次 API 调用的费用print(cost)   # 0.002048

字符串(str)是拼 prompt 的主力。 字符串本质是一串字符,支持"索引"——从 0 开始数位置,也支持负数从末尾数:

text = "hello agent"print(text[0])     # h,第 1 个字符print(text[-1])    # t,倒数第 1 个字符print(text[0:5])   # hello,切片:取第 0 到第 4 个字符

切片是 [起点:终点],含头不含尾,这个规则记住一次,以后处处受用。它常用来截断超长的用户输入,保护你的 token 预算。

字符串还自带一堆方法,处理模型返回的文本时天天用:

raw = "  Hello, Agent!  "print(raw.strip())          # "Hello, Agent!",去掉首尾空白print(raw.upper())          # 全部转大写print(raw.lower())          # 全部转小写print("a,b,c".split(","))   # ['a', 'b', 'c'],按逗号拆成列表print("-".join(["a""b"])) # "a-b",把列表拼回字符串

split 和 join 是一对"拆"与"合":split 把字符串按分隔符拆成列表,join 把列表按分隔符合成字符串。处理 CSV 数据、拼接请求参数时经常用到。

字符串在 Agent 里的高频用法,是"判断"和"提取"。 判断用 in 和 startswith/endswith,比如判断用户输入是否包含某个关键词、是否以某个词开头:

user_input = "帮我查一下明天的天气"print("天气"in user_input)        # True,包含"天气"print(user_input.startswith("帮我")) # True,以"帮我"开头

提取则配合切片,从一段文本里截取指定位置的子串。大模型的返回结果往往是一大段文本,你要从中定位并截取关键信息,这套"定位 + 截取"能力就是基本功。真实 Agent 里处理工具返回的文本、解析模型输出,天天都在用。

类型转换很常用。 input() 拿到的用户输入永远是字符串,想当数字用必须转:

age = input("你几岁了?")    # 输入 18,得到的是字符串 "18"age_num = int(age)          # 转成整数 18print(age_num + 1)          # 19

int()、float()、str() 分别是转整数、转小数、转字符串的三件套。在 Agent 里,你经常要把模型返回的数字字符串转成数值去计算,或者把数字拼进提示词——类型搞混,程序就会报 TypeError。

布尔值(bool)只有两个:True 和 False。 比较运算会产出布尔值,比如 3 > 2 是 True,3 < 2 是 False。它常被用来做"开关",比如"是否启用重试""是否记录日志",后面你会经常看到。

除了上面这些基础类型,Agent 开发中还频繁用到几种"容器"类型:

  • list(列表):有序的集合,["搜索", "计算器"]
  • dict(字典):键值对,{"role": "user", "content": "你好"}
  • tuple(元组):不可变的列表,("北京", "上海")
  • set(集合):自动去重的集合,{"a", "b"}

list 详解:Agent 里到处是列表。 工具清单、消息历史、待办任务,全是 list。增删改查是基本功:

tools = ["搜索""计算器"]tools.append("天气")        # 末尾追加tools.remove("搜索")        # 删除指定元素popped = tools.pop()        # 弹出末尾元素,并拿到它print(tools)                # ['计算器']print(len(tools))           # 1,长度print("天气"in tools)      # False,判断是否包含

list 也支持索引和切片,和字符串一样:tools[0] 取第一个,tools[1:] 取从第二个到末尾。注意 append 是"加到末尾",insert 可以插到指定位置,remove 按值删,pop 按位置删并返回被删的元素。先记住 append 和 pop 这对最常用的即可。

list 在 Agent 里的典型场景,是"消息历史"和"工具清单"。 每次对话,你都要把用户和模型的对话一条条追加到 messages 里,这就是 append 的主场:

messages = []messages.append({"role""user""content""你好"})messages.append({"role""assistant""content""你好!"})# 会话越长,列表越长,模型能记住的上下文越多print(len(messages))   # 2

但消息太多会撑爆 token 预算,所以超限时要"丢最旧的"。实用技巧:用切片 messages[-10:] 只保留最后 10 条,或者用 pop(0) 弹出最早的一条。这种"滚动窗口"管理上下文的方式,是每个真实 Agent 都要处理的细节。

dict 详解:大模型消息格式就是它。 dict 是键值对集合,键像"抽屉的标签",值像"抽屉里的东西":

msg = {"role""user""content""你好"}msg["content"] = "帮我写周报"# 改值msg["name"] = "小明"# 新增键值对del msg["name"]                    # 删除键print(msg.get("role"))             # user,取不到返回 Noneprint(msg.get("age"0))           # 0,取不到返回默认值

遍历 dict 最常用 items(),一次拿到键和值:

for key, value in msg.items():    print(key, "=>", value)

dict 和 JSON 是一对双胞胎。 大模型的输入输出都是 JSON 字符串,而 JSON 在 Python 里就是 dict 和 list 的组合。模型返回 {"content": "你好"},解析出来就是一个 dict。这也是为什么 dict 必须学扎实——它是你和大模型对话的"通用语言"。

嵌套结构很常见。 一个 dict 的值可以是 list,list 里又可以套 dict,就像消息列表:

messages = [    {"role""system""content""你是一个乐于助人的助手"},    {"role""user""content""帮我写一份周报"}]print(messages[0]["role"])   # system,先取第 0 个,再取 role 键

这种 list 套 dict 的结构,你后面会天天见到。取值的口诀是"一层层剥洋葱":先 [下标] 再 ["键名"],按顺序剥到目标为止。

tuple 和 set 的适用场景。 tuple 不可变,适合放"不该被改"的数据,比如模型的 (温度, 最大长度) 配置;函数返回多个值时也常用 tuple 打包。set 自动去重,适合"判断元素在不在集合里"和"去掉重复项":

ids = ["a""b""a""c"]unique = set(ids)          # {'a', 'b', 'c'},自动去重print("b"in unique)       # True,成员判断极快

f-string:拼 prompt 的最优雅姿势。 前面说过字符串是拼 prompt 的主力,而 f-string 是 Python 3.6 之后最优雅的拼接方式:在字符串前加一个 f,用花括号嵌入变量:

assistant_name = "智能客服"version = "2.0"prompt = f"你是{assistant_name},当前版本{version},请用简洁专业的语气回答用户问题。"print(prompt)

输出:你是智能客服,当前版本2.0,请用简洁专业的语气回答用户问题。

在 Agent 开发里,你经常要动态拼 system prompt——把角色设定、用户输入、上下文组合成一段完整指令,f-string 就是你的主力工具。记住这个写法,后面天天用。

新手常见坑:f-string 里的花括号是插值用的,如果提示词里本身想写花括号(比如 JSON 模板),要写成 {{ 和 }} 转义。另外 dict 用 [] 取值时键不存在会直接报 KeyError 崩溃,所以不确定键是否存在时,优先用 .get()。

03 控制流:让代码学会"判断"和"重复"

光有数据还不够,代码需要逻辑。控制流就是给代码装"大脑"——会判断,会循环。

先认识比较运算符和逻辑运算符。 比较运算符有 ==(等于)、!=(不等于)、>、<、>=、<=,它们产出的都是布尔值。逻辑运算符有三个:and(并且)、or(或者)、not(取反)。

code = 200if code == 200and code != 429:    print("请求成功")if code == 200or code == 201:    print("成功类状态码")ifnot code == 429:    print("没有触发限流")

在 Agent 里,你经常要判断"API 返回状态码":200 代表成功,429 代表限流,500 代表服务器错误。用 if 分支分别处理,就是最典型的实战场景。

条件判断用 if/elif/else,语法接近自然语言:

user_input = input("你今天心情好吗?请输入 好 或 不好:")if user_input == "好":    print("太好了,保持好心情!")elif user_input == "不好":    print("没关系,写点代码放松一下。")else:    print("我没听懂,请重新输入。")

注意两点:条件后面要有冒号;代码块靠缩进(通常 4 个空格)区分层级。Python 用缩进代替了其他语言的花括号,这也是它读起来清爽的原因。

新手常见坑:缩进是新手第一周最大的报错来源。混用 Tab 和空格、缩进层级不一致,都会报 IndentationError。建议统一用 4 个空格,VS Code 默认就是,别手动敲 Tab。

if 的实战场景:判断用户输入、判断 API 返回状态码。 比如一个简单的"意图路由"——根据用户输入决定调用哪个工具:

user_input = "帮我查一下明天北京的天气"if"天气"in user_input:    tool = "weather"elif"翻译"in user_input:    tool = "translate"else:    tool = "chat"print(f"路由到工具:{tool}")

这就是 Agent 里"意图识别"的最朴素版本:关键词命中就分派到对应工具。真实产品会用大模型做意图分类,但"先判断再执行"的思路一模一样。注意 in 这个运算符:判断一个字符串是否包含另一个字符串,返回布尔值,写起来非常自然。

状态码判断的完整写法。 大模型和各类 API 都会返回状态码,200 表示成功,429 表示限流,500 表示服务器错误。你需要在代码里根据状态码决定下一步动作:

status = 429if status == 200:    print("正常处理返回结果")elif status == 429:    print("触发限流,请等待后重试")elif status >= 500:    print("服务器错误,稍后再试")else:    print(f"未知状态码:{status}")

这种"状态码 → 对应处理"的分支逻辑,几乎每个调用外部服务的函数里都有。注意 elif 是"else if"的缩写,可以连续写多个,从上到下依次判断,命中一个就停止。

循环有两种:for 循环用来遍历集合,while 循环在条件成立时反复执行。

for 循环 + range():遍历是 Agent 的高频操作。 range() 可以生成一串数字:

for i in range(3):          # 0, 1, 2    print(f"第 {i + 1} 次尝试")for i in range(1102):   # 从 1 到 9,步长 2    print(i)                # 1 3 5 7 9

range(n) 生成 0 到 n-1,range(起点, 终点, 步长) 可以定制。配合列表遍历,比如逐个加载工具列表:

tools = ["搜索""计算器""天气查询""翻译"]for tool in tools:    print(f"正在加载工具:{tool}")

break 和 continue 是对循环的"遥控器"。 break 立刻跳出整个循环,continue 跳过本次、进入下一次:

for i in range(10):if i == 3:continue# 跳过 3,不打印if i == 7:break# 到 7 就停    print(i)              # 输出 0 1 2 4 5 6

实战里,break 常用于"找到第一个符合条件的就收手",continue 常用于"跳过无效数据"。比如遍历消息列表,跳过 role 为 system 的,遇到第一条 user 消息就处理。

while 循环:常用于"轮询任务状态"。 很多模型平台支持异步任务:你提交一个任务,拿到一个 task_id,然后反复查询它的状态,直到变成"完成"。这就是 while 的典型战场:

status = "pending"attempt = 0while status notin ("completed""failed"and attempt < 5:    print(f"第 {attempt + 1} 次查询任务状态:{status}")# 真实项目里这里会调用查询 API    status = "completed"# 模拟:任务完成了    attempt += 1print("最终状态:", status)

注意 attempt += 1 不能漏,否则条件永远成立,程序会陷入死循环。这是新手最容易踩的坑。另一个技巧是给 while 加"次数上限",防止无限轮询——真实项目里还会配合超时时间一起用。

列表推导式:一行代码完成"遍历 + 筛选 + 生成新列表"。

tools = ["搜索""计算器""天气查询""翻译"]available = [t for t in tools if"查询"notin t]print(available)  # ['搜索', '计算器', '翻译']

这段代码读起来像英语:"for t in tools if not 查询"——把符合条件的 t 收集成新列表。带 if 条件是最常见用法;嵌套推导式可以对二维数据做处理,比如把消息列表里的 content 全取出来:

messages = [    {"role""user""content""你好"},    {"role""assistant""content""你好!有什么可以帮你?"}]contents = [m["content"for m in messages]print(contents)   # ['你好', '你好!有什么可以帮你?']

字典推导式: 类似的语法可以快速生成 dict:

scores = {"搜索"3"计算器"2}double = {k: v * 2for k, v in scores.items()}print(double)   # {'搜索': 6, '计算器': 4}

在 Agent 里,列表推导式常用于"从工具清单里筛选可用工具""过滤无效消息""批量提取字段"这类场景。写多了你会发现,它能让你代码短一半,逻辑还一目了然。

04 函数:把代码打包成"工具"

函数是把一段逻辑打包起来、起个名字、随时调用的机制。写 Agent 代码时,你会把"处理输入""调用模型""解析结果"分别写成函数,就像搭积木。

定义函数用 def 关键字:

defgreet(name):returnf"你好,{name}!"print(greet("小红"))  # 你好,小红!

参数有四种玩法。 位置参数按顺序传;默认参数给参数一个兜底值,调用时不传就用默认值;关键字参数让你按名字传参,不用记顺序:

defbuild_messages(user_input, system_prompt="你是一个乐于助人的助手", max_len=500):if len(user_input) > max_len:        user_input = user_input[:max_len] + "..."return [        {"role""system""content": system_prompt},        {"role""user""content": user_input}    ]# 只传必填参数msgs = build_messages("帮我写一份周报")# 用关键字参数覆盖默认值msgs = build_messages("帮我写一份周报", system_prompt="你是一个资深职场顾问")

这个函数就是"调用大模型前的参数处理":截断超长输入、组装成标准消息格式。默认参数让调用方可以少写很多重复配置,这也是框架代码里最常见的参数设计。

新手常见坑:默认参数不要用可变对象(比如 [] 或 {})。Python 只在定义函数时创建一次默认值,多次调用会共享同一个列表,改一处全变。想用"空列表"做默认值,写成 None,函数内部再判断。

*args 和 **kwargs: 用来接收"不定数量的参数"。*args 把多余的按位置传的参数打包成元组,**kwargs 把多余的关键字参数打包成 dict。在框架源码里很常见,比如日志函数、事件回调:

deflog_event(event, **kwargs):    print(f"事件:{event},附加信息:{kwargs}")log_event("api_call", model="gpt-4o", cost=0.01)# 事件:api_call,附加信息:{'model': 'gpt-4o', 'cost': 0.01}

返回值: return 把结果交还给调用方。没有 return 的函数返回 None。一个函数可以返回多个值,Python 会打包成元组:

defanalyze(text):return len(text), text.upper()   # 返回两个值length, upper_text = analyze("hello")print(length, upper_text)   # 5 HELLO

变量作用域: 函数里定义的变量是"局部"的,外面看不到;函数外定义的叫"全局"变量,函数内可以读,但想修改要加 global 声明。新手阶段记住一句话:尽量用参数传数据、用 return 拿结果,少动全局变量,代码会干净很多。

count = 0# 全局变量defincrement():global count              # 声明要修改全局变量    count += 1increment()print(count)                  # 1

不过在实际的 Agent 项目里,你很少会用 global,因为"共享状态"这件事,类和对象已经帮你解决得更好(下一节就讲)。这里只要理解"函数内部的变量是封闭的"这个原则,避免写出"在函数里改全局变量导致到处出问题"的 bug 就行。判断一个变量是局部还是全局,就看它有没有在函数里被赋值——没赋值的就是从外面读的。

lambda 详解: 匿名函数,不需要名字,常用于配置里传简短的逻辑。语法是 lambda 参数: 表达式:

add = lambda x, y: x + yprint(add(12))   # 3

lambda 在框架配置中很常见,看到 lambda x: 表达式 这种写法,理解成"一个小型无名函数"即可,不用怕。它适合"一句话能写完"的逻辑,逻辑复杂了就该用 def 定义有名函数。

高阶函数:map、filter、sorted 的 key。 高阶函数就是"接收函数作为参数的函数"。map 对每个元素做变换,filter 按条件筛选,sorted 配合 key 自定义排序规则:

nums = [1234]print(list(map(lambda x: x * 2, nums)))       # [2, 4, 6, 8]print(list(filter(lambda x: x > 2, nums)))    # [3, 4]tools = ["搜索""计算器""天气查询"]sorted_tools = sorted(tools, key=lambda t: len(t))print(sorted_tools)   # ['搜索', '计算器', '天气查询']

注意 map 和 filter 的结果要包一层 list() 才能打印出列表,这是 Python 的"惰性求值"特性,先混个眼熟。sorted 的 key 参数尤其实用:按长度、按价格、按优先级排序,一行搞定。

实战:用函数组装 Agent 的调用流程。 真实 Agent 里,一次对话要经历"处理输入 → 组装消息 → 调用模型 → 解析结果"好几个环节。把它们拆成独立函数,每个函数只干一件事,代码就像流水线一样清晰:

defbuild_messages(user_input, system_prompt="你是一个乐于助人的助手"):return [        {"role""system""content": system_prompt},        {"role""user""content": user_input},    ]defcall_model(messages):# 真实项目里这里是 openai 调用return'{"choices": [{"message": {"content": "你好!"}}]}'defparse_content(raw):import jsonreturn json.loads(raw)["choices"][0]["message"]["content"]msgs = build_messages("帮我写一份周报")raw = call_model(msgs)print(parse_content(raw))   # 你好!

函数化的好处是:同一段逻辑只写一次,换个参数就能复用,改一处全局生效。你在看 LangGraph 或 OpenAI SDK 的示例代码时,会反复见到这种"处理 + 组装"的函数——几乎每个真实 Agent 都有这么几个"处理函数",先把这种组织代码的感觉建立起来。

05 类与对象:给代码"造物主"视角

函数打包的是逻辑,类打包的是"数据 + 逻辑"。类可以理解成一张设计图纸,对象是按照图纸造出来的具体产品。

先看一个最典型的例子:封装一个 LLMClient 类。

classLLMClient:def__init__(self, api_key, model="gpt-4o-mini"):        self.api_key = api_key        self.model = modeldefchat(self, messages):# 真实项目里,这里会调用大模型 APIreturnf"[{self.model}] 收到 {len(messages)} 条消息"client = LLMClient(api_key="sk-xxxx", model="gpt-4o-mini")result = client.chat([{"role""user""content""你好"}])print(result)  # [gpt-4o-mini] 收到 1 条消息

拆解一下:__init__ 是构造函数,创建对象时自动执行,用来初始化数据;self 代表"这个对象自己",类里的每个方法第一个参数都是它,通过它可以访问对象的属性(如 self.api_key)和其他方法。

类属性与实例属性: 写在 init 里、以 self. 开头的叫实例属性,每个对象各有一份;直接写在类体里的叫类属性,所有对象共享一份。比如 API 的基础地址适合放类属性,api_key 适合放实例属性。

实例方法: 第一个参数是 self 的方法,通过对象调用,能访问对象的数据。这是类里最常见的成员。后面你还会遇到 @staticmethod(静态方法,不依赖对象数据)和 @classmethod(类方法),先混个眼熟,用到再查。

继承:子类复用父类。 你可以写一个"基础客户端",再派生出"带记忆的客户端""带工具的客户端",子类自动拥有父类的全部能力,还能改写:

classBaseClient:def__init__(self, api_key):        self.api_key = api_keydefchat(self, messages):returnf"调用模型,收到 {len(messages)} 条消息"classMemoryClient(BaseClient):def__init__(self, api_key, memory_size=10):        super().__init__(api_key)          # 调用父类构造函数        self.memory_size = memory_sizedefchat(self, messages):        result = super().chat(messages)    # 复用父类逻辑return result + f",记忆容量 {self.memory_size}"client = MemoryClient("sk-xxx")print(client.chat([{"role""user""content""hi"}]))# 调用模型,收到 1 条消息,记忆容量 10

super() 就是"父类"的引用,子类想调用父类的方法就靠它。继承的价值在于"复用":公共能力写在父类,特殊能力在子类里叠加,代码不会越写越臃肿。

魔术方法:str 和 repr 名字前后带双下划线的方法,Python 会在特定时机自动调用。str 定义"打印这个对象时显示什么":

classTool:def__init__(self, name, enabled=True):        self.name = name        self.enabled = enableddef__str__(self):returnf"工具({self.name}, 启用={self.enabled})"t = Tool("搜索")print(t)   # 工具(搜索, 启用=True),而不是一串看不懂的内存地址

没有 str 时打印对象,你会看到 <__main__.Tool object at 0x...> 这种地址,毫无信息量。定义 str 后,调试日志瞬间变得可读。repr 类似,主要给开发者调试用,先记住 str 就够。

实战:完整版 LLMClient(含重试、日志)。 把前面学的都揉进去:

import timeclassLLMClient:def__init__(self, api_key, model="gpt-4o-mini", max_retries=3):        self.api_key = api_key        self.model = model        self.max_retries = max_retries        self.call_count = 0# 记录调用次数defchat(self, messages):for attempt in range(self.max_retries):try:# 真实项目里这里是 requests.post 或 openai 调用                self.call_count += 1                print(f"[日志] 第 {attempt + 1} 次调用 {self.model}")returnf"[{self.model}] 回复:收到 {len(messages)} 条消息"except Exception as e:                print(f"[日志] 调用失败:{e},准备重试")                time.sleep(1)        # 退避一下再试return"调用多次失败,请稍后再试"client = LLMClient(api_key="sk-xxx")print(client.chat([{"role""user""content""你好"}]))print(f"累计调用次数:{client.call_count}")

为什么 Agent 开发中要用类? 因为一个完整的 LLM 客户端需要封装很多东西:API 密钥、模型名、请求重试、日志记录、成本统计。用类把这些状态和行为绑定在一起,调用方只需要 client.chat(...),不用关心内部细节。这就是"封装"的价值——这也是你在看 LangChain、LangGraph 源码时,会看到大量类的根本原因。

你可能想问:这些用函数也能实现,为什么非要类?区别在于"状态"。函数是"用完即走"的,而类可以长期持有状态——比如 client 记住你的 api_key 和 model,你每次调用都不用重新传。一个 Agent 项目里,模型客户端、工具管理器、记忆存储,几乎都是这样用类封装的。理解了这一点,你读框架源码时就不会再发怵。

06 异常处理:让程序"摔倒了能爬起来"

调用外部 API 时,有一件事你迟早会遇到:报错。网络抖动、接口限流、参数不合法,任何一个环节出错,程序都可能当场崩溃。

先认识常见的异常类型。 Python 内置了各种异常,各管一摊:

异常类型
什么时候出现
ValueError
值不合法,比如 int("abc")
TypeError
类型用错,比如字符串 + 数字
KeyError
dict 里键不存在
ConnectionError
网络连接失败
TimeoutError
请求超时

看到报错信息末尾的异常类型名,你就能猜个大概,这是排查问题的第一步。

try/except/else/finally 完整结构。 除了 try 和 except,还有两个可选块:

try:    num = int("abc")          # 故意制造错误except ValueError as e:    print(f"转换失败:{e}")    # 出错时执行else:    print("没有出错才执行这里")finally:    print("无论是否出错,都执行这里")

else 块在 try 没出错时执行,finally 块无论如何都会执行——比如"无论成败都要关闭连接、释放资源"。

捕获多个异常: 可以写多个 except 分支,分别处理;也可以把多个异常类型放进一个元组:

try:    result = 10 / 0except (ValueError, TypeError):    print("参数类错误")except ZeroDivisionError as e:    print(f"除零错误:{e}")except Exception as e:      # 兜底,捕获所有其他异常    print(f"未知错误:{e}")

自定义异常: 当内置异常不够表达业务语义时,可以自己定义。比如"余额不足""超过调用限额":

classQuotaExceededError(Exception):passdefcall_model():raise QuotaExceededError("本月调用额度已用完")try:    call_model()except QuotaExceededError as e:    print(f"业务错误:{e},请充值或等额度重置")

实战:带重试机制的 API 调用函数。 大模型 API 经常限流(429)、超时(TimeoutError),一个健壮的函数应该自动重试:

import timedefcall_api_with_retry(url, max_retries=3, delay=1):for attempt in range(max_retries):try:# 真实项目里这里是 requests.get 或 openai 调用if url == "":raise ValueError("URL 不能为空")if attempt == 0:raise ConnectionError("模拟网络抖动")return"请求成功"except (ConnectionError, TimeoutError) as e:            print(f"第 {attempt + 1} 次失败:{e}{delay} 秒后重试")            time.sleep(delay)except ValueError as e:            print(f"参数错误,不重试:{e}")returnNonereturn"重试多次仍失败"print(call_api_with_retry("https://api.example.com"))

注意这里的技巧:ValueError 属于"改了也白改"的参数错误,直接返回不重试;ConnectionError 属于"过会儿可能就好了"的临时错误,值得重试。区分这两类,是写健壮代码的关键。

在 Agent 实战中,异常处理是必修课。 大模型 API 经常限流、超时,一个健壮的 Agent 必须能捕获这些异常并给出降级方案——重试一次、换备用模型、告诉用户稍后再试。可以这么说:没有异常处理的 Agent,上线第一天就会崩给你看。

07 异步编程基础:让代码"同时干几件事"

最后一个概念,也是很多新手最容易懵的地方:异步编程。先用一个比喻讲清楚为什么需要它。

假设你的 Agent 要同时调用三个 API:查天气、查新闻、算数据。如果一个个来,每个耗时 1 秒,总共要 3 秒;如果能同时发起三个请求,总耗时还是 1 秒左右。异步编程,就是让代码具备这种"同时开工"的能力。

打个比方:同步代码像排队打饭,一个窗口一个人,前面的打完才轮到你;异步代码像自助餐厅,多个窗口同时出餐,你手里同时排着好几份。对 Agent 来说,它要调用大模型、查工具、读文件,全是耗时操作,异步几乎是必备技能。

同步 vs 异步对比:

特性
同步
异步
执行方式
一个一个来
同时开工
3 个 1 秒请求
约 3 秒
约 1 秒
代码难度
简单
稍复杂
Agent 场景
单次调用
多工具并行

async/await 详解。 Python 里用 async/await 实现异步。async def 定义的是协程函数(可以理解为"可暂停的任务");await 表示"在这里等结果,但等待期间可以去干别的":

import asyncioasyncdeffetch_weather(city):await asyncio.sleep(1)   # 模拟网络请求耗时 1 秒returnf"{city}:晴,25℃"asyncdeffetch_news():await asyncio.sleep(1)return"今日要闻:AI 技术正在改变软件开发"asyncdefmain():    results = await asyncio.gather(fetch_weather("北京"), fetch_news())    print(results)asyncio.run(main())

gather 与 create_task。 asyncio.gather 把多个协程打包并发执行,等全部完成返回结果列表,是最常用的写法。create_task 则把协程"挂到后台"运行,适合"发出去就不管,稍后再收结果"的场景:

asyncdefmain():    task = asyncio.create_task(fetch_weather("上海"))   # 后台启动# 这里可以干别的活    result = await task                                 # 需要时再等结果    print(result)

实战:并发调用多个 API。 假设 Agent 一次任务要查三个城市天气,同步要 3 秒,异步只要 1 秒:

import asyncioasyncdeffetch_weather(city):await asyncio.sleep(1)          # 模拟网络请求returnf"{city}:晴"asyncdefmain():    cities = ["北京""上海""广州"]    results = await asyncio.gather(        *[fetch_weather(c) for c in cities]   # * 把列表展开成多个参数    )for r in results:        print(r)asyncio.run(main())# 北京:晴# 上海:晴# 广州:晴

注意 *[fetch_weather(c) for c in cities] 里的星号:它把列表"拆开"成一个个独立参数传给 gather,这是 Python 里很常用的解包技巧,配合列表推导式使用,代码非常简洁。

什么时候该用异步? 三条判断标准:一是有多个独立的耗时操作要并发;二是这些操作之间没有先后依赖;三是操作主要是"等网络"而不是"算 CPU"。满足这三条,就用异步。如果只是单次调用、或者操作之间有强依赖,同步就够了,别为了异步而异步。

本篇你只需要建立这个认知:看到 async/await 知道是在做并发,能读懂示例即可。等你在真实项目里用上几次,自然就越写越顺了。

08 模块与导入:站在巨人的肩膀上

Python 之所以强大,一半功劳要归给"别人写好的代码"——模块。模块就是别人打包好的功能,导入进来就能用,不用自己从零写。

import 的三种写法。 最常用的是 import 模块名,然后模块名.函数名 调用:

import jsondata = json.loads('{"content": "你好"}')print(data["content"])   # 你好

from 模块 import 名字 可以直接导入某个函数,调用时不用带模块名:

from datetime import datetimenow = datetime.now()print(now)               # 2026-08-16 12:00:00 之类

as 是起别名,名字太长或容易撞车时用:

import json as jprint(j.loads('{"a": 1}'))   # {'a': 1}

常用标准库:json、os、datetime。 标准库是 Python 自带的,不用安装。json 负责 JSON 和 dict 互转;os 负责和操作系统打交道(读环境变量、拼文件路径);datetime 处理时间:

import osimport jsonfrom datetime import datetime# 读环境变量里的 API 密钥(比硬编码安全)api_key = os.getenv("OPENAI_API_KEY""未设置")print(api_key)# 给消息加时间戳now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")print(f"[{now_str}] 收到用户消息")

pip 安装第三方库。 标准库之外还有海量第三方库,用 pip 安装:

pip install requestspip install openai

装完就能 import 使用。requests 是 HTTP 请求神器,openai 是官方 SDK。注意:装库前建议先建一个虚拟环境,把不同项目的依赖隔离开,避免版本冲突。这一步新手常忽略,等踩坑了再回来补。

python -m venv venv          # 创建虚拟环境source venv/bin/activate     # Mac/Linux 激活(Windows 用 venv\Scripts\activate)pip install requests openai  # 在虚拟环境里装库

虚拟环境可以理解成"每个项目一个独立的行李箱":A 项目装 requests 2.31,B 项目装 requests 2.28,互不干扰。没有它,两个项目一升级依赖,就可能互相把对方搞崩。等你开始做真实项目,几乎每个都会建一个虚拟环境,现在先建立这个习惯。

os 模块还有一个高频用法:拼接文件路径。 不同操作系统的路径分隔符不一样(Windows 是反斜杠,Mac/Linux 是正斜杠),用 os.path.join 可以自动适配,避免"代码在 Mac 能跑、到 Windows 就报错"的尴尬:

import osconfig_path = os.path.join("config""agent.yaml")print(config_path)   # Mac 输出 config/agent.yaml

实战:用 json 模块解析大模型返回结果。 大模型 API 返回的是一段 JSON 字符串,解析是每天的常规操作:

import json# 模拟大模型返回的原始 JSON 字符串raw_response = '{"choices": [{"message": {"role": "assistant", "content": "你好,我是智能助手"}}]}'data = json.loads(raw_response)                     # 字符串 -> dictcontent = data["choices"][0]["message"]["content"]  # 层层取print(content)   # 你好,我是智能助手# 反向操作:把 dict 转成 JSON 字符串(发给 API 时用)payload = {"model""gpt-4o-mini""messages": [{"role""user""content""hi"}]}print(json.dumps(payload, ensure_ascii=False))      # 中文不转义,方便阅读

json.loads 是"字符串变 dict",json.dumps 是"dict 变字符串",这一进一出,就是你和模型 API 之间的"翻译官"。ensure_ascii=False 保证中文原样输出,不然会变成 \uXXXX 的转义符。

新手常见坑:json.loads 遇到格式不对的字符串会抛 JSONDecodeError。解析前最好先确认字符串是完整合法的 JSON,或者用 try/except 包一层。

09 实战综合案例:写一个"简易智能客服 Agent"

前面学的都是零件,现在把它们组装起来。下面这个"简易智能客服",把变量、列表、字典、循环、推导式、函数、类、异常处理、异步全部用上。先整体看一遍,再逐行讲解。

import asyncioimport jsonimport timeclassLLMClient:"""模拟大模型客户端"""def__init__(self, api_key, model="gpt-4o-mini", max_retries=2):        self.api_key = api_key        self.model = model        self.max_retries = max_retriesdefchat(self, messages):for attempt in range(self.max_retries):try:# 真实项目里这里是 openai 调用                user_msg = messages[-1]["content"]returnf"我是{self.model},已收到你的问题:{user_msg}"except Exception as e:                print(f"调用失败:{e},重试中...")                time.sleep(0.5)raise ConnectionError("多次调用失败")defbuild_messages(user_input, system_prompt="你是智能客服小助手"):return [        {"role""system""content": system_prompt},        {"role""user""content": user_input},    ]defparse_response(raw):"""解析模型返回的 JSON"""    data = json.loads(raw)return data["choices"][0]["message"]["content"]defroute_intent(user_input, keywords):"""根据关键词路由到对应回复模板"""for intent, words in keywords.items():if any(w in user_input for w in words):return intentreturn"chat"asyncdeffetch_order_status(order_id):"""模拟异步查询订单状态"""await asyncio.sleep(0.5)returnf"订单 {order_id} 已发货,预计明天送达"asyncdefmain():    client = LLMClient(api_key="sk-xxx")    keywords = {"order": ["订单""物流""快递"],"refund": ["退款""退货"],    }whileTrue:        user_input = input("请问有什么可以帮您?(输入 quit 退出)")if user_input == "quit":            print("感谢使用,再见!")break        intent = route_intent(user_input, keywords)        print(f"[路由] 识别意图:{intent}")if intent == "order":# 并发查询多个订单            results = await asyncio.gather(                fetch_order_status("A001"), fetch_order_status("A002")            )for r in results:                print(r)else:            messages = build_messages(user_input)            raw = client.chat(messages)            print(f"[模型] {raw}")asyncio.run(main())

逐行讲解:

  1. 顶部 import 三行:asyncio 做并发、json 解析返回、time 做重试退避。
  2. LLMClient 类:init 保存密钥、模型名、重试次数;chat 方法内部用 for 循环做重试,try/except 捕获异常,全部失败后 raise 抛出 ConnectionError——异常处理学以致用。
  3. build_messages 函数:复用默认参数,拼出标准的 system + user 消息列表。
  4. parse_response 函数:json.loads 把字符串变 dict,再层层取到 content。这里定义了但主流程里没直接调用,留给你当练习——把 client.chat 改成返回 JSON 字符串再调用它。
  5. route_intent 函数:用推导式 any(w in user_input for w in words) 判断用户输入是否命中关键词,命中就返回对应意图。这就是最朴素的"意图路由"。
  6. fetch_order_status 协程:async def + await asyncio.sleep 模拟网络耗时。
  7. main 函数:while True 让客服"一直在线",quit 用 break 退出;根据意图分流——订单类走异步并发查询,其他走模型对话。
  8. asyncio.run(main()) 启动整个程序。

运行这个程序,你会看到一次完整的"输入 → 路由 → 并发查询/模型回复"流程。虽然离生产级 Agent 还很远,但它把本篇所有知识点串成了一条线:你现在看到的每一个零件,将来在 LangGraph、OpenAI SDK 的代码里都会以更复杂的形式再次出现。

动手挑战:试着给这个客服加上"退款"分支的异步处理,或者把 LLMClient 的返回改成 JSON 字符串,再用 parse_response 解析。改通的那一刻,你就真的入门了。

10 小结:你已经迈过了最难的坎

回顾一下,这一篇你掌握了:

  • 环境搭建:Python 3.10+、VS Code、交互式终端、注释
  • 变量与数据类型:int、float、str、bool,以及 list、dict、tuple、set
  • 字符串与 f-string:索引、切片、常用方法,拼 prompt 的核心技能
  • 控制流:if/elif/else、for/while、break/continue、推导式
  • 函数:def、默认参数、关键字参数、*args/**kwargs、lambda、高阶函数
  • 类与对象:class、init、self、继承、魔术方法、封装
  • 异常处理:常见异常、try/except/else/finally、重试机制
  • 异步基础:async/await、gather/create_task、并发调用
  • 模块与导入:import 三种写法、标准库、pip、json 解析
  • 综合实战:简易智能客服,全部知识点串成一条线

这些就是 Agent 开发中出镜率最高的 Python 语法。但"看懂"和"会写"之间,隔着一个关键动作:动手敲。

给你留四个练习,建议在交互环境或新建的 .py 文件里完成:

  1. 写一个函数 format_user_input,接收用户输入,用 f-string 拼出一段完整的 system prompt + user prompt 并返回。
  2. 用列表推导式,从一个工具列表中过滤出"名称包含'查询'且长度大于 2"的工具。
  3. 写一个带 try/except 的函数,模拟调用 API:传入一个 URL,如果 URL 为空则抛出并捕获异常,返回友好的错误提示。
  4. 把综合案例里的 LLMClient.chat 改成返回 JSON 字符串,用 parse_response 解析出 content。

四个练习做完,你对本篇内容的掌握程度会比只读一遍高出一大截。编程是"手上功夫",不是"眼上功夫"——看懂不算会,敲出来才算。这些语法已经足够你动手写出第一个 Agent 脚本了。

今天你写了几个练习?评论区打卡,卡在哪一步我们一起解决,关注我们,一起搞定 AI Agent 开发。


参考来源

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-22 01:57:07 HTTP/2.0 GET : https://f.mffb.com.cn/a/511705.html
  2. 运行时间 : 0.101615s [ 吞吐率:9.84req/s ] 内存消耗:4,723.06kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=7ffcf79ca3cf6ff57b69cf812789f9df
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000556s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000813s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000337s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000277s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000488s ]
  6. SELECT * FROM `set` [ RunTime:0.000247s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000596s ]
  8. SELECT * FROM `article` WHERE `id` = 511705 LIMIT 1 [ RunTime:0.017842s ]
  9. UPDATE `article` SET `lasttime` = 1787335027 WHERE `id` = 511705 [ RunTime:0.001196s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000259s ]
  11. SELECT * FROM `article` WHERE `id` < 511705 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.003291s ]
  12. SELECT * FROM `article` WHERE `id` > 511705 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000508s ]
  13. SELECT * FROM `article` WHERE `id` < 511705 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002431s ]
  14. SELECT * FROM `article` WHERE `id` < 511705 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004858s ]
  15. SELECT * FROM `article` WHERE `id` < 511705 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000767s ]
0.103075s