教学教程 —— 从零学会写汉语 Python
⬇ ChinesePython 教学教程 —— 下载 Word 版(.docx) 适合打印、发邮件、或发给不习惯看网页的人。内容与本页相同。
这本教程教你三件事:中文关键字怎么用(每个都给出对应的英文)、 原本那些符号怎么用(
() [] {} :一个没换)、 常用标准库怎么用(操作系统、JSON解析、正则、时间…)。它只讲汉语化带来的差异与够用的基础,不替代 Python 教材。
本文件里的代码块 == 项目仓库 的真源码(逐字一致),
期望输出也是真跑出来的。 目前由 项目仓库 装配;若以后要像 Chinese++ 那样「由模板+例子生成 + 校验脚本真跑核对」, 需要新增tools\\生成教学教程.py与tools\\校验教学教程.py(按 §12 要先拍板)。
怎么用这本教程
- 先读「第 0 课」把跑法打通。
- 每课都有一份能直接跑的例子,放在 项目仓库。
- 例子开头的注释里写了它自己的期望输出 —— 你跑出来的应当一模一样。
- 汉语写法和英文写法可以混着写,同一行里混都行。学会汉语不等于扔掉英文。
第 0 课 准备:装、跑
发行形态是绿色目录:python.exe + Lib\\ + Doc\\ + 启动.cmd。三种跑法:
# ① 双击 启动.cmd(进中文 REPL;退出用 退出() 或 Ctrl+Z 回车)
# ② 直接跑脚本
bin\\python.exe 你的脚本.py
# ③ 便携单文件(Release 附件)
ChinesePython.exe 你的脚本.py一个最小程序长这样(第 1 课细讲):
打印("你好,世界")报错显示层有三档(环境变量 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)
例子的真源码(项目仓库)
打印("你好,世界") # 打印 = print
定义 打招呼(名字): # 定义 = def
返回 "你好," + 名字 # 返回 = return
打印(打招呼("汉语编程"))
打印("长度:", 长度([1, 2, 3])) # 长度 = len
打印("类型:", 取类型(1).__name__, 取类型("甲").__name__) # 取类型 = type
导入 操作系统 作为 操 # 导入 = import;作为 = as
打印("模块真名:", 操.__name__) # 中文名模块的 __name__ 就是中文名期望输出
你好,世界
你好,汉语编程
长度: 3
类型: int str
模块真名: 操作系统
井号后面是注释,解释器不看讲解
打印 就是 print,圆括号、引号、注释(#)全是 Python 原样;定义/返回 是 def/return。中英可以混写:print(打招呼("甲")) 与 打印(打招呼("甲")) 等价。注意中文名模块的 __name__ 就是中文名(操作系统),不是 os。
练习
① 打印一句自我介绍。② 定义 相加(甲, 乙) 并打印 相加(3, 4)。③ 把 定义 改成 def 再跑一遍,输出应当完全一样。
第 2 课 变量与类型
本课要点 / 关键字 / 可用名字
本课关键字:定义(def) 返回(return) 空值(None) 真值/假值(True/False) 打印(print) 本课可用名字:整数 浮点数 字符串 布尔 列表 字典 元组 集合 长度 取类型
例子的真源码(项目仓库)
甲 = 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)
列表甲.排序()
打印("追加并排序后:", 列表甲)
打印("切分:", "甲,乙,丙".切分(","))
打印("替换后:", "甲乙".替换("乙", "丙"))
打印("大写/去空白:", "汉字".转大写(), " 乙 ".去两端空白())期望输出
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)
例子的真源码(项目仓库)
甲 = 7
乙 = 2
打印("加减乘:", 甲 + 乙, 甲 - 乙, 甲 * 乙)
打印("除与整除:", 甲 / 乙, 甲 // 乙) # / 得浮点,// 是整除
打印("取余与乘方:", 甲 % 乙, 甲 ** 乙) # % 取余、** 乘方
打印("比较:", 甲 > 乙, 甲 == 乙, 甲 != 乙)
打印("区间比较(可以连着写):", 1 < 乙 < 甲)
# 逻辑:并且 = and、或者 = or、并非 = not
打印("逻辑:", 真值 并且 并非 假值, 假值 或者 真值, 并非 假值)
# 属于 = in、等同 = is
列表甲 = [1, 2, 3]
打印("属于:", 2 属于 列表甲, 9 属于 列表甲)
打印("等同(是不是同一个对象):", 列表甲 等同 列表甲, [1] 等同 [1])
# 位运算只有符号、没有英文词形 ⇒ 不翻,保持符号
打印("位运算:", 6 & 3, 6 | 3, 6 ^ 3, 1 << 3)
# 聚合函数
打印("聚合:", 求和(列表甲), 最大(列表甲), 最小(列表甲), 排序(列表甲, 反向=真值))期望输出
加减乘: 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) 打印
例子的真源码(项目仓库)
分数 = 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:
打印("二")
情形 _:
打印("其他")期望输出
及格
—— 对于 循环 ——
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) 本课可用名字:打印 长度 求和 排序 列表 范围 编号
例子的真源码(项目仓库)
定义 面积(宽, 高=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
加一()
加一()
打印("计数 =", 计数)期望输出
3 12 10
6 你好,甲
[1, 2, 3]
[1, 2, 3, 4]
计数 = 2讲解
默认参数、关键字实参照旧;*数们、**信息 里的名字随便起(中文也行),* 与 ** 仍是符号。全局 = global(函数里改模块级变量必须写它)。产出 = yield,写生成器。
练习
① 用递归写 阶乘(甲)。② 写一个用 **信息 收任意关键字的函数。③ 用 产出 写一个斐波那契生成器,取前 6 个。
第 6 课 自己定义类型(类)
本课要点 / 关键字 / 可用名字
本课关键字:类型(class) 定义(def) 返回(return) 超类(super) 打印(print) 本课可用名字:类型 取类型(type) 等同实例(isinstance)
例子的真源码(项目仓库)
类型 动物:
"""一个最小的类。"""
定义 __init__(自身, 名, 叫声): # __init__ 必须英文
自身.名 = 名
自身.叫声 = 叫声
定义 叫(自身):
返回 f"{自身.名}:{自身.叫声}"
定义 __str__(自身): # __str__ 也必须英文
返回 f"<动物 {自身.名}>"
类型 狗(动物):
定义 __init__(自身, 名):
超类(狗, 自身).__init__(名, "汪汪") # 两参 超类 = super
定义 握手(自身):
返回 f"{自身.名} 伸出爪子"
甲 = 狗("旺财")
打印(甲.叫())
打印(甲.握手())
打印(甲) # 打印对象会调 __str__
打印("是动物吗:", 等同实例(甲, 动物), "是狗吗:", 等同实例(甲, 狗))
打印("它的类型:", 取类型(甲).__name__, "父类:", 取类型(甲).__bases__[0].__name__)期望输出
旺财:汪汪
旺财 伸出爪子
<动物 旺财>
是动物吗: True 是狗吗: True
它的类型: 狗 父类: 动物讲解
类型 = class;魔术方法必须写英文(__init__/__str__)——C 层按字符串查找,翻了就不认。self 不是关键字,习惯写 自身。⚠ 零参 超类() 不行(它是编译器特例,靠 __class__ cell,别名救不了)⇒ 写 超类(类, 自身)。
练习
① 给 动物 加一个 年龄 属性并在 __str__ 里打出来。② 写 猫(动物) 覆盖 叫。③ 用 等同实例 判断一个对象是不是 动物 的实例。
第 7 课 标准库(157 个汉语库;这里挑最常用的几个)
本课要点 / 关键字 / 可用名字
本课关键字:导入(import) 来自(import from) 作为(as) 打印(print) 本课可用名字:操作系统(os) JSON解析(json) 时间(time) 随机(random) 数学(math) 正则(re)
例子的真源码(项目仓库)
导入 操作系统
导入 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.]+", "***", 邮件))期望输出
当前目录在吗: 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)
例子的真源码(项目仓库)
尝试: # 尝试 = try
甲 = 1 / 0
捕获 除零错误 作为 错: # 捕获 = except;作为 = as
打印("屏幕上是中文,但对象里是英文:")
打印(" str(错) =", str(错))
打印(" 类型名 =", 取类型(错).__name__)
最终必须: # 最终必须 = finally
打印("最终必须一定执行")
定义 转整数(文本):
尝试:
返回 整数(文本)
捕获 值错误: # 值错误 = ValueError
返回 空值
打印(转整数("42"), 转整数("不是数"))
类型 我的错误(值错误): # 自定义异常
略过 # 略过 = pass
定义 检查(甲):
如果 甲 < 0:
抛出 我的错误("不能是负数") # 抛出 = raise
返回 甲
尝试:
检查(-1)
捕获 值错误 作为 错: # 自定义异常是 值错误 的子类,能被它捕获
打印("捕获到自定义异常:", 错)
尝试:
断言 1 == 2, "这里应当失败" # 断言 = assert
捕获 断言错误 作为 错: # 断言错误 = AssertionError
打印("断言失败:", 错)期望输出
屏幕上是中文,但对象里是英文:
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)
例子的真源码(项目仓库)
路径 = "教学_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(路径)期望输出
读到几行: 3
去掉换行: ['甲', '乙', '丙']
文件在吗: True
删掉之后: False
存取一致: True讲解
使用 ... 作为 ... = with ... as ...,块结束自动关文件;打开 = open。⚠ 文件对象的方法名保持英文(write/read/close),os.path 也保持英文。读写 JSON 用 JSON解析.转字符串 / 读字符串。
练习
① 写一个三行文件再读回来打印行数。② 把一个列表按行写进文件。③ 用 尝试/捕获 文件未找到错误 处理文件不存在的情况。
第 10 课 中英混写与排错
本课要点 / 关键字 / 可用名字
本课要点:① 中英混写(关键字/内置名/模块都行);② 中文内置名是「一等公民」(能当值传参); 本课可用名字:打印 取类型 排序 绝对值 字符串 最大 操作系统 os len
例子的真源码(项目仓库)
导入 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 自己的编译期规则。)期望输出
内置名同一个对象: 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 课的例子,比较输出差异。