Python 语法详解 —— 面向 C / C++ 开发者
本文档基于
codePython1.py~codePython10.py中的代码示例,逐一解释涉及的 Python 语法。 读者定位:资深 C 语言开发者 + 基础 C++ 开发者,因此会大量与 C/C++ 做对比。
目录
- Python 整体哲学:与 C/C++ 的根本差异
- 函数定义与参数
- 类与面向对象
- 魔术方法(
__xxx__) - 类型注解与 typing 模块
- 装饰器
- 异步编程:async / await
- 异常处理
- 模块与包
- 高级数据结构与语法糖
- 文件与 I/O
- 并发编程:threading
- 其他实用语法
- 总结:Python 与 C/C++ 关键差异速查表
1. Python 整体哲学:与 C/C++ 的根本差异
1.1 动态类型 vs 静态类型
C/C++:
int x = 10; // 必须声明类型
char* s = "hello"; // 类型固定
Python:
x = 10 # 无需声明类型,运行时推断
x = "hello" # 同一个变量可以随时改变类型!
代码示例(codePython2.py 第 5-7 行):
def __init__(self, role: str, content: str):
self.role = role
self.content = content
这里的 role: str 是类型注解(Type Hint),但它不是强制约束——它只是给开发者看的”注释”,Python 解释器不会检查类型是否正确。这与 C/C++ 的静态类型系统完全不同。
1.2 缩进代替花括号
C/C++:
if (x > 0) {
printf("positive");
}
Python:
if x > 0:
print("positive") # 缩进(通常是4个空格)表示代码块
代码示例(codePython2.py 第 54-58 行):
def is_visible(self) -> bool:
return self.status not in ["hidden", "deleted"]
def is_editable(self) -> bool:
return self.status not in ["locked", "readonly"]
注意:没有花括号,没有 {},完全靠缩进层级来定义函数体、循环体、条件体。
1.3 Python 的”一切皆对象”
在 Python 中,函数、类、模块、甚至类型本身都是对象。这意味着:
- 函数可以像变量一样传递
- 类可以动态创建
- 函数可以有属性
代码示例(codePython2.py 第 430-434 行):
def register_plugin(intent: str):
def decorator(func):
plugin_registry[intent] = func
return func
return decorator
这里 register_plugin 是一个函数,它返回另一个函数 decorator。这在 C 语言中是不可能的(C 的函数不能嵌套定义并返回),但在 C++ 中可以通过 lambda 或函数对象实现类似效果。
2. 函数定义与参数
2.1 基本函数定义:def
语法:
def 函数名(参数列表):
"""文档字符串(可选)"""
函数体
return 返回值 # 可选
与 C/C++ 对比:
| 特性 | C | C++ | Python |
|---|---|---|---|
| 函数定义 | int f(int x) | int f(int x) | def f(x): |
| 返回值类型 | 必须声明 | 必须声明 | 无需声明(可用注解) |
| 参数类型 | 必须声明 | 必须声明 | 无需声明(可用注解) |
| 函数重载 | 不支持 | 支持 | 不支持(同名函数会覆盖) |
代码示例(codePython3.py 第 34-63 行):
def simulate_mcp_response(success=True): # 默认参数
if success:
return { ... } # 返回字典
else:
return { ... } # 返回另一个字典
2.2 参数类型注解(Type Hints)
Python 3.5+ 支持类型注解,但仅用于提示,不强制检查。
def func(x: int, y: str) -> bool: # x是int, y是str, 返回bool
return True
代码示例(codePython2.py 第 5-14 行):
def __init__(
self,
role: str,
content: str,
name: Optional[str] = None, # Optional[str] 表示可以是 str 或 None
status: Optional[str] = None,
metadata: Optional[Dict] = None, # Dict 表示字典类型
id: Optional[str] = None,
parent_id: Optional[str] = None
):
与 C++ 对比:
- C++ 的
int x是编译时强制检查 - Python 的
x: int是运行时注释,可以用工具(如 mypy)做静态检查,但 Python 解释器本身不检查
2.3 默认参数
def func(x, y=10): # y 的默认值是 10
return x + y
代码示例(codePython2.py 第 155 行):
def __init__(self, role, content, parent_id=None, status="active"):
⚠️ 重要陷阱(与 C++ 不同): Python 的默认参数在函数定义时求值,而不是在调用时。如果默认值是可变对象(如列表、字典),会有问题:
def add_item(item, lst=[]): # ❌ 危险!lst 只初始化一次
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 同一个列表!
正确做法:
def add_item(item, lst=None): # ✅ 安全
if lst is None:
lst = []
lst.append(item)
return lst
2.4 返回值注解:-> 类型
def func() -> str: # 返回 str 类型
return "hello"
def func() -> bool: # 返回 bool 类型
return True
def func() -> List[str]: # 返回字符串列表
return ["a", "b"]
代码示例(codePython2.py 第 54-55 行):
def is_visible(self) -> bool:
return self.status not in ["hidden", "deleted"]
2.5 lambda 匿名函数
类似 C++ 的 lambda 表达式,但 Python 的 lambda 只能写单行表达式。
lambda 参数: 表达式
代码示例(codePython6.py 第 624 行):
condition_func=lambda ctx: ctx["user_type"] == "admin"
等价于:
def condition_func(ctx):
return ctx["user_type"] == "admin"
与 C++ lambda 对比:
| 特性 | C++ lambda | Python lambda |
|---|---|---|
| 语法 | [capture](params){body} | lambda params: expr |
| 多行 | 支持 | 不支持 |
| 捕获 | 显式捕获列表 | 自动捕获外部变量 |
| 用途 | 通用 | 主要用于高阶函数参数 |
2.6 yield 生成器
yield 类似 C++ 的协程或迭代器,函数可以”暂停”并”恢复”。
代码示例(codePython4.py 第 845-858 行):
def token_stream_generator():
"""模拟一个Token流生成器,每次迭代返回一部分Token。"""
tokens = ["您好", ",", "欢迎", "使用", ...]
for token in tokens:
time.sleep(0.1) # 模拟生成延迟
yield token # ← 暂停并返回值,下次从这继续
调用方式:
for token in token_stream_generator(): # 每次循环调用一次 yield
print(token)
🎯 个性化理解(来自资深 C 开发者):yield 相当于特殊断点
可以把 yield 想象成一个特殊的断点:
next()调用:执行到yield断点处,打印(返回)yield后面变量的值,然后函数暂停send(value)调用:为yield后面的变量赋值(即yield表达式的结果),然后继续执行- 没有
next()和yield调用:函数会继续执行到下一行yield或函数末尾
def gen():
x = yield 1 # 第一次 next() 返回 1,暂停
y = yield x + 10 # send(5) 给 x 赋值为 5,然后返回 15,暂停
yield y + 100 # send(20) 给 y 赋值为 20,返回 120
g = gen()
print(next(g)) # 1 —— 执行到第一个 yield,返回 1
print(g.send(5)) # 15 —— 给 x 赋 5,执行到第二个 yield,返回 5+10
print(g.send(20)) # 120 —— 给 y 赋 20,执行到第三个 yield,返回 20+100
与 C/C++ 对比:
- C 语言没有直接等价物
- C++20 有协程(coroutines),但语法更复杂
- Python 的
yield更接近 C++ 的generator(Boost.Coroutine)
2.7 函数是一等公民
函数可以像变量一样赋值、传递、作为返回值。
代码示例(codePython2.py 第 319 行):
self.subscribers: Dict[str, List[Callable[[StateChangeEvent], None]]] = {}
# 存储的是"函数列表",Callable 表示可调用对象(函数)
代码示例(codePython2.py 第 373-385 行):
def bind(self, callback):
self.listeners.append(callback) # 把函数当作值存储
def trigger_event(self):
for callback in self.listeners:
callback() # 调用存储的函数
# 使用:
event_system.bind(prompt.activate) # 把方法当作参数传递
这在 C 语言中可以通过函数指针实现,在 C++ 中可以通过 std::function 或 lambda 实现。
3. 类与面向对象
3.1 class 定义
语法:
class ClassName:
"""文档字符串"""
class_variable = 0 # 类变量(类似 C++ 的 static 成员)
def __init__(self, ...): # 构造函数
self.instance_var = ... # 实例变量
def method(self, ...): # 成员方法
pass
代码示例(codePython2.py 第 4-21 行):
class ContextObject:
def __init__(self, role: str, content: str, ...):
self.role = role
self.content = content
...
与 C++ class 的关键区别:
| 特性 | C++ | Python |
|---|---|---|
| 访问控制 | public/private/protected | 没有(全靠约定:_ 表示保护,__ 表示私有) |
| 构造函数 | ClassName() | __init__(self) |
| 析构函数 | ~ClassName() | __del__(self)(不常用) |
| this/self | 隐式 this 指针 | 显式 self 参数 |
| 成员变量 | 在类体中声明 | 在 __init__ 中通过 self.xxx 动态创建 |
| 多继承 | 支持 | 支持(C3线性化算法) |
| 虚函数 | virtual 关键字 | 所有方法默认都是”虚函数” |
3.2 self 参数 —— 与 C++ 的 this 对比
C++:
class Foo {
int x;
void setX(int v) { this->x = v; } // this 是隐式的
};
Python:
class Foo:
def setX(self, v): # self 是显式的第一个参数
self.x = v # 必须用 self.x 访问成员
为什么 Python 要显式写 self?
- 为了明确区分实例变量和局部变量
- 在 Python 中,
self只是一个约定名称(不是关键字),你可以叫它this或任何名字,但约定都用self
3.3 __init__ —— 构造函数
__init__ 是 Python 类的构造函数,在对象创建时自动调用。
代码示例(codePython2.py 第 5-14 行):
class ContextObject:
def __init__(self, role: str, content: str, ...):
self.role = role
self.content = content
...
创建对象:
obj = ContextObject(role="user", content="hello")
# 不需要 new 关键字!直接调用类名即可
与 C++ 对比:
- C++:
ContextObject* obj = new ContextObject();或ContextObject obj; - Python:
obj = ContextObject()—— 没有new关键字
3.4 实例变量 vs 类变量
类变量(类似 C++ 的 static 成员):
class Foo:
count = 0 # 类变量,所有实例共享
def __init__(self):
Foo.count += 1
实例变量(每个对象独有):
class Foo:
def __init__(self, name):
self.name = name # 实例变量,通过 self.xxx 创建
代码示例(codePython2.py 第 317 行):
class StateChangeNotifier:
def __init__(self):
self.subscribers: Dict[str, List[Callable]] = {}
# subscribers 是实例变量,每个 StateChangeNotifier 对象都有自己的 subscribers
3.5 @classmethod 和 @staticmethod
@classmethod(类方法):
- 第一个参数是
cls(类本身),而不是self(实例) - 可以通过类名直接调用,也可以通过实例调用
- 类似 C++ 的 static 成员函数,但可以访问类变量
@staticmethod(静态方法):
- 没有
self或cls参数 - 就是一个放在类命名空间里的普通函数
- 类似 C++ 的 static 成员函数,但不能访问类变量
代码示例(codePython2.py 第 171-175 行):
class ContextObject:
@classmethod
def from_dict(cls, d): # cls 是类本身
obj = cls(d["role"], d["content"], d.get("parent_id"), d.get("status", "active"))
obj.id = d["id"]
return obj
调用方式:
# 类方法可以通过类名直接调用
obj = ContextObject.from_dict(some_dict)
3.6 super() —— 调用父类方法
类似 C++ 的 BaseClass::method()。
代码示例(codePython6.py 第 432 行):
class MailSorter(MailModuleBase):
def __init__(self):
super().__init__("邮件整理") # 调用父类 MailModuleBase 的 __init__
self.mail_content = ""
与 C++ 对比:
- C++:
MailModuleBase::MailModuleBase("邮件整理")或使用初始化列表 - Python:
super().__init__("邮件整理")
3.7 @dataclass —— 数据类
Python 3.7+ 引入,自动生成 __init__、__repr__、__eq__ 等方法,类似 C++ 的 POD 结构体。
代码示例(codePython9.py 第 92-101 行):
from dataclasses import dataclass
@dataclass
class CharacterProfile:
name: str
background: str
personality: str
speaking_style: str
emotion: str
等价于手动写:
class CharacterProfile:
def __init__(self, name, background, personality, speaking_style, emotion):
self.name = name
self.background = background
self.personality = personality
self.speaking_style = speaking_style
self.emotion = emotion
def __repr__(self):
return f"CharacterProfile(name={self.name!r}, ...)"
def __eq__(self, other):
return (self.name, self.background, ...) == (other.name, other.background, ...)
与 C++ struct 对比:
- C++ struct 只是数据聚合
- Python
@dataclass自动生成构造函数、字符串表示、比较运算符等
3.8 pydantic.BaseModel —— 带验证的数据模型
类似 @dataclass 但更强大,提供类型验证、序列化/反序列化等功能。
代码示例(codePython7.py 第 92-110 行):
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
class MailMeta(BaseModel):
sender: str = Field(..., description="发件人邮箱地址")
receiver: str = Field(..., description="收件人邮箱地址")
subject: str = Field(..., description="邮件主题")
timestamp: datetime = Field(..., description="邮件接收时间")
特点:
Field(...)中的...表示必填字段Field(None)表示可选字段- 自动进行类型验证(比如
timestamp必须是datetime类型) - 提供
.dict()、.json()等方法进行序列化
3.9 Enum 枚举
Python 的枚举类似 C++ 的 enum class。
代码示例(codePython7.py 第 314-323 行):
from enum import Enum, auto
class TaskState(Enum):
INIT = auto() # 自动分配值 1
PARSED = auto() # 2
CLASSIFIED = auto() # 3
SUMMARIZED = auto() # 4
REPLIED = auto() # 5
ARCHIVED = auto() # 6
COMPLETED = auto() # 7
使用方式:
state = TaskState.INIT
if state == TaskState.INIT:
print("初始化中")
print(state.name) # "INIT"
print(state.value) # 1
4. 魔术方法(__xxx__)
魔术方法(Magic Methods / Dunder Methods)是 Python 中以双下划线开头和结尾的特殊方法,它们不是被直接调用的,而是由 Python 解释器在特定场景下自动调用。
🎯 个性化理解(来自资深 C 开发者):魔术方法相当于 C++ 的运算符重载
在 C++ 中,你可以重载 operator+、operator==、operator[] 等运算符,让自定义类型支持内置运算符的语法。Python 的魔术方法本质上是同一件事——通过定义特殊名称的方法,让自定义对象支持 Python 的内置操作。
| Python 魔术方法 | 等价 C++ 运算符重载 | 触发场景 |
|---|---|---|
__add__(self, other) | operator+(const T& other) | obj + other |
__eq__(self, other) | operator==(const T& other) | obj == other |
__getitem__(self, key) | operator[](const Key& key) | obj[key] |
__call__(self, args) | operator()(Args... args) | obj(args) |
__str__(self) | operator<<(ostream&, const T&) | print(obj) |
__len__(self) | 无直接等价 | len(obj) |
关键区别:
- C++ 的运算符重载使用
operator关键字 + 运算符符号 - Python 的”运算符重载”使用固定的双下划线方法名
- Python 的魔术方法覆盖范围更广,还包括对象创建(
__init__)、资源管理(__enter__/__exit__)、迭代器(__iter__/__next__)等
4.1 __init__ —— 构造函数
触发时机: 对象创建时自动调用
obj = MyClass(args) # → 自动调用 __init__(self, args)
代码示例(codePython2.py 第 5-14 行):
def __init__(self, role: str, content: str, ...):
self.role = role
self.content = content
4.2 __name__ == "__main__" —— 模块入口检查
这不是魔术方法,而是一个常见的 Python 惯用法。
if __name__ == "__main__":
# 只有直接运行此文件时才会执行
main()
作用:
- 当文件被直接运行时,
__name__被设为"__main__" - 当文件被
import导入时,__name__被设为模块名(如"codePython2") - 这样可以让一个文件既可以作为脚本运行,也可以作为模块导入
代码示例(codePython2.py 第 264 行):
if __name__ == "__main__":
engine = ExecutionEngine()
...
与 C/C++ 对比:
- C 语言没有直接等价物
- 类似用
#ifdef MAIN宏来控制编译
4.3 __aenter__ 和 __aexit__ —— 异步上下文管理器
用于 async with 语句,类似 C++ 的 RAII 但用于异步场景。
代码示例(codePython5.py 第 14-18 行):
async with stdio_client(server_params) as (stdio, write):
async with ClientSession(stdio, write) as session:
await session.initialize()
async with 的执行流程:
- 调用
__aenter__(异步获取资源) - 执行
with块中的代码 - 调用
__aexit__(异步释放资源)
4.4 其他常见魔术方法
| 魔术方法 | 触发时机 | 类似 C++ |
|---|---|---|
__str__ | str(obj) 或 print(obj) | operator<< |
__repr__ | 调试输出 | — |
__len__ | len(obj) | — |
__getitem__ | obj[key] | operator[] |
__setitem__ | obj[key] = value | operator[] |
__call__ | obj(args) | operator() |
__enter__ / __exit__ | with obj: | RAII |
__iter__ / __next__ | for x in obj: | 迭代器 |
__eq__ | obj == other | operator== |
__lt__ | obj < other | operator< |
__add__ | obj + other | operator+ |
5. 类型注解与 typing 模块
5.1 基本类型注解
x: int = 10
y: str = "hello"
z: bool = True
def func() -> float:
return 3.14
5.2 Optional —— 可选类型
Optional[X] 等价于 Union[X, None],表示可以是 X 类型或 None。
代码示例(codePython2.py 第 9 行):
name: Optional[str] = None
# 等价于:name 可以是 str 或 None
5.3 Dict, List —— 泛型容器
代码示例(codePython2.py 第 103 行):
self.nodes: Dict[str, ContextObject] = {}
# 键是 str,值是 ContextObject 的字典
代码示例(codePython2.py 第 108 行):
def trace_chain(self, start_id: str) -> List[ContextObject]:
# 返回 ContextObject 列表
5.4 Callable —— 可调用类型
代码示例(codePython2.py 第 294 行):
from typing import Callable
self.subscribers: Dict[str, List[Callable[[StateChangeEvent], None]]] = {}
# Callable[[参数类型], 返回值类型]
# 这里表示:接收 StateChangeEvent 参数,返回 None 的函数
5.5 Any —— 任意类型
from typing import Any
x: Any = 10
x = "hello" # 没问题,Any 表示任意类型
5.6 类型注解只是”注释”
重要: Python 的类型注解不会在运行时检查。以下代码可以正常运行:
def add(x: int, y: int) -> int:
return x + y
print(add("hello", "world")) # 输出 "helloworld"!类型注解被忽略
要真正做类型检查,需要使用外部工具如 mypy。
6. 装饰器
装饰器(Decorator)是 Python 中修改函数或类行为的一种方式,本质是一个接受函数并返回新函数的高阶函数。
6.1 装饰器的本质
# 装饰器语法糖:
@decorator
def func():
pass
# 等价于:
func = decorator(func)
🎯 个性化理解(来自资深 C 开发者):装饰器 = 模板函数 + 函数指针重命名
假设有一个模板函数(即装饰器函数),其中有一行是函数指针调用——调用传入的入参函数。装饰器会将包含实际入参函数的模板函数重命名为入参函数的名字。
# 模板函数(装饰器)
def decorator(func): # func 是"入参函数指针"
def wrapper(*args, **kwargs): # wrapper 是"模板函数"
print("调用前") # 模板的前置逻辑
result = func(*args, **kwargs) # ← 函数指针调用!调用传入的函数
print("调用后") # 模板的后置逻辑
return result
return wrapper # 返回模板函数
# 使用装饰器
@decorator
def say_hello(name): # say_hello 是"实际入参函数"
print(f"你好, {name}")
# 等价于:
# say_hello = decorator(say_hello)
# 即:将包含 say_hello 的模板函数 wrapper 重命名为 say_hello
say_hello("张三")
# 输出:
# 调用前
# 你好, 张三
# 调用后
关键理解:
decorator是模板工厂,接收一个函数指针funcwrapper是模板函数,内部通过func(...)调用传入的函数@decorator将wrapper重命名为原函数的名字(say_hello)- 之后调用
say_hello("张三"),实际执行的是wrapper("张三"),其中包含了模板逻辑 + 原函数调用
6.2 函数装饰器
代码示例(codePython2.py 第 430-434 行):
def register_plugin(intent: str):
def decorator(func):
plugin_registry[intent] = func
return func
return decorator
使用:
@register_plugin("generate_report") # 相当于 generate_daily_report = register_plugin("generate_report")(generate_daily_report)
def generate_daily_report(input_text):
return f"[插件返回] 日报已生成..."
执行流程:
register_plugin("generate_report")被调用,返回decorator函数@decorator将generate_daily_report函数作为参数传给decoratordecorator把函数注册到plugin_registry中,然后返回原函数
6.3 FastMCP 工具装饰器
代码示例(codePython5.py 第 119 行):
@app.tool()
async def fetch_data(api_url: str) -> str:
"""模拟从外部API获取数据的工具函数"""
return f"Data from {api_url}"
这里的 @app.tool() 将 fetch_data 函数注册为 MCP 服务器的一个工具。
6.4 装饰器与 C++ 的对比
| 特性 | Python 装饰器 | C++ 等价物 |
|---|---|---|
| 函数包装 | @decorator | 函数包装器 / lambda |
| 注册机制 | @app.tool() | 手动注册 |
| AOP 编程 | 装饰器 | 模板 / 宏 |
7. 异步编程:async / await
Python 的 async/await 是协程(Coroutine)的实现,类似 C++20 的协程,但语法更简洁。
7.1 基本概念
async def func(): # 定义一个协程函数
await other_func() # 等待另一个协程完成
return result
result = await func() # 在另一个协程中调用
7.2 asyncio.run() —— 事件循环入口
代码示例(codePython5.py 第 24-25 行):
if __name__ == "__main__":
asyncio.run(main()) # 创建事件循环,运行 main() 协程
与 C++ 对比:
- C++ 需要手动管理事件循环(如
boost::asio::io_context) - Python 的
asyncio.run()自动创建和销毁事件循环
7.3 async with —— 异步上下文管理器
代码示例(codePython5.py 第 14-18 行):
async with stdio_client(server_params) as (stdio, write):
async with ClientSession(stdio, write) as session:
await session.initialize()
执行流程:
__aenter__异步获取资源- 执行代码块
__aexit__异步释放资源
7.4 await —— 等待协程
代码示例(codePython5.py 第 18-21 行):
await session.initialize() # 等待初始化完成
response = await session.call_tool(...) # 等待工具调用结果
await 的作用:
- 暂停当前协程的执行
- 让出控制权给事件循环
- 等待的协程完成后恢复执行
7.5 async def —— 定义协程
代码示例(codePython5.py 第 12 行):
async def main():
...
调用协程:
# ❌ 错误:直接调用不会执行协程
main() # 返回一个 coroutine 对象,不会执行
# ✅ 正确:必须在事件循环中 await
await main()
# ✅ 或者用 asyncio.run()
asyncio.run(main())
7.6 异步与多线程的对比
| 特性 | asyncio | threading |
|---|---|---|
| 并发模型 | 单线程协作式 | 多线程抢占式 |
| 切换方式 | await 主动让出 | 操作系统调度 |
| 共享数据 | 无需锁(单线程) | 需要锁 |
| 适用场景 | I/O 密集型 | CPU 密集型 |
| 类似 C++ | C++20 协程 | std::thread |
8. 异常处理
8.1 try / except / finally
语法:
try:
# 可能出错的代码
result = risky_operation()
except SomeError as e:
# 捕获特定异常
print(f"出错:{e}")
except Exception as e:
# 捕获所有异常
print(f"未知错误:{e}")
else:
# 没有异常时执行
print("成功!")
finally:
# 无论是否异常都执行(类似 C++ 的析构函数)
cleanup()
代码示例(codePython3.py 第 161-166 行):
try:
serialized = json.dumps(request_object, ensure_ascii=False, indent=2)
print("✅ JSON结构合法")
except Exception as e:
print("❌ JSON格式错误:", e)
8.2 自定义异常
代码示例(codePython3.py 第 171-184 行):
class MCPError(Exception): # 继承自 Exception
def __init__(self, code, message, detail=None):
self.code = code
self.message = message
self.detail = detail or "无详细信息"
使用:
raise MCPError(
code="TOOL_FAIL_002",
message="工具调用失败:缺少必要参数",
detail="resume_text 字段未提供"
)
8.3 与 C++ 异常对比
| 特性 | C++ | Python |
|---|---|---|
| 抛出异常 | throw | raise |
| 捕获异常 | catch | except |
| 捕获所有 | catch(...) | except: |
| 清理操作 | RAII / catch + 清理 | finally |
| 异常类型 | 任何类型 | 必须是 BaseException 的子类 |
9. 模块与包
9.1 import 语句
语法:
import module_name # 导入整个模块
from module_name import func # 导入特定函数
from module_name import func as f # 导入并重命名
from module_name import * # 导入所有(不推荐)
代码示例(codePython1.py 第 3 行):
from openai import OpenAI # 从 openai 包中导入 OpenAI 类
与 C/C++ 对比:
- C:
#include <stdio.h>—— 文本包含,编译时 - Python:
import openai—— 运行时加载,模块是对象
9.2 包结构
Python 的包是一个包含 __init__.py 文件的目录。
代码示例(codePython9.py 中的包结构):
actors/
__init__.py # 可以是空文件,标识这是一个包
character_config.py
context_manager.py
prompts/
__init__.py
character_prompt_templates.py
emotion_map.py
story_templates.py
导入方式:
from actors.character_config import CHARACTER_CONFIGS
from prompts.emotion_map import emotion_tone_hint
10. 高级数据结构与语法糖
10.1 列表推导式(List Comprehension)
类似数学中的集合构造:{ x² | x ∈ [1,10], x 是偶数 }
语法:
[表达式 for 变量 in 可迭代对象 if 条件]
代码示例(codePython2.py 第 141 行):
return [p for p in self.prompts if model_capability in p.status]
等价于:
result = []
for p in self.prompts:
if model_capability in p.status:
result.append(p)
return result
代码示例(codePython2.py 第 144 行):
return [p.to_dict() for p in self.prompts]
与 C++ 对比:
- C++ 需要手动写循环
- C++20 有 ranges 库可以实现类似效果,但语法更复杂
10.2 字典推导式
{k: v for k, v in iterable if condition}
代码示例(codePython7.py 第 384 行):
self._kv_cache = {item["step"]: item["data"] for item in self._chain}
10.3 字典的 get / setdefault 方法
dict.get(key, default) —— 安全获取值,不存在时返回默认值:
代码示例(codePython2.py 第 250 行):
return context_cache.get(session_id, None)
# 等价于:
# if session_id in context_cache:
# return context_cache[session_id]
# else:
# return None
dict.setdefault(key, default) —— 获取值,不存在时设置默认值并返回:
代码示例(codePython2.py 第 320 行):
self.subscribers.setdefault(event_type, []).append(handler)
# 等价于:
# if event_type not in self.subscribers:
# self.subscribers[event_type] = []
# self.subscribers[event_type].append(handler)
10.4 enumerate —— 带索引的遍历
代码示例(codePython8.py 第 262 行):
for idx, row in df.iterrows():
print(f"第{idx + 1}行:{row_prompt}")
等价于 C++:
for (int i = 0; i < rows.size(); i++) {
cout << "第" << i+1 << "行:" << rows[i] << endl;
}
10.5 切片操作
语法: list[start:stop:step]
代码示例(codePython9.py 第 136 行):
context = "\n".join(self.history[-3:]) # 取最近3条历史记录
切片操作一览:
lst = [0, 1, 2, 3, 4, 5]
lst[1:4] # [1, 2, 3] —— 从索引1到3(不含4)
lst[:3] # [0, 1, 2] —— 从开头到索引2(不含3)
lst[::2] # [0, 2, 4] —— 步长为2
lst[::-1] # [5, 4, 3, 2, 1, 0] —— 反转列表
10.6 三元表达式(条件表达式)
语法: 值1 if 条件 else 值2
类似 C 的 条件 ? 值1 : 值2。
代码示例(codePython2.py 第 55 行):
return self.status not in ["hidden", "deleted"]
虽然没有直接使用三元表达式,但 Python 的 in / not in 运算符本身就是一个布尔表达式。
代码示例(codePython3.py 第 279 行):
return {"status": "error", "error": "无效Token,认证失败"} if token_input != VALID_TOKEN["token"] else ...
10.7 with 语句 —— 资源管理(类似 RAII)
语法:
with open("file.txt", "r") as f:
content = f.read()
# 离开 with 块时自动关闭文件
代码示例(codePython4.py 第 439 行):
with Image.open(self.image_path) as img:
img = img.resize((256, 256))
与 C++ RAII 对比:
- C++:在析构函数中释放资源
- Python:
with语句调用__enter__和__exit__魔术方法
10.8 join() —— 字符串拼接
语法: "分隔符".join(字符串列表)
代码示例(codePython9.py 第 136 行):
context = "\n".join(self.history[-3:]) # 用换行符拼接历史记录
等价于 C++:
std::string result;
for (const auto& s : history) {
result += s + "\n";
}
10.9 f-string —— 格式化字符串
Python 3.6+ 引入,类似 C 的 printf 但更强大。
语法: f"文本 {变量} 文本"
代码示例(codePython2.py 第 241 行):
print(f"[ERROR] 无效ID: {ctx_id}")
print(f"[WAIT] Prompt '{ctx.content[:20]}...' 被中断,等待恢复")
与 C/C++ 对比:
- C:
printf("x = %d", x); - C++:
std::cout << "x = " << x; - Python:
print(f"x = {x}")
10.10 in / not in —— 成员检查
语法: 元素 in 容器
代码示例(codePython2.py 第 55 行):
return self.status not in ["hidden", "deleted"]
代码示例(codePython9.py 第 309 行):
if any(word in msg for word in trigger_words):
return True
10.11 any() / all() —— 存在性/全称检查
any(iterable): 只要有一个元素为 True,就返回 True
all(iterable): 所有元素都为 True,才返回 True
代码示例(codePython9.py 第 309 行):
if any(word in msg for word in trigger_words):
# 如果 msg 中包含任意一个 trigger_words 中的词
return True
代码示例(codePython9.py 第 319 行):
return all(any(word in msg for word in key_words) for msg in messages)
# 对于 messages 中的每一条 msg,都包含至少一个 key_words 中的词
10.12 sorted() —— 排序
代码示例(codePython6.py 第 641-643 行):
active_blocks = sorted(
[b for b in blocks if b.condition_func(context)],
key=lambda b: b.priority # 按优先级排序
)
与 C++ 对比:
- C++:
std::sort(vec.begin(), vec.end(), cmp); - Python:
sorted(list, key=func)—— 更简洁
10.13 max() / min() —— 最大值/最小值
代码示例(codePython9.py 第 433 行):
new_emotion = max(emotion_score.items(), key=lambda x: x[1])[0]
# 在 emotion_score 字典中,找出值最大的键
11. 文件与 I/O
11.1 open() —— 打开文件
语法: open(path, mode, encoding)
代码示例(codePython4.py 第 702 行):
with open(file_path, "r", encoding="utf-8") as file:
raw_text = file.read()
常用模式:
| 模式 | 含义 | 类似 C |
|---|---|---|
"r" | 只读 | "r" |
"w" | 写入(覆盖) | "w" |
"a" | 追加 | "a" |
"rb" | 二进制读 | "rb" |
"wb" | 二进制写 | "wb" |
11.2 json 模块 —— JSON 序列化
json.dumps(obj): 将 Python 对象转为 JSON 字符串
json.loads(str): 将 JSON 字符串转为 Python 对象
代码示例(codePython2.py 第 195 行):
data = [p.to_dict() for p in chain]
return json.dumps(data, indent=2, ensure_ascii=False)
代码示例(codePython2.py 第 199 行):
data = json.loads(snapshot_json)
Python 与 JSON 类型映射:
| Python | JSON |
|---|---|
dict | {} |
list | [] |
str | "" |
int / float | 数字 |
True / False | true / false |
None | null |
11.3 os.path / os.makedirs —— 路径操作
代码示例(codePython7.py 第 397 行):
os.makedirs(LOG_DIR, exist_ok=True) # 创建目录,如果已存在也不报错
代码示例(codePython8.py 第 251 行):
if not os.path.exists(data.path):
return f"[错误] 文件不存在:{data.path}"
11.4 base64 编码
代码示例(codePython4.py 第 453 行):
encoded_str = base64.b64encode(image_data).decode("utf-8")
12. 并发编程:threading
12.1 threading.Thread —— 多线程
代码示例(codePython6.py 第 699-728 行):
import threading
import time
class TaskSession:
def __init__(self, task_id):
self.task_id = task_id
self.state = "初始化"
self.context = []
def update(self, user_input):
self.context.append(user_input)
self.state = f"处理中: {user_input}"
def finalize(self):
self.state = "已完成"
def run_task(task_id, messages):
session = TaskSession(task_id)
for msg in messages:
session.update(msg)
print(f"[{task_id}] 当前状态:{session.state}")
time.sleep(0.5)
session.finalize()
print(f"[{task_id}] 最终状态:{session.state}")
# 启动两个并发任务线程
t1 = threading.Thread(target=run_task, args=("任务A", ["查询天气", "查看气温"]))
t2 = threading.Thread(target=run_task, args=("任务B", ["读取邮件", "发送报告"]))
t1.start()
t2.start()
t1.join() # 等待 t1 完成
t2.join() # 等待 t2 完成
与 C++ pthread 对比:
| 特性 | C++ (pthread/std::thread) | Python threading |
|---|---|---|
| 创建线程 | std::thread t(func) | threading.Thread(target=func) |
| 启动 | 自动启动 | .start() |
| 等待 | .join() | .join() |
| 参数传递 | 构造函数参数 | args=() 元组 |
| 数据竞争 | 需要 mutex | 需要 Lock(GIL 提供部分保护) |
12.2 Python 的 GIL(全局解释器锁)
重要概念: Python 的多线程不能真正并行执行 CPU 密集型任务,因为 GIL 确保同一时刻只有一个线程执行 Python 字节码。
- I/O 密集型任务:多线程有效(如网络请求、文件读写)
- CPU 密集型任务:多线程无效,应使用
multiprocessing模块
13. 其他实用语法
13.1 isinstance() —— 类型检查
代码示例(codePython4.py 第 65 行):
if last_prompt["role"] == "user":
虽然没有直接使用 isinstance,但类似的类型检查在代码中很常见。
isinstance(obj, ClassName) # 检查 obj 是否是 ClassName 的实例
isinstance(obj, (A, B, C)) # 检查 obj 是否是 A、B、C 中任意一个的实例
13.2 copy.deepcopy() —— 深拷贝
代码示例(codePython7.py 第 366 行):
from copy import deepcopy
self._chain.append({"step": step_name, "data": deepcopy(data)})
浅拷贝 vs 深拷贝:
- 浅拷贝:只复制引用,不复制对象本身
- 深拷贝:递归复制所有对象
13.3 uuid.uuid4() —— 生成唯一ID
代码示例(codePython2.py 第 156 行):
import uuid
self.id = str(uuid.uuid4()) # 生成类似 "550e8400-e29b-41d4-a716-446655440000" 的字符串
13.4 time.sleep() —— 延时
代码示例(codePython2.py 第 249 行):
time.sleep(delay) # 暂停 delay 秒
13.5 logging 模块 —— 日志系统
代码示例(codePython5.py 第 39-46 行):
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s | %(levelname)s | %(message)s",
handlers=[
logging.FileHandler("mcp_debug.log", encoding="utf-8"),
logging.StreamHandler()
]
)
logging.info("准备调用工具 'add'")
logging.debug("详细调试信息")
logging.warning("警告信息")
logging.error("错误信息")
日志级别(从低到高): DEBUG < INFO < WARNING < ERROR < CRITICAL
13.6 hasattr() / getattr() —— 属性操作
hasattr(obj, "attr_name") # 检查对象是否有某个属性
getattr(obj, "attr_name") # 获取属性值
getattr(obj, "attr_name", default) # 获取属性值,不存在时返回默认值
13.7 str() / repr() —— 字符串表示
str(obj) # 面向用户的字符串表示(类似 C++ 的 operator<<)
repr(obj) # 面向开发者的字符串表示(调试用)
13.8 len() —— 获取长度
len(list) # 列表长度
len(str) # 字符串长度
len(dict) # 字典键值对数量
13.9 range() —— 生成数字序列
range(5) # 0, 1, 2, 3, 4
range(1, 5) # 1, 2, 3, 4
range(0, 10, 2) # 0, 2, 4, 6, 8
13.10 type() —— 获取类型
type(10) # <class 'int'>
type("hello") # <class 'str'>
type(obj) # <class '__main__.ClassName'>
13.11 dir() —— 列出对象属性和方法
dir(obj) # 返回对象所有属性和方法的列表
13.12 zip() —— 并行遍历
names = ["张三", "李四", "王五"]
ages = [28, 32, 26]
for name, age in zip(names, ages):
print(f"{name} 今年 {age} 岁")
13.13 map() / filter() —— 函数式编程
map(func, iterable) # 对每个元素应用函数
filter(func, iterable) # 过滤出满足条件的元素
13.14 集合操作
s = {1, 2, 3} # 集合定义
s.add(4) # 添加元素
s.remove(2) # 删除元素
{1, 2} | {2, 3} # 并集:{1, 2, 3}
{1, 2} & {2, 3} # 交集:{2}
{1, 2} - {2, 3} # 差集:{1}
14. 总结:Python 与 C/C++ 关键差异速查表
14.1 语法对照表
| 功能 | C/C++ | Python |
|---|---|---|
| 注释 | // 或 /* */ | # |
| 代码块 | {} | 缩进(4空格) |
| 行尾 | ; | 不需要(但可加) |
| 变量声明 | int x; | x = 0(动态类型) |
| 常量 | const int X = 10; | X = 10(约定大写,无强制) |
| 布尔值 | true / false | True / False |
| 空值 | NULL / nullptr | None |
| 逻辑运算符 | && ` | |
| 自增/自减 | ++i i-- | 不支持(用 i += 1) |
| switch-case | switch(x) { case 1: ... } | 不支持(用 if-elif-else) |
| do-while | do { ... } while(cond); | 不支持 |
| 三目运算符 | cond ? a : b | a if cond else b |
| 数组 | int arr[10]; | arr = [0] * 10(列表) |
| 字符串 | char* / std::string | str = "hello" |
| 结构体 | struct | @dataclass 或普通类 |
| 联合体 | union | 不支持 |
| 指针 | int* p = &x; | 没有指针(一切引用) |
| 引用 | int& r = x; | 所有变量都是引用语义 |
| new/delete | new / delete | 直接创建,自动垃圾回收 |
| 头文件 | #include | import |
| 宏定义 | #define | 常量或函数 |
| 模板 | template<T> | 动态类型(无需模板) |
| 命名空间 | namespace | 模块(文件名即命名空间) |
| 异常 | try/catch/throw | try/except/raise |
| 文件操作 | fopen/fclose | open() + with 语句 |
14.2 Python 特有、C/C++ 没有的概念
| 概念 | 说明 |
|---|---|
| 动态类型 | 变量类型在运行时确定,可随时改变 |
| 垃圾回收 | 自动内存管理(引用计数 + 分代回收) |
| 列表推导式 | [x**2 for x in range(10)] |
| 装饰器 | @decorator 修改函数行为 |
| 生成器 | yield 暂停/恢复函数 |
| 协程 | async/await 异步编程 |
| 魔术方法 | __init__, __str__ 等双下划线方法 |
| 一切皆对象 | 函数、类、模块都是对象 |
| GIL | 全局解释器锁,限制多线程并行 |
| with 语句 | 资源管理(类似 RAII) |
| f-string | f"Hello {name}" 字符串插值 |
14.3 C/C++ 特有、Python 没有的概念
| 概念 | 说明 |
|---|---|
| 指针 | Python 没有指针操作 |
| 手动内存管理 | Python 自动垃圾回收 |
| 编译时类型检查 | Python 运行时类型检查 |
| 宏定义 | Python 没有预处理器 |
| 头文件 | Python 用 import 替代 |
| switch-case | 用 if-elif-else 替代 |
| do-while | 用 while True + break 替代 |
| 运算符重载 | Python 通过魔术方法实现 |
| 模板/泛型 | Python 动态类型无需模板 |
| const 正确性 | Python 没有 const 关键字 |
| 位域 | Python 不支持 |
| union | Python 不支持 |
最后建议: 作为 C/C++ 开发者学习 Python,最大的挑战不是语法本身,而是思维方式的转变:
- 从”编译器帮我检查类型”到”运行时自己负责”
- 从”手动管理内存”到”信任垃圾回收器”
- 从”编译-链接-运行”到”解释执行”
- 从”花括号组织代码”到”缩进组织代码”
但好消息是:Python 的语法比 C++ 简单得多,学习曲线更平缓。你已有的编程思维(变量、循环、函数、类、异常处理等)全部可以迁移到 Python 中。