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_case(user_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

四、类型系统:dataclass 和 Pydantic(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 即测试
相关推荐
一水鉴天3 小时前
映射、哈希表与哈斯图:计算机科学的三种基线 20261003(元宝)
开发语言·人工智能
Frank_refuel3 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
海绵宝宝转agent3 小时前
learn-claude-code第1-5章开源学习笔记分享
人工智能·笔记·python·学习
小奇不哭3 小时前
ROS2 单节点,RGB-D 深度相机局部路径提取 + B 样条平滑路径 + YOLOv8 障碍物检测 + 深度测距,用于移动机器人视觉局部循迹。
python·yolov8·ros2·cv2·路径探索循迹
小小龙学IT4 小时前
Python scikit-learn 机器学习库深度解析
python·机器学习·scikit-learn
Wang's Blog4 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
2601_962071574 小时前
类变量和全局变量的查找路径有什么区别?
开发语言·python
卷无止境5 小时前
独立开发者的"富矿地带":哪些垂直领域值得你押注一辈子?
后端·python
\光辉岁月/5 小时前
5.java-数组
java·开发语言
Java后端的Ai之路5 小时前
Python进阶探索29_eval内置函数
开发语言·python·探索·eval·内置函数