Skip to content

第3章 写Agent之前,这些Python够用了

第2章装好了环境,这一章快速过一遍Python——不是从头教,是挑Agent开发里真正常用到的部分。如果你Python已经熟了,可以扫一遍直接跳到第4章。如果有些生疏,跟着过一遍,后面写Agent代码的时候不会卡在基础语法上。


3.1 Agent的工作台

3.1.1 用得最多的三种数据

写Agent的时候,你会频繁跟三种数据结构打交道。

列表:Agent拿到一堆工具返回的结果,用列表装着最方便。

python
# Agent调用了三个搜索工具,结果放在一起
search_results = [
    "北京今天晴,20-28℃",
    "北京明天多云,18-25℃", 
    "北京后天有雨,15-22℃"
]

# Agent需要从中挑出"有雨"的那条
rain_days = [r for r in search_results if "雨" in r]
print(rain_days)  # ['北京后天有雨,15-22℃']

字典:Agent跟外部API打交道,JSON来回全是字典。

python
# 工具返回的天气数据(JSON转成的字典)
weather = {
    "city": "北京",
    "temperature": 25,
    "humidity": 60,
    "forecast": ["晴", "多云", "有雨"]
}

# Agent提取需要的信息
if weather["temperature"] > 30:
    print(f"{weather['city']}今天很热")
else:
    print(f"{weather['city']}今天温度还行")

集合:Agent需要"去重"的时候用。比如一个Agent问了三个不同的人同一个问题,得到了一些重复的回答,用集合快速去重。

python
# 三个Agent返回的推荐方案,有重复
plan_a = {"改签", "退款", "补偿"}
plan_b = {"改签", "升级舱位", "补偿"}  
plan_c = {"退款", "补偿", "优惠券"}

# 合并所有方案,自动去重
all_plans = plan_a | plan_b | plan_c
print(all_plans)  # {'改签', '退款', '补偿', '升级舱位', '优惠券'}

3.1.2 推导式:少写for循环的秘密

Agent代码里经常需要"把A处理成B",用推导式一行搞定。

python
# 不用推导式:三行
tools = ["search", "calculator", "weather"]
upper_tools = []
for t in tools:
    upper_tools.append(t.upper())

# 用推导式:一行  
upper_tools = [t.upper() for t in tools]

字典推导式更常用——Agent经常需要把一种格式的字典转成另一种:

python
# API返回的工具配置
tool_configs = {
    "search": {"enabled": True, "timeout": 10},
    "calculator": {"enabled": False, "timeout": 5},
    "weather": {"enabled": True, "timeout": 8}
}

# 只要启用的工具
active_tools = {k: v for k, v in tool_configs.items() if v["enabled"]}
# {'search': {'enabled': True, 'timeout': 10}, 'weather': {'enabled': True, 'timeout': 8}}


3.2 写Agent代码的好帮手

3.2.1 lambda:临时小函数

Agent开发中经常需要传一个小函数作为参数,但专门写个 def 又太重了。这时候用 lambda

python
# 场景:Agent拿到了一批工具的评分,需要按分数排序
tools = [
    {"name": "search", "score": 4.5},
    {"name": "calculator", "score": 3.2},
    {"name": "weather", "score": 4.8}
]

# lambda 一行搞定按score排序
tools.sort(key=lambda t: t["score"], reverse=True)
print([t["name"] for t in tools])  # ['weather', 'search', 'calculator']

3.2.2 map 和 filter:批量处理利器

这两个函数在LangChain的源码里出现频率很高,值得了解一下。

python
# Agent拿到了一堆用户消息,需要全部转成小写再处理
messages = ["Hello World", "HOW ARE YOU", "Fine Thank You"]
lowered = list(map(str.lower, messages))
# ['hello world', 'how are you', 'fine thank you']

# 过滤掉空消息
raw = ["你好", "", "帮我查天气", "", "谢谢"]
valid = list(filter(None, raw))
# ['你好', '帮我查天气', '谢谢']

3.2.3 解包:让参数传递更灵活

Agent框架里经常看到 *args**kwargs,其实就是"我不管你给我多少个参数,我都能处理"。

python
# 场景:Agent的工具调用函数,不知道每次会传几个参数
def call_tool(tool_name, *args, **kwargs):
    """通用工具调用函数"""
    print(f"调用工具: {tool_name}")
    print(f"位置参数: {args}")
    print(f"关键字参数: {kwargs}")

# 不同工具传不同的参数
call_tool("search", "北京天气")
# 调用工具: search
# 位置参数: ('北京天气',)
# 关键字参数: {}

call_tool("weather", city="北京", date="明天")
# 调用工具: weather
# 位置参数: ()
# 关键字参数: {'city': '北京', 'date': '明天'}

3.3 让代码更优雅

3.3.1 装饰器:给函数加个"壳"

Agent开发中最常见的装饰器场景:记录每个工具调用的耗时。

python
import time

def log_time(func):
    """记录函数执行时间的装饰器"""
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        cost = time.time() - start
        print(f"工具 {func.__name__} 执行耗时: {cost:.2f}秒")
        return result
    return wrapper

@log_time
def search_weather(city):
    time.sleep(1.2)  # 模拟API调用
    return f"{city}今天晴"

@log_time  
def search_news(topic):
    time.sleep(0.8)
    return f"关于{topic}的最新消息..."

# 两个函数自动带上了计时功能
print(search_weather("北京"))
# 工具 search_weather 执行耗时: 1.20秒
# 北京今天晴

3.3.2 上下文管理器:自动"进门"和"出门"

Agent需要连数据库、开文件、调API——这些操作都有"打开"和"关闭"两步。上下文管理器帮你自动关,不用手动 close()

python
# 不用上下文管理器:容易忘关
f = open("agent_log.txt", "w")
f.write("Agent started\n")
# ... 写了一堆代码,中间可能报错
f.close()  # 如果中间报错了,这行根本执行不到

# 用上下文管理器:自动关,绝不出错
with open("agent_log.txt", "w") as f:
    f.write("Agent started\n")
    # 不管中间报不报错,退出 with 块自动关闭

你自己写Agent工具时也会用到:

python
from contextlib import contextmanager

@contextmanager
def tool_session(tool_name):
    """模拟工具调用的会话管理"""
    print(f"[{tool_name}] 初始化连接...")
    yield  # 这里执行工具的具体逻辑
    print(f"[{tool_name}] 关闭连接,释放资源")

# 使用
with tool_session("weather_api"):
    print("正在查询天气...")
# 输出:
# [weather_api] 初始化连接...
# 正在查询天气...
# [weather_api] 关闭连接,释放资源

3.4 让Agent同时做多件事

Agent经常需要"同时"调好几个工具——比如查天气的同时查新闻、查股价。如果串行执行,用户得等很久。

3.4.1 什么时候用 asyncio

asyncio 适合"IO密集型"任务——大部分时间在等网络返回,Python可以趁等待的时间去干别的事。

python
import asyncio

async def call_api(tool_name, delay):
    """模拟调用外部API"""
    print(f"开始调用 {tool_name}...")
    await asyncio.sleep(delay)  # 模拟网络等待
    print(f"{tool_name} 返回结果")
    return f"{tool_name} 的结果"

async def main():
    # 同时发起三个工具调用
    results = await asyncio.gather(
        call_api("天气查询", 1),
        call_api("新闻搜索", 0.8),
        call_api("股价查询", 0.5)
    )
    print(f"全部完成: {results}")

asyncio.run(main())
# 输出:三个调用几乎同时开始,总耗时≈1秒而不是1+0.8+0.5=2.3秒

3.4.2 什么时候不用

如果你的工具调用本身就是"串行"的(第二步依赖第一步的结果),那老老实实写同步代码就好。asyncio 不是魔法,它只在"等待IO时可以切走"这个场景有用。

python
# 这种场景不需要 asyncio
# 因为第二步依赖第一步的结果
result_1 = search_location("北京")
result_2 = search_weather(result_1["location_id"])  # 依赖result_1

3.5 Agent的眼睛和耳朵

3.5.1 文件读写:Agent记日志、读配置

Agent运行时会记日志、读配置文件、保存结果——文件操作是基本功。

python
import time
from pathlib import Path

# 写日志(追加模式)
log_file = Path("agent.log")
with open(log_file, "a") as f:
    f.write(f"[{time.strftime('%H:%M:%S')}] 用户提问:今天天气怎么样\n")

# 读配置文件
import json
with open("agent_config.json", "r") as f:
    config = json.load(f)
print(config["model"])  # 比如 "gpt-4"

3.5.2 网络请求:Agent调用外部API

Agent最核心的能力就是调用外部API。requests 库基本上每个Agent项目都会用到。

python
import requests

def search_weather(city):
    """调用天气API"""
    try:
        response = requests.get(
            "https://api.weather.com/v1/current",
            params={"city": city},
            timeout=5  # 5秒超时,别让Agent傻等
        )
        response.raise_for_status()  # 状态码不是200就抛异常
        return response.json()
    except requests.Timeout:
        return {"error": "天气服务超时,请稍后重试"}
    except requests.RequestException as e:
        return {"error": f"请求失败: {str(e)}"}

几个写Agent时容易踩的坑

  1. 永远加 timeout——不然Agent可能卡死在一个慢API上
  2. 永远处理异常——外部API随时可能挂,你的Agent不能跟着挂
  3. API Key 放 .env 文件,别硬编码——这个第2章讲过了

3.6 本章小结

这一章我们快速过了一遍Agent开发中最常用的Python知识:

  1. 数据结构:列表装结果、字典传数据、集合去重——Agent的日常工作台
  2. 函数式编程:lambda、map、filter、解包——让Agent代码更简洁
  3. 装饰器与上下文管理器:给工具加日志、自动管理资源——让代码更优雅
  4. asyncio并发:Agent同时调多个工具时,别让用户傻等
  5. 文件与网络:Agent读配置、记日志、调API的基本功

这些不是你还没学的Python基础——是你写Agent时真正常用到的部分。剩下的语法,遇到了查一下就行。


✅ 知识点检查

学完这一章,试试回答这几个问题:

  • [ ] 列表、字典、集合各适合什么场景?Agent代码里为什么用推导式比for循环更多?
  • [ ] lambda 在什么情况下比写一个 def 更合适?
  • [ ] 装饰器和上下文管理器的本质区别是什么?
  • [ ] asyncio 什么时候能加速你的Agent?什么时候加速不了?
  • [ ] 写Agent调外部API时,有哪三个容易踩的坑?

📚 延伸阅读


🎯 下一章预告

第4章,我们正式进入AI Agent的世界——

"Agent不是魔法,它只是个聪明点的程序。看完这一章,你就知道它到底是个什么东西。"