Python 语法简洁,但“看得懂”不等于理解它的运行方式。尤其是变量、赋值和对象,如果沿用其他语言中的直觉,很容易在可变参数、复制和并发代码里踩坑。
本文以 CPython 3.14 为基线,从名称绑定开始讲清基础类型、表达式和控制流。读者只需完成上一篇的解释器与虚拟环境准备。
1. 缩进是语法,不是装饰
Python 使用缩进划分代码块,不使用花括号:
| |
同一代码块必须保持一致缩进。工程中通常使用 4 个空格,不要混用 Tab 和空格。冒号表示即将开始一个代码块,常见于 if、for、while、def、class、try、with 和 match。
较长表达式应借助括号自然换行:
| |
不要依赖反斜杠拼接复杂表达式;括号内换行更稳健,也更容易被格式化工具处理。
2. 变量更准确地说是“名称”
在 Python 中,赋值把名称绑定到对象:
| |
这里没有复制列表。first 和 second 指向同一个对象,所以通过任一名称修改列表,都能从另一个名称观察到。
每个对象都有类型、标识和值:
| |
type(value)返回对象的类型;id(value)返回对象在当前生命周期内唯一的标识;is比较对象标识,==比较值是否相等。
因此,判断空值应写:
| |
不要用 is 比较普通数字或字符串。CPython 可能复用某些对象,但那是实现细节,不是业务语义。
3. 数值类型与除法
常用内置数值类型包括:
int:任意精度整数,大小主要受可用内存限制;float:通常对应平台的双精度二进制浮点数;complex:复数;bool:逻辑值,是int的子类,但业务代码应把它当布尔类型使用。
| |
// 是向负无穷方向取整,不是简单“截掉小数”:
| |
二进制浮点不能精确表示所有十进制小数:
| |
这不是 Python 独有问题。金额等需要确定十进制语义的场景可使用 decimal.Decimal,但必须从字符串构造,避免先引入浮点误差:
| |
4. 文本 str 与字节 bytes
Python 3 的 str 表示 Unicode 文本,bytes 表示 0 到 255 的字节序列。两者不能直接拼接:
| |
字符串是不可变对象。所谓“修改字符串”实际会创建新字符串并重新绑定名称:
| |
常用格式化方式是 f-string:
| |
输出为 product='sensor', price=12.35。格式说明符控制的是展示,不会改变原始数值。
Python 3.14 还新增了模板字符串字面量(t-string)。它使用类似 f-string 的语法,但结果不是 str,而是保留静态片段与插值信息的 string.templatelib.Template:
| |
t-string 供模板引擎、HTML 转义或领域专用处理器检查插值后再渲染,本身不会自动完成转义,也不能当普通字符串直接交给所有 API。普通展示继续使用 f-string;只有接收方明确支持 Template 时才使用 t-string。
处理文件和网络数据时,应该在系统边界明确编码:内部尽量使用 str,读写时显式使用 UTF-8。
5. None、布尔值与真值判断
None 表示缺少值,它不是空字符串、零或 False。函数没有显式 return 时会返回 None。
下列对象在布尔上下文中为假:
False和None;- 数值零;
- 空字符串和空容器;
- 自定义类型通过
__bool__()或__len__()定义的假值。
| |
但是“没有值”和“值恰好为零”可能代表不同业务状态:
| |
不要把这里写成 if not count,否则合法的 0 会被误判为缺失。
逻辑运算符 and 和 or 会短路,并返回参与运算的对象,不保证返回 bool:
| |
这个习惯写法适合“所有假值都等价”的场景;若空字符串和 None 含义不同,仍要显式判断。
6. 比较、成员检查与链式比较
| |
链式比较 18 <= age < 65 只求值中间表达式一次,语义接近 18 <= age and age < 65。不同类型通常不能随意排序,例如 1 < "2" 会抛出 TypeError,这能避免隐式转换掩盖数据问题。
7. if、for 与 while
Python 的 for 遍历可迭代对象,不是传统 C 风格计数循环:
| |
同时遍历多个序列可使用 zip():
| |
strict=True 会在序列长度不一致时抛出 ValueError,适合长度不一致代表数据错误的场景。
while 适合由状态而非固定集合驱动的循环:
| |
break 退出当前循环,continue 跳到下一轮。循环还支持 else:只有循环正常结束、没有被 break 打断时才执行。
| |
8. 结构化模式匹配
match/case 不是简单的 switch,它可以按数据结构解构对象:
| |
模式中的裸名称通常是捕获变量,不是与同名常量比较。需要匹配枚举或常量时,应使用限定名称,例如 Color.RED。简单条件继续使用 if 更清楚;只有当数据形状本身就是分支依据时,模式匹配才真正有价值。
9. 输入、转换与错误边界
input() 始终返回字符串:
| |
int() 遇到非法文本会抛出 ValueError,实际程序需要定义错误处理策略:
| |
不要使用 eval(input(...)) 解析用户输入。eval 会执行任意表达式,无法替代正常的格式解析与校验。
10. 小结
- Python 赋值是名称绑定,不会自动复制对象;
is比较标识,==比较值。 str是 Unicode 文本,bytes是字节;编码和解码应发生在系统边界。- 真值判断很方便,但不能混淆
None、零和空字符串的业务含义。 for面向可迭代对象,zip(strict=True)能主动发现长度错位。match适合按数据结构分支,不应机械替代if。
下一篇将学习列表、元组、字典和集合,并深入解释可变性、哈希与复制。