中文关键字表
35 个硬关键字 + 4 个软关键字(3 译 + 1 不译),与英文关键字并列,不是替换。
〇、两条铁律
铁律一:只翻译**有「英文词形」**的东西
这条规则同时界定了「译什么」和「不译什么」:
| 类别 | 例子 | 有英文词形? | 译不译 |
|---|---|---|---|
| 语言关键字 | if def class return | 有(本身是英文词) | ✅ 译 |
| 有词形的运算符 | and or not in is | 有 | ✅ 译(而它们恰好全是关键字) |
| 只有符号的运算符 | == != < + & = -> @ | 没有 | ❌ 不译,保持符号 |
| 魔术方法 | __init__ __str__ | 有 | ❌ 不能译(C 层按字符串硬编码查找,见第七节) |
| 模块名 | os sys json | 有 | ❌ 不能译(是文件系统路径) |
铁律二:一个中文词只服务一个英文概念
反例(都被否掉):
最终同时服务final(禁止重写)和finally(必执行)→ 假朋友等同若同时服务is(身份)和==(值)→ 同样的问题
正解是加限定造新词:最终 = final,最终必须 = finally。英语自己就是这么干的(final : finally)。
原理一句话
关键字识别全树只有一处 —— Parser/pegen.c 的 _get_keyword_or_name_type()。中文表挂在它前面,命中后立即把中文换成对应的英文短串,再走完全没被改动的英文原表。
"if" ──→ 英文原表 ────────────────→ 682 ─┐
├─→ 同一个 token,parser 分不出区别
"如果" ──→ 中文表 ──→ "if" ──→ 英文原表 ──→ 682 ─┘所以中英并存不是额外设计的功能,而是「挂在原表旁边」这个做法的必然结果。
一、硬关键字(35 个)
图例:同 = 与 Chinese++ 既定译法逐字一致 | 派 = 从 Chinese++ 某译法派生 | 新 = Python 特有,全新定
控制流
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
if | 如果 | 条件为真则执行下面的块 | 同 |
elif | 否则如果 | 上一分支不成立时再判断一个新条件,可连续多个 | 新 |
else | 否则 | 前面所有分支都不成立时执行。除 if 外还挂在 for/while/try 上:循环正常跑完(没被 跳出)或没抛异常时执行 | 同 |
while | 每当 | 条件为真就反复执行 | 同 |
for | 对于 | 遍历一个可迭代对象 | 同 |
break | 跳出 | 立即跳出最近一层循环 | 同 |
continue | 跳过 | 跳过本轮剩余部分,直接进下一轮 | 同 |
定义与作用域
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
class | 类型 | 定义一个类 | 同 |
def | 定义 | 定义一个函数或方法 | 新 |
lambda | 匿名函数 | 没有名字的一次性函数表达式 | 新 |
return | 返回 | 从函数返回值;不写值就是返回 空值 | 同 |
yield | 产出 | 从生成器产出一个值并挂起,下次从这里继续。它本身是表达式,可以接收 send() 进来的值 | 派(协程产出) |
pass | 略过 | 空语句,什么都不做——因为 Python 的块不能为空,需要占位 | 新 |
del | 删除 | 删除一个名字、一个属性、或一个下标项 | 同 |
assert | 断言 | 断言为假就抛 AssertionError;-O 优化模式下整条被去掉,所以别用它做检查 | 派(#断言) |
global | 全局 | 声明这个名字指的是模块级变量,不是本函数的局部变量 | 新 |
nonlocal | 非局部 | 声明这个名字指的是外层函数里的变量(闭包,不是模块级) | 新 |
异常
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
try | 尝试 | 开始一段受保护代码,后面必须跟 捕获 或 最终必须 | 同 |
except | 捕获 | 捕获指定类型的异常并处理 | 派(catch) |
finally | 最终必须 | 不管有没有抛异常都执行 | 新 |
raise | 抛出 | 主动抛异常。单独写 抛出 是重抛当前异常 | 同 |
导入与上下文
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
import | 导入 | 导入一个模块 | 同 |
from | 来自 | 配合 导入 从模块里取指定名字:来自 x 导入 y | 新 |
as | 作为 | 三个位置都用它:导入 x 作为 y、使用 x 作为 y、捕获 E 作为 e | 新 |
with | 使用 | 上下文管理器:进入时调 __enter__,离开时(含异常路径)保证调 __exit__ | 新 |
布尔、空、逻辑、比较
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
True | 真值 | 布尔真 | 同 |
False | 假值 | 布尔假 | 同 |
None | 空值 | "什么都没有"的单例。它不等于 假值(但条件里算假) | 派(空指针) |
and | 并且 | 逻辑与,短路;返回的是操作数本身而不是布尔 | 同 |
or | 或者 | 逻辑或,短路,同上 | 同 |
not | 并非 | 逻辑非 | 同 |
in | 属于 | 两个位置:成员测试 x 属于 y;迭代 对于 x 属于 y | 新 |
is | 等同 | 判断两个引用是不是同一个对象。is not 语法上是两个词(等同 并非) | 新 |
上面这 5 个(
andornotinis)就是 Python 里仅有的带英文词形的运算符, 而它们恰好全是关键字,所以并行拼写在这里一次做齐 —— 不需要单独的运算符层。
异步
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
async | 异步 | 前缀,只用在三处:异步 定义、异步 对于、异步 使用 | 新 |
await | 等待 | 在协程里挂起,等一个可等待对象完成再继续 | 派(协程等待) |
二、软关键字(4 个:3 译 + 1 不译)
软关键字和硬关键字根本不同:它们不随处生效,只在特定上下文里被当作关键字,别的位置仍是普通标识符。所以它们不占标识符空间。
| 英文 | 汉语 | 功能描述 | 依据 |
|---|---|---|---|
match | 匹配 | 开启结构化模式匹配块:匹配 x:。只在语句开头生效 | 新 |
case | 情形 | 匹配 块里的一个分支:情形 [1, 2]:。只在 匹配 块内生效 | 同 |
type | 类型别名 | 声明类型别名:类型别名 向量 = 列表[浮点]。只在语句开头生效 | 同(typedef) |
_ | 不译 | 匹配 块里的通配符模式。它是单字符符号不是词,翻译会破坏「至少两汉字」定则 | — |
实测它们仍然是软的:
匹配 = 42 情形 = 变量 类型别名 = 也是变量 ← 都仍是普通标识符三、关键决定的理由(留痕)
class → 类型,不用 类
沿用 Chinese++ 的既定译法。且「至少两个汉字」定则本来就排除单字 类。
def → 定义,不用 函数 也不用 定义函数
def 是 define,不是 function,所以 函数 从语义上就错。 定义 在 Python 里没有歧义——def 只能定义函数和方法。定义函数 是「准确直译 + 冗余补充」,而函数定义是最高频的语句,每次多打两字不划算。
finally → 最终必须,绝不用裸的 最终
三条理由,最终必须 全部解决:
| 理由 | 裸 最终 | 最终必须 |
|---|---|---|
| 假朋友:同一个词服务两个不相关的英文概念 | ✗ | ✅ 是另一个词 |
最终 必须留给 final —— Python 3.8+ 真有 typing.final(3.12+ 还有 typing.override) | ✗ 被占用 | ✅ 最终 完好无损 |
Chinese++ 已经占用 最终 = final | ✗ 两项目打架 | ✅ 各占各的 |
关键区别是「同词两义」vs「同词根两词」。 英语自己就是这么干的:final : finally :: 最终 : 最终必须。
elif → 否则如果
if 已经是 如果,elif = "else if" 最自然的构造就是 否则 + 如果。 备选 否则若 被否掉:若 是文言词素、全表别处都不出现,语域和 如果/否则/每当/对于 不统一。
is → 等同
is 不是系动词,是一个运算 —— 它执行一次身份比较并返回布尔。所以中文该用动作谓词,不是 就是 / 正是 / 即是 这类静态系动词。
语言学依据是一对字的语义分工:
| 字 | 义 | 比的是 |
|---|---|---|
等 | 相等、同等、等级 | 量 |
同 | 相同、同一个、同一 | 物 |
等同 不说成 等于,而 == 保持符号,于是分工一眼可见:
列表甲 == 列表乙 # 符号 = 值比较
列表甲 等同 列表乙 # 中文词 = 身份比较中文词 vs 符号,比 等于/等同 一字之差清楚得多。
not → 并非
并非 是中文逻辑学的标准否定(「并非 P」),中性判断否定。 并不 是对比副词(他并不笨=言下之意「别以为他笨」),not 没有那层「出乎意料」的语气。 且 Chinese++ 已经用 并非 = not = !。
全部译名都有一个共同特质:有标记性
关键字应该在句子里一眼看得出「这是语法,不是内容」。为此排除了一批「无标记」候选:
| 定稿 | 被排除的无标记候选 |
|---|---|
每当 | 当 |
并非 | 不 |
真值/假值 | 真/假 |
类型 | 类 |
等同 | 就是 ← 「就」是汉语里义项最多的虚词之一 |
四、与 Chinese++ 对拍
| 数量 | |
|---|---|
| 硬关键字 | 35 |
| 逐字一致 | 17 |
| 派生 | 6 |
| Python 全新定 | 12 |
| 软关键字 | 3 译 + 1 不译(其中 2 个逐字一致) |
| 符号运算符 | 0 个译文(Python 没有 alternative tokens,见铁律一) |
逐字一致(17):如果、否则、每当、对于、跳出、跳过、类型、返回、删除、导入、 真值、假值、并且、或者、并非、尝试、抛出 派生(6):否则如果(构词)、产出←协程产出、断言←#断言、捕获←catch、 空值←空指针、等待←协程等待 全新(12):定义、匿名函数、略过、全局、非局部、最终必须、 来自、作为、使用、属于、等同、异步
为什么 Chinese++ 的运算符表在 Python 上是空的
C++ 标准给了 11 个 alternative tokens,它们是英文单词:
and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq所以 Chinese++ 译了它们(并且 与赋值 位与 位或 取反 并非不等于 或者 或赋值 异或 异或赋值)—— 一个不多一个不少。
Python 没有 alternative tokens。 所以同一套原则在 Python 上产出的符号运算符译文是 0 个。 这不是两个项目不一致,而是同一原则在两种语言上的正确应用。