Python Agent 开发速通清单

目录

[一、环境与工程(对应 Maven/Gradle)](#一、环境与工程(对应 Maven/Gradle))

[二、基础语法:和 Java 不同的 7 个坑](#二、基础语法:和 Java 不同的 7 个坑)

速查对照表

[1. 缩进即作用域(没有 {})](#1. 缩进即作用域(没有 {}))

[2. 变量是引用,但不可变类型行为像值类](#2. 变量是引用,但不可变类型行为像值类)

[3. 没有 ++ / for(i=0;i < a=""> <>](#3. 没有 ++ / for(i=0;i < a=""> <>)

[4. 字符串:f-string 取代 String.format](#4. 字符串:f-string 取代 String.format)

[5. 字典 = HashMap,但语法是字面量](#5. 字典 = HashMap,但语法是字面量)

[6. 函数是一等公民(可当参数传,类似 Java 8 lambda)](#6. 函数是一等公民(可当参数传,类似 Java 8 lambda))

[7. 真值判断:空容器、0、None 都是 False](#7. 真值判断:空容器、0、None 都是 False)

[三、面向对象:和 Java OO 的对照](#三、面向对象:和 Java OO 的对照)

类与构造器

[私有:没有真正的 private(呼应你上一个问题)](#私有:没有真正的 private(呼应你上一个问题))

[接口 / 抽象类](#接口 / 抽象类)

[继承(支持多继承 + MRO)](#继承(支持多继承 + MRO))

[四、类型系统:dataclass 和 Pydantic(agent 开发核心)](#四、类型系统:dataclass 和 Pydantic(agent 开发核心))

[dataclass ------ 对应 Java record(轻量、快)](#dataclass —— 对应 Java record(轻量、快))

[Pydantic ------ 对应 Java record + 校验(agent 开发首选)](#Pydantic —— 对应 Java record + 校验(agent 开发首选))

五、异常与资源管理

[try-with-resources → with 语句](#try-with-resources → with 语句)

异常体系

[六、异步:async/await(对应 CompletableFuture / WebFlux)](#六、异步:async/await(对应 CompletableFuture / WebFlux))

[七、装饰器(对应 Java 注解 + AOP)](#七、装饰器(对应 Java 注解 + AOP))

[八、Agent 核心:一次完整的最小可用示例](#八、Agent 核心:一次完整的最小可用示例)

九、生态地图(别全学,按需挑)


前言约定:每条都给 Java 对照 + 能跑的示例。你只需抓住"和 Java 不一样的地方",相同的地方直接跳过。


一、环境与工程(对应 Maven/Gradle)

Java 概念 Python 对应 说明
JDK Python 解释器 用 3.10+(agent 生态最低要求)
Maven/Gradle uv 或 poetry 别用裸 pip,依赖管理会乱
pom.xml pyproject.toml 依赖与项目元信息都在这
.m2 本地仓库 虚拟环境 .venv 每个项目隔离依赖
Maven Central PyPI uv add anthropic

最快上手(推荐 uv):

复制代码
# 安装 uv(一次)
pip install uv
# 建项目
uv init my-agent
cd my-agent
uv add anthropic          # 类似 mvn install + 写 pom
uv run python main.py     # 在隔离环境里跑

关键差异:Python 没有编译期类型检查。类型注解(x: int)只是提示,运行时不校验。要真校验得靠 Pydantic(下面会讲)。


二、基础语法:和 Java 不同的 7 个坑

速查对照表

对象 Python 规范 示例 Java 对比
变量、函数 snake_case 蛇形 user_name userName 驼峰
PascalCase 大驼峰 ChatAgent 一样
常量 UPPER_SNAKE MAX_RETRY 一样
模块(文件) lowercase / lower_with_underscore agent_utils.py ---
包(目录) lowercase短、无下划线 myagent 全小写
私有成员 前缀 _ _internal 无约定俗成
名字冲突/强制私有 前缀 __ __private ---
类型变量 T / TypeVar 单大写 T, T_co <T>

⚠️ 最大的坑 :Java 习惯用 camelCase 写变量名(userName),Python 一律 snake_caseuser_name)。IDE 会标黄。

1. 缩进即作用域(没有 {}

python 复制代码
# Java: if (x > 0) { ... }
# Python: 靠缩进
def check(x):
    if x > 0:
        print("正数")   # 4 空格缩进 = 在 if 内
    print("总会执行")   # 不缩进 = if 外

2. 变量是引用,但不可变类型行为像值类

python 复制代码
a = [1, 2, 3]
b = a           # b 和 a 指向同一个 list(类似 Java 引用)
b.append(4)
print(a)        # [1, 2, 3, 4] ------ a 也变了!

# 想要副本:
b = a.copy()    # 浅拷贝
b = a[:]        # 等价写法

3. 没有 ++ / for(i=0;i<n;i++)

python 复制代码
# Java: for (int i = 0; i < 3; i++)
for i in range(3):
    print(i)    # 0, 1, 2

# 遍历集合(Java: for (String s : list))
for item in ["a", "b", "c"]:
    print(item)

4. 字符串:f-string 取代 String.format

python 复制代码
name = "agent"
count = 3
# Java: String.format("Hello %s, count=%d", name, count)
print(f"Hello {name}, count={count}")   # f-string,最常用
print(f"{count:03d}")                    # 003,格式化

5. 字典 = HashMap,但语法是字面量

python 复制代码
# Java: Map<String, Integer> map = new HashMap<>();
d = {"a": 1, "b": 2}
d["c"] = 3
print(d.get("z", 0))   # 不存在返回默认值 0,类似 getOrDefault

6. 函数是一等公民(可当参数传,类似 Java 8 lambda)

python 复制代码
# Java: list.stream().map(x -> x * 2).collect(...)
nums = [1, 2, 3]
doubled = [x * 2 for x in nums]          # 列表推导,最 Pythonic
doubled = list(map(lambda x: x * 2, nums))  # 也能这么写,但不推荐

7. 真值判断:空容器、0、None 都是 False

python 复制代码
# Java: if (list != null && !list.isEmpty())
lst = []
if lst:          # 非空为真,无需判空
    print("有元素")
if not lst:
    print("空")  # 打印这个

三、面向对象:和 Java OO 的对照

类与构造器

python 复制代码
# Java:
# public class User {
#     private String name; private int age;
#     public User(String name, int age) { ... }
# }

class User:
    def __init__(self, name: str, age: int):   # 构造器;self = this
        self.name = name
        self.age = age

u = User("bot", 3)
print(u.name)

self 必须显式写第一个参数(Java 的 this 是隐式的)。这是新手最容易忘的。

私有:没有真正的 private(呼应你上一个问题)

python 复制代码
class Agent:
    def __init__(self):
        self.name = "bot"        # public
        self._config = {}        # 约定私有(单下划线)
        self.__secret = "key"    # 名称改写(双下划线)→ 实际叫 _Agent__secret

# 没有 private 关键字,全靠约定。你上一题的报错就是这个。

接口 / 抽象类

python 复制代码
from abc import ABC, abstractmethod

# Java: interface Tool { String run(String input); }
class Tool(ABC):                       # ABC = Abstract Base Class
    @abstractmethod
    def run(self, input: str) -> str:
        ...

class SearchTool(Tool):
    def run(self, input: str) -> str:  # 必须实现
        return f"searching {input}"

还有更轻的 Protocol(结构化类型,类似 TypeScript interface / Go 接口,不要求显式继承)------agent 框架里很常见:

python 复制代码
from typing import Protocol

class ToolLike(Protocol):
    def run(self, input: str) -> str: ...   # 只定义形状,不继承也能匹配

继承(支持多继承 + MRO)

python 复制代码
class Base:
    def greet(self):
        return "base"

class Mixin:
    def log(self):
        print("logged")

class Agent(Base, Mixin):   # 多继承,Java 不支持
    pass

a = Agent()
a.greet()   # base
a.log()     # logged

四、类型系统:dataclassPydantic(agent 开发核心)

Agent 开发要大量定义"消息结构 / 工具参数 / API 响应"。Java 用 record / POJO,Python 用这两个。

dataclass ------ 对应 Java record(轻量、快)

python 复制代码
from dataclasses import dataclass

# Java: public record User(String name, int age) {}
@dataclass
class User:
    name: str
    age: int = 18          # 默认值

u = User("bot")
print(u)                    # User(name='bot', age=18)  ------ 自动 __repr__

Pydantic ------ 对应 Java record + 校验(agent 开发首选)

python 复制代码
from pydantic import BaseModel, Field

class ToolArgs(BaseModel):
    query: str = Field(..., min_length=1, max_length=100)
    limit: int = Field(10, ge=1, le=50)   # ge=大于等于,le=小于等于

# 自动校验 + 报错(运行时真正校验,这是和 dataclass 的关键区别)
args = ToolArgs(query="hello", limit=5)
print(args.model_dump())     # {'query': 'hello', 'limit': 5}

# ToolArgs(query="")          # ❌ 校验失败抛 ValidationError
# ToolArgs(query="x", limit=0) # ❌ limit 必须 >=1

为什么 agent 开发离不开 Pydantic: LLM 返回的是 JSON,你要把它映射成 Python 对象并校验。几乎所有 agent 框架(LangChain、Anthropic SDK 的结构化输出)底层都是 Pydantic。


五、异常与资源管理

try-with-resources → with 语句

python 复制代码
# Java:
# try (var br = new BufferedReader(new FileReader("f.txt"))) { ... }

with open("data.txt", "r", encoding="utf-8") as f:   # 退出 with 自动关闭
    content = f.read()
# 这里 f 已关闭,无需 finally

异常体系

python 复制代码
# Java: try { ... } catch (IOException e) { ... } finally { ... }
try:
    result = 10 / 0
except ZeroDivisionError as e:        # 捕获具体异常
    print(f"除零: {e}")
except (ValueError, TypeError):       # 多个异常一起捕获
    print("类型错误")
except Exception as e:                # 兜底(类似 catch Throwable)
    print(f"其他: {e}")
else:
    print("无异常时执行")
finally:
    print("总执行")

Python 异常不要求"声明或捕获"(没有 checked exception)。这更灵活,但也意味着你得主动列出可能出错的点,不能靠编译器提醒。


六、异步:async/await(对应 CompletableFuture / WebFlux)

Agent 经常要并发调多个工具或 LLM,异步是必修。

python 复制代码
import asyncio
import anthropic

# Java CompletableFuture:
#   CompletableFuture.supplyAsync(() -> callA())
#       .thenCombine(CompletableFuture.supplyAsync(() -> callB()), ...)

async def call_llm(prompt: str) -> str:
    client = anthropic.AsyncAnthropic()          # 异步客户端
    resp = await client.messages.create(         # await = 阻塞等待,不占线程
        model="claude-opus-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return resp.content[0].text

async def main():
    # 并发执行多个(类似 CompletableFuture.allOf)
    results = await asyncio.gather(
        call_llm("写一句诗"),
        call_llm("写一句歌词"),
    )
    print(results)

asyncio.run(main())   # 启动事件循环(入口必须这么调)

三条铁律:

  1. async def 定义的函数必须用 await 调用,不能直接 call()
  2. await 只能在 async def 内部。
  3. 事件循环入口:脚本顶层用 asyncio.run(main())

七、装饰器(对应 Java 注解 + AOP)

Python 装饰器是真正的函数包装,不像 Java 注解只是标记。

python 复制代码
import time
from functools import wraps

# Java AOP @Around 思路:在方法前后插逻辑
def log_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时 {time.time()-start:.2f}s")
        return result
    return wrapper

@log_time                    # 等价于  search = log_time(search)
def search(q):
    time.sleep(0.5)
    return f"结果: {q}"

search("hello")              # 打印: search 耗时 0.50s

Agent 框架大量用装饰器注册工具,例如 Anthropic SDK 的 @beta_tool。把它理解成"声明这个函数是个工具 + 自动生成参数 schema"。


八、Agent 核心:一次完整的最小可用示例

下面用 Anthropic 官方 SDK 做一个带工具调用的 agent loop------这是 agent 开发的本质:LLM 决定调什么工具 → 你执行 → 把结果喂回去 → 循环直到完成。

python 复制代码
# pip install anthropic
import anthropic

client = anthropic.Anthropic()   # 读 ANTHROPIC_API_KEY 环境变量

# 1) 定义工具(LLM 看得懂的"函数签名")
tools = [{
    "name": "get_weather",
    "description": "查询某城市天气",
    "input_schema": {
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "城市名"},
        },
        "required": ["city"],
    },
}]

# 2) 实际执行工具的 Python 函数
def get_weather(city: str) -> str:
    # 真实场景里这里调天气 API
    return f"{city} 今天 25°C 晴"

# 3) Agent 主循环
def run_agent(user_input: str):
    messages = [{"role": "user", "content": user_input}]

    while True:                                  # agent loop
        resp = client.messages.create(
            model="claude-opus-5",
            max_tokens=1024,
            tools=tools,
            messages=messages,
        )

        # 4) LLM 想调工具 → stop_reason == "tool_use"
        if resp.stop_reason == "tool_use":
            # 把 assistant 这轮(含 tool_use 块)加回历史
            messages.append({"role": "assistant", "content": resp.content})

            # 执行所有被请求的工具,把结果作为 user 消息回传
            tool_results = []
            for block in resp.content:
                if block.type == "tool_use":
                    result = get_weather(**block.input)   # ** 解包字典为参数
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": result,
                    })
            messages.append({"role": "user", "content": tool_results})
            # 继续 while,让 LLM 看到工具结果后决定下一步
        else:
            # 5) 不再需要工具 → end_turn,输出最终回答
            for block in resp.content:
                if block.type == "text":
                    print(block.text)
            return

run_agent("北京天气怎么样?")

这段就是 agent 的全部内核。不管框架多花哨,本质都是这个 while 循环。理解了它,LangChain / LangGraph / Anthropic Tool Runner 都只是这个循环的不同封装。


九、生态地图(别全学,按需挑)

工具 类比 何时用
LLM SDK anthropic 直接调 API 最底层、最可控,先掌握这个
Agent 框架 LangGraph 工作流引擎 多步骤、带状态的复杂 agent
Agent 框架 LangChain Spring 全家桶 功能多但重,不建议入门
Web 框架 FastAPI Spring Boot 把 agent 包成 HTTP 服务
数据校验 Pydantic Bean Validation 必学,FastAPI/agent 都依赖它
包管理 uv Maven 必学
测试 pytest JUnit 语法最简,assert 即测试
相关推荐
小蒜学长1 小时前
基于Django的社区团购购物平台的设计与实现(代码+数据库+LW)
数据库·后端·python·django
zq_63891 小时前
ObjectModel_diagram.pdf 文档详细总结
开发语言·matlab
AC赳赳老秦1 小时前
个保法下数据处理:OpenClaw 自动过滤公开数据中的个人信息,保障采集分析合规性
java·python·sqlite·json·php·deepseek·openclaw
Zane19941 小时前
threading、multiprocessing、asyncio 到底怎么选?一张图 + 三组实测数据说清楚
后端·python
Three_ST1 小时前
沐神-动手学习深度学习-习题答案4.4模型选择,欠拟合,过拟合
人工智能·python·深度学习·学习·算法
CodeStats1 小时前
【Java进程通信】Java进程通信系统完全指南:从ProcessBuilder底层原理到多语言实战
java·前端·python·进程·ai编程·processbuilder
用户0332126663671 小时前
使用 Python 设置 Excel 文件属性
python
jyOverQ2 小时前
LangGraph Agent 模式详解:从自主决策到 Tool Calling 执行链
python·langchain
自己的九又四分之三站台2 小时前
C# 接入 RasterLite2:从原生 DLL 加载到 Coverage、Section、Tile 验证
开发语言·c#·地理信息