Skip to content

教学教程 —— 从零学会写汉语 Python ​

⬇ ChinesePython 教学教程 —— 下载 Word 版(.docx) 适合打印、发邮件、或发给不习惯看网页的人。内容与本页相同。

这本教程教你三件事:中文关键字怎么用(每个都给出对应的英文)、 原本那些符号怎么用(() [] {} : 一个没换)、 常用标准库怎么用(操作系统、JSON解析、正则、时间…)。

它只讲汉语化带来的差异与够用的基础,不替代 Python 教材。

本文件里的代码块 == 项目仓库 的真源码(逐字一致),期望输出 也是真跑出来的。 目前由 项目仓库 装配;若以后要像 Chinese++ 那样「由模板+例子生成 + 校验脚本真跑核对」, 需要新增 tools\\生成教学教程.py 与 tools\\校验教学教程.py(按 §12 要先拍板)。


怎么用这本教程 ​

  1. 先读「第 0 课」把跑法打通。
  2. 每课都有一份能直接跑的例子,放在 项目仓库。
  3. 例子开头的注释里写了它自己的期望输出 —— 你跑出来的应当一模一样。
  4. 汉语写法和英文写法可以混着写,同一行里混都行。学会汉语不等于扔掉英文。

第 0 课 准备:装、跑 ​

发行形态是绿色目录:python.exe + Lib\\ + Doc\\ + 启动.cmd。三种跑法:

powershell
# ① 双击 启动.cmd(进中文 REPL;退出用 退出() 或 Ctrl+Z 回车)
# ② 直接跑脚本
bin\\python.exe 你的脚本.py
# ③ 便携单文件(Release 附件)
ChinesePython.exe 你的脚本.py

一个最小程序长这样(第 1 课细讲):

python
打印("你好,世界")

报错显示层有三档(环境变量 CHINESEPYTHON_ERRORS):zh(默认,中文)/ en(100% 还原英文)/ both(中英并排,校对用);但 str(e)、e.args、type(e).__name__ 永远是英文, 第三方库、日志、except 判断都不受影响。

想知道手里这份是哪一份:python --build-info(全量改动文件的联合哈希 + python314.dll 实测 SHA-256 + 两仓 HEAD)。


(以下第 1~10 课由 项目仓库 装配;每课都附该例子的真源码与真输出。)


第 1 课 程序骨架 —— 一行中文 Python 的最小样子 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字(括号里是对应的英文): 本课可用名字:长度(len)、取类型(type)、字符串(str)、整数(int)

例子的真源码(项目仓库) ​

python
打印("你好,世界")                 # 打印 = print

定义 打招呼(名字):                 # 定义 = def
    返回 "你好," + 名字            # 返回 = return

打印(打招呼("汉语编程"))
打印("长度:", 长度([1, 2, 3]))     # 长度 = len
打印("类型:", 取类型(1).__name__, 取类型("甲").__name__)   # 取类型 = type

导入 操作系统 作为 操              # 导入 = import;作为 = as
打印("模块真名:", 操.__name__)      # 中文名模块的 __name__ 就是中文名

期望输出 ​

text
你好,世界
你好,汉语编程
长度: 3
类型: int str
模块真名: 操作系统

井号后面是注释,解释器不看

讲解 ​

打印 就是 print,圆括号、引号、注释(#)全是 Python 原样;定义/返回 是 def/return。中英可以混写:print(打招呼("甲")) 与 打印(打招呼("甲")) 等价。注意中文名模块的 __name__ 就是中文名(操作系统),不是 os。

练习 ​

① 打印一句自我介绍。② 定义 相加(甲, 乙) 并打印 相加(3, 4)。③ 把 定义 改成 def 再跑一遍,输出应当完全一样。


第 2 课 变量与类型 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:定义(def) 返回(return) 空值(None) 真值/假值(True/False) 打印(print) 本课可用名字:整数 浮点数 字符串 布尔 列表 字典 元组 集合 长度 取类型

例子的真源码(项目仓库) ​

python
甲 = 42                        # 整数 = int
乙 = 3.5                       # 浮点数 = float
丙 = "汉语"                    # 字符串 = str
丁 = 真值                      # 布尔 = bool(真值 = True、假值 = False)
空 = 空值                      # 空值 = None

打印(甲, 乙, 丙, 丁, 空)
打印("类型:", 取类型(甲).__name__, 取类型(乙).__name__, 取类型(丙).__name__, 取类型(丁).__name__, 取类型(空).__name__)

列表甲 = [3, 1, 2]             # 列表 = list
字典甲 = {"甲": 1, "乙": 2}     # 字典 = dict
元组甲 = (1, 2, 3)             # 元组 = tuple
集合甲 = {1, 2, 3}             # 集合 = set

打印(列表甲, 字典甲, 元组甲, 集合甲)
打印("取下标:", 列表甲[0], 元组甲[2], 字典甲["乙"])
打印("切片:", 列表甲[0:2])
打印("长度:", 长度(列表甲), 长度(字典甲))       # 长度 = len

# 类型转换(整数 = int、浮点数 = float、字符串 = str)
打印(整数("42") + 1, 浮点数("1.5"), 字符串(42) + "!")

# f-string:花括号里照样能写中文名字
打印(f"{丙}Python,{甲 + 1}")

# 常用方法:中文名与英文名指的是同一个方法
列表甲.追加(9)
列表甲.排序()
打印("追加并排序后:", 列表甲)
打印("切分:", "甲,乙,丙".切分(","))
打印("替换后:", "甲乙".替换("乙", "丙"))
打印("大写/去空白:", "汉字".转大写(), " 乙 ".去两端空白())

期望输出 ​

text
42 3.5 汉语 True None
类型: int float str bool NoneType
[3, 1, 2] {'甲': 1, '乙': 2} (1, 2, 3) {1, 2, 3}
取下标: 3 3 2
切片: [3, 1]
长度: 3 2
43 1.5 42!
汉语Python,43
追加并排序后: [1, 2, 3, 9]
切分: ['甲', '乙', '丙']
替换后: 甲丙
大写/去空白: 汉字 乙

讲解 ​

类型名只是别名:取类型(...).__name__ 打出来的仍是英文 int/str/list(这保证第三方库、isinstance 判断全不受影响)。f-string 的 {} 里照样能写中文名字。方法也是别名:追加 = append、切分 = split、替换 = replace。

练习 ​

① 把 3 个数字放进列表,用 求和 求总和。② 用 f-string 打印「我叫某某,今年几岁」。③ 让 " 甲,乙 ".去两端空白().切分(",") 得到 ['甲', '乙']。


第 3 课 运算与表达式 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字(有英文词形的才翻;纯符号的保持符号): 本课可用名字:打印 列表 求和(sum) 最大(max) 最小(min) 排序(sorted)

例子的真源码(项目仓库) ​

python
甲 = 7
乙 = 2

打印("加减乘:", 甲 + 乙, 甲 - 乙, 甲 * 乙)
打印("除与整除:", 甲 / 乙, 甲 // 乙)          # / 得浮点,// 是整除
打印("取余与乘方:", 甲 % 乙, 甲 ** 乙)         # % 取余、** 乘方

打印("比较:", 甲 > 乙, 甲 == 乙, 甲 != 乙)
打印("区间比较(可以连着写):", 1 < 乙 < 甲)

# 逻辑:并且 = and、或者 = or、并非 = not
打印("逻辑:", 真值 并且 并非 假值, 假值 或者 真值, 并非 假值)

# 属于 = in、等同 = is
列表甲 = [1, 2, 3]
打印("属于:", 2 属于 列表甲, 9 属于 列表甲)
打印("等同(是不是同一个对象):", 列表甲 等同 列表甲, [1] 等同 [1])

# 位运算只有符号、没有英文词形 ⇒ 不翻,保持符号
打印("位运算:", 6 & 3, 6 | 3, 6 ^ 3, 1 << 3)

# 聚合函数
打印("聚合:", 求和(列表甲), 最大(列表甲), 最小(列表甲), 排序(列表甲, 反向=真值))

期望输出 ​

text
加减乘: 9 5 14
除与整除: 3.5 3
取余与乘方: 1 49
比较: True False True
区间比较(可以连着写): True
逻辑: True True True
属于: True False
等同(是不是同一个对象): True False
位运算: 2 7 5 8
聚合: 6 3 1 [3, 2, 1]

讲解 ​

只有「有英文词形」的运算符才翻:并且/或者/并非/属于/等同。纯符号(+ - * / // % ** & | ^ << ==)保持符号。== 比的是值、等同(is) 比的是「是不是同一个对象」——这两件事别混。

练习 ​

① 判断一个数是不是偶数(用 %)。② 用 属于 判断某个字是否在字符串里。③ 比较 [1] == [1] 与 [1] 等同 [1] 的结果并解释。


第 4 课 分支与循环 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:如果(if) 否则如果(elif) 否则(else) 对于(for) 属于(in) 每当(while) 本课可用名字:范围(range) 编号(enumerate) 列表(list) 追加(list.append) 打印

例子的真源码(项目仓库) ​

python
分数 = 75

如果 分数 >= 60:                        # 如果 = if
    打印("及格")
否则如果 分数 > 100:                    # 否则如果 = elif
    打印("分数不合法")
否则:                                   # 否则 = else
    打印("不及格")

打印("—— 对于 循环 ——")
累加 = 0
对于 甲 属于 范围(1, 5):                 # 对于 = for;属于 = in;范围 = range
    累加 = 累加 + 甲
打印("1 到 4 的和:", 累加)

打印("—— 跳出 与 跳过 ——")
留下的 = []
对于 甲 属于 范围(10):
    如果 甲 == 5:
        跳出                            # 跳出 = break
    如果 甲 % 2 == 0:
        跳过                            # 跳过 = continue
    留下的.追加(甲)                      # 追加 = list.append
打印("留下的奇数:", 留下的)

打印("—— 每当 循环 ——")
遍 = 0
每当 遍 < 3:                            # 每当 = while
    遍 = 遍 + 1
打印("遍数:", 遍)

打印("—— 推导式 与 匿名函数 ——")
平方表 = [甲 * 甲 对于 甲 属于 范围(5)]
打印("平方表:", 平方表)
双倍 = 匿名函数 甲: 甲 * 2               # 匿名函数 = lambda
打印("映射:", [双倍(甲) 对于 甲 属于 范围(3)])
打印("带条件:", [甲 对于 甲 属于 范围(6) 如果 甲 % 2 == 1])

打印("—— 编号 与 匹配 ——")
对于 序号, 值 属于 编号(["甲", "乙"]):    # 编号 = enumerate
    打印(序号, 值)

匹配 2:                                  # 匹配 = match
    情形 1:                              # 情形 = case
        打印("一")
    情形 2:
        打印("二")
    情形 _:
        打印("其他")

期望输出 ​

text
及格
—— 对于 循环 ——
1 到 4 的和: 10
—— 跳出 与 跳过 ——
留下的奇数: [1, 3]
—— 每当 循环 ——
遍数: 3
—— 推导式 与 匿名函数 ——
平方表: [0, 1, 4, 9, 16]
映射: [0, 2, 4]
带条件: [1, 3, 5]
—— 编号 与 匹配 ——
0 甲
1 乙
二

讲解 ​

Python 用缩进当语法,没有大括号;如果/否则如果/否则 每个分支后面是冒号。推导式、编号(enumerate)、匹配/情形(match/case) 都能用中文写。

练习 ​

① 打印 1..20 里能被 3 整除的数。② 用 每当 求 1..100 的和。③ 用 匹配 给分数打等级(≥90 优 / ≥60 及格 / 否则 不及格)。


第 5 课 函数 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:定义(def) 返回(return) 匿名函数(lambda) 产出(yield) 全局(global) 空值(None) 本课可用名字:打印 长度 求和 排序 列表 范围 编号

例子的真源码(项目仓库) ​

python
定义 面积(宽, 高=1):                 # 定义 = def;默认参数照旧
    """算面积;三引号字符串就是文档字符串。"""
    返回 宽 * 高                    # 返回 = return

打印(面积(3), 面积(3, 4), 面积(高=2, 宽=5))    # 位置参数、默认值、关键字实参都能用

# 可变参数:名字随便起(中文也行),* 和 ** 还是符号
定义 全部相加(*数们):
    合计 = 0
    对于 项 属于 数们:
        合计 += 项
    返回 合计

定义 打招呼(**信息):
    返回 "你好," + 信息["名字"]

打印(全部相加(1, 2, 3), 打招呼(名字="甲"))

# 匿名函数 = lambda
双倍 = 匿名函数 甲: 甲 * 2
打印(排序([3, 1, 2], 键=双倍))

# 生成器:产出 = yield
定义 数到(上界):
    甲 = 1
    每当 甲 <= 上界:
        产出 甲                  # 产出 = yield
        甲 += 1
打印(列表(数到(4)))

# 全局 = global(函数里改模块级变量要用它)
计数 = 0
定义 加一():
    全局 计数                     # 不加这句,下面那行会创建局部变量
    计数 += 1

加一()
加一()
打印("计数 =", 计数)

期望输出 ​

text
3 12 10
6 你好,甲
[1, 2, 3]
[1, 2, 3, 4]
计数 = 2

讲解 ​

默认参数、关键字实参照旧;*数们、**信息 里的名字随便起(中文也行),* 与 ** 仍是符号。全局 = global(函数里改模块级变量必须写它)。产出 = yield,写生成器。

练习 ​

① 用递归写 阶乘(甲)。② 写一个用 **信息 收任意关键字的函数。③ 用 产出 写一个斐波那契生成器,取前 6 个。


第 6 课 自己定义类型(类) ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:类型(class) 定义(def) 返回(return) 超类(super) 打印(print) 本课可用名字:类型 取类型(type) 等同实例(isinstance)

例子的真源码(项目仓库) ​

python
类型 动物:
    """一个最小的类。"""

    定义 __init__(自身, 名, 叫声):      # __init__ 必须英文
        自身.名 = 名
        自身.叫声 = 叫声

    定义 叫(自身):
        返回 f"{自身.名}:{自身.叫声}"

    定义 __str__(自身):                  # __str__ 也必须英文
        返回 f"<动物 {自身.名}>"

类型 狗(动物):
    定义 __init__(自身, 名):
        超类(狗, 自身).__init__(名, "汪汪")     # 两参 超类 = super

    定义 握手(自身):
        返回 f"{自身.名} 伸出爪子"

甲 = 狗("旺财")
打印(甲.叫())
打印(甲.握手())
打印(甲)                                 # 打印对象会调 __str__
打印("是动物吗:", 等同实例(甲, 动物), "是狗吗:", 等同实例(甲, 狗))
打印("它的类型:", 取类型(甲).__name__, "父类:", 取类型(甲).__bases__[0].__name__)

期望输出 ​

text
旺财:汪汪
旺财 伸出爪子
<动物 旺财>
是动物吗: True 是狗吗: True
它的类型: 狗 父类: 动物

讲解 ​

类型 = class;魔术方法必须写英文(__init__/__str__)——C 层按字符串查找,翻了就不认。self 不是关键字,习惯写 自身。⚠ 零参 超类() 不行(它是编译器特例,靠 __class__ cell,别名救不了)⇒ 写 超类(类, 自身)。

练习 ​

① 给 动物 加一个 年龄 属性并在 __str__ 里打出来。② 写 猫(动物) 覆盖 叫。③ 用 等同实例 判断一个对象是不是 动物 的实例。


第 7 课 标准库(157 个汉语库;这里挑最常用的几个) ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:导入(import) 来自(import from) 作为(as) 打印(print) 本课可用名字:操作系统(os) JSON解析(json) 时间(time) 随机(random) 数学(math) 正则(re)

例子的真源码(项目仓库) ​

python
导入 操作系统
导入 JSON解析
导入 时间
导入 随机
导入 数学
导入 正则

# —— 操作系统 = os ——
打印("当前目录在吗:", 操作系统.路径.exists("."))     # os.path 整块保持英文
打印("路径分隔符:", 操作系统.分隔符)                 # os.sep 有中文名
打印("列目录非空:", 长度(操作系统.列出目录(".")) > 0)

# —— JSON解析 = json(转字符串 = dumps、读字符串 = loads)——
文本 = JSON解析.转字符串({"甲": 1, "乙": [2, 3]}, ensure_ascii=False)
打印("转成文本:", 文本)
打印("读回来的乙:", JSON解析.读字符串(文本)["乙"])

# —— 时间 = time(打印会变的值没法核对,所以只做判断与差值)——
起点 = 时间.时间戳()
时间.休眠(0.01)
打印("休眠确实过去了:", 时间.时间戳() > 起点)

# —— 随机 = random(先用英文 seed 固定住,输出才可核对)——
随机.seed(1)
打印("固定种子后的随机整数:", 随机.随机整数(1, 6))

# —— 数学 = math ——
打印("平方根:", 数学.平方根(9), "向上取整:", 数学.向上取整(1.2))

# —— 正则 = re(搜索 = search、替换 = sub)——
邮件 = "联系 a@x.com 或 b@y.com"
打印("第一个邮箱:", 正则.搜索(r"[\w.]+@[\w.]+", 邮件).group())
打印("打码后:", 正则.替换(r"[\w.]+@[\w.]+", "***", 邮件))

期望输出 ​

text
当前目录在吗: True
路径分隔符: \
列目录非空: True
转成文本: {"甲": 1, "乙": [2, 3]}
读回来的乙: [2, 3]
休眠确实过去了: True
固定种子后的随机整数: 2
平方根: 3.0 向上取整: 2
第一个邮箱: a@x.com
打码后: 联系 *** 或 ***

讲解 ​

157 个汉语库。操作系统 的中文成员很多(取当前目录/列出目录/分隔符),但 操作系统.路径 整块保持英文(exists/join/sep),这点教材如实说明。JSON解析 用 转字符串(dumps)/读字符串(loads);时间 用 时间戳/休眠;随机 想核对输出先 seed;正则 用 搜索(search)/替换(sub)。

练习 ​

① 列出当前目录并数出条目个数。② 把字典写成 JSON 文本再读回来(用 使用 ... 作为)。③ 用正则把一段文本里的所有数字替换成 #。


第 8 课 异常与报错 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:尝试(try) 捕获(except) 最终必须(finally) 抛出(raise) 作为(as) 略过(pass) 断言(assert) 本课可用名字:值错误(ValueError) 除零错误(ZeroDivisionError) 键错误(KeyError)

例子的真源码(项目仓库) ​

python
尝试:                                      # 尝试 = try
    甲 = 1 / 0
捕获 除零错误 作为 错:                      # 捕获 = except;作为 = as
    打印("屏幕上是中文,但对象里是英文:")
    打印("  str(错) =", str(错))
    打印("  类型名 =", 取类型(错).__name__)
最终必须:                                   # 最终必须 = finally
    打印("最终必须一定执行")

定义 转整数(文本):
    尝试:
        返回 整数(文本)
    捕获 值错误:                            # 值错误 = ValueError
        返回 空值

打印(转整数("42"), 转整数("不是数"))

类型 我的错误(值错误):                       # 自定义异常
    略过                                    # 略过 = pass

定义 检查(甲):
    如果 甲 < 0:
        抛出 我的错误("不能是负数")           # 抛出 = raise
    返回 甲

尝试:
    检查(-1)
捕获 值错误 作为 错:                        # 自定义异常是 值错误 的子类,能被它捕获
    打印("捕获到自定义异常:", 错)

尝试:
    断言 1 == 2, "这里应当失败"              # 断言 = assert
捕获 断言错误 作为 错:                       # 断言错误 = AssertionError
    打印("断言失败:", 错)

期望输出 ​

text
屏幕上是中文,但对象里是英文:
str(错) = division by zero
类型名 = ZeroDivisionError
最终必须一定执行
42 None
捕获到自定义异常: 不能是负数
断言失败: 这里应当失败

讲解 ​

尝试/捕获/最终必须/抛出 = try/except/finally/raise。异常类的中文名(除零错误/值错误/键错误)与英文类是同一个对象。中文只在显示层:str(错) 仍是英文,e.args 也是——这样日志、except 分支、第三方库都不受影响。自定义异常继承 值错误,就能被 捕获 值错误 接住。

练习 ​

① 写一个安全除法(捕获 除零错误)。② 自定义 余额不足错误(值错误) 并在取款函数里 抛出。③ 用 最终必须 保证文件一定被关闭。


第 9 课 文件与数据 ​

本课要点 / 关键字 / 可用名字 ​

本课关键字:使用(with) 作为(as) 导入(import) 尝试(try) 捕获(except) 打印(print) 本课可用名字:打开(open) 操作系统(os) JSON解析(json) 长度(len)

例子的真源码(项目仓库) ​

python
路径 = "教学_09_临时.txt"

# 使用 = with:块结束自动关闭文件
使用 打开(路径, "w", encoding="utf-8") 作为 文:      # 打开 = open
    文.write("甲\n乙\n丙\n")

使用 打开(路径, encoding="utf-8") 作为 文:
    行们 = 文.readlines()

打印("读到几行:", 长度(行们))
打印("去掉换行:", [行.strip() for 行 in 行们])

导入 操作系统
打印("文件在吗:", 操作系统.路径.exists(路径))
操作系统.remove(路径)
打印("删掉之后:", 操作系统.路径.exists(路径))

导入 JSON解析
数据 = {"名字": "旺财", "年龄": 3}
文本 = JSON解析.转字符串(数据, ensure_ascii=False)
使用 打开(路径, "w", encoding="utf-8") 作为 文:
    文.write(文本)
使用 打开(路径, encoding="utf-8") 作为 文:
    读回 = JSON解析.读字符串(文.read())
打印("存取一致:", 读回 == 数据)
操作系统.remove(路径)

期望输出 ​

text
读到几行: 3
去掉换行: ['甲', '乙', '丙']
文件在吗: True
删掉之后: False
存取一致: True

讲解 ​

使用 ... 作为 ... = with ... as ...,块结束自动关文件;打开 = open。⚠ 文件对象的方法名保持英文(write/read/close),os.path 也保持英文。读写 JSON 用 JSON解析.转字符串 / 读字符串。

练习 ​

① 写一个三行文件再读回来打印行数。② 把一个列表按行写进文件。③ 用 尝试/捕获 文件未找到错误 处理文件不存在的情况。


第 10 课 中英混写与排错 ​

本课要点 / 关键字 / 可用名字 ​

本课要点:① 中英混写(关键字/内置名/模块都行);② 中文内置名是「一等公民」(能当值传参); 本课可用名字:打印 取类型 排序 绝对值 字符串 最大 操作系统 os len

例子的真源码(项目仓库) ​

python
导入 os
导入 操作系统
打印("内置名同一个对象:", 取类型 == type, 打印 == print)
打印("模块成员同一个函数:", 操作系统.取当前目录 == os.getcwd, 操作系统.路径.exists == os.path.exists)

# —— ② 中文内置名是「一等公民」:能当值传出去 ——
打印("当排序的键:", 排序([3, -1, 2], 键=绝对值))
打印("当排序的键(按长度):", 排序(["甲甲", "乙"], 键=len))       # 长度 也行,这里用 len 演示混写
取出类型 = [打印, 取类型][1]
打印("从列表里拿出来用:", 取出类型(7).__name__)
打印("当作映射的函数:", 列表(映射(字符串.转大写, ["甲a", "乙b"])))

# ⚠ 但**导入 os 拿不到中文成员名**:中文名挂在「操作系统」这个中文壳上
打印("中文壳的模块名:", 操作系统.__name__, "英文模块的模块名:", os.__name__)

# —— ③ 关键字不能当标识符(下面两行取消注释就语法错)——
# 类型 = 1        # SyntaxError:类型 是 class 关键字
# 如果 = 2        # SyntaxError:如果 是 if 关键字
打印("上面两行被注释掉了,写出来会直接语法错")

# —— ④ 魔术方法必须英文 ——
类型 甲:
    定义 __init__(自身, 值):        # 不能写成「初始化」
        自身.值 = 值
    定义 __str__(自身):
        返回 f"值={自身.值}"
打印("打印对象会调 __str__:", 甲(7))

# —— ⑤ 报错显示层三档:这里演示默认档(zh);换档要设环境变量后新起进程 ——
尝试:
    1 / 0
捕获 除零错误 作为 错:
    打印("屏幕上是中文,对象里是英文:", str(错))
打印("想换档:把 CHINESEPYTHON_ERRORS 设成 en(完全还原)或 both(中英并排)再重跑")

# —— ⑥ 遮蔽演示:故意用本文件没出现过的名字(最大 = max),免得把上面的用法弄炸 ——
最大 = 99
打印("现在的 最大 是变量:", 最大)
# 规则:中文内置名和英文名共享同一个名字空间。本模块只要有**一处**赋值,这个名字在整个模块里
# 就是变量 —— 而且**顺序敏感**:把这一行挪到最前面,上面任何一次 最大(...) 都会报「名字错误」。
# (写这份教材时就踩过一次:把 长度 = 99 放在末尾,导致前面 键=长度 报「名字 '长度' 没有定义」。
#   这不是中文名没实现 —— 它们是真的全局名 —— 是 Python 自己的编译期规则。)

期望输出 ​

text
内置名同一个对象: True True
模块成员同一个函数: True True
当排序的键: [-1, 2, 3]
当排序的键(按长度): ['乙', '甲甲']
从列表里拿出来用: int
当作映射的函数: ['甲A', '乙B']
中文壳的模块名: 操作系统 英文模块的模块名: os
上面两行被注释掉了,写出来会直接语法错
打印对象会调 __str__: 值=7
屏幕上是中文,对象里是英文: division by zero
想换档:把 CHINESEPYTHON_ERRORS 设成 en(完全还原)或 both(中英并排)再重跑
现在的 最大 是变量: 99

—— ① 中英混写:关键字、内置名两边都对得上 ——

讲解 ​

① 关键字、内置名、模块都能混写;② 中文内置名是一等公民(能当值传参:排序(..., 键=绝对值));③ 中文关键字不能当标识符(类型 = 1 直接语法错);④ 中文成员名挂在中文模块壳上,导入 os 拿不到 取当前目录;⑤ 内置名的中文别名会被自己的变量遮蔽,而且顺序敏感(本模块只要有一处赋值,这个名字在整个模块里就是变量);⑥ 魔术方法必须英文;⑦ 报错三档 zh/en/both。

练习 ​

① 把第 1 课的例子改成全英文关键字,输出应当不变。② 找出至少一个「不是关键字、但也不该拿来当变量名」的中文名,并说明为什么。③ 用 CHINESEPYTHON_ERRORS=both 再跑第 8 课的例子,比较输出差异。


以 MIT / Apache-2.0 等宽松许可发布 · 联系作者 QQ:1396257961