Course Builder个人学习工作台 · 本地模式
Modern Python:面向有经验开发者的回归路线

名字、值、字符串与控制流

目标:能够用 Python 的“名字绑定到对象”模型解释赋值、条件和循环,并写出一个可测试的文本分类函数。

来自 C++、Rust 或 Go 时,很容易把 Python 变量想成带固定存储槽和编译期类型的盒子。更准确的模型是:名字在某个作用域中绑定到对象。对象有类型和值;名字可以在之后绑定到另一个对象。

count = 3          # 名字 count 绑定到 int 对象
count = "three"    # 同一个名字改为绑定 str 对象

这不代表“对象的类型变了”。整数 3 仍然是整数,只是 count 不再指向它。类型标注能让静态检查器警告这种变化,但默认运行时不会阻止。

Python 的 if 不要求显式布尔类型,而是调用 truth-value 规则:零、空容器、空字符串和 None 通常为假。工程代码里要区分“为空”和“缺失”:if text 会同时把 "" 当作假,而 if text is None 只判断缺失。

完整示例:分类一条文本请求

保存为 text_rules.py:

from __future__ import annotations


def classify(text: str, urgent: bool = False) -> str:
    cleaned = text.strip()
    if not cleaned:
        return "empty"
    if urgent or "退款" in cleaned:
        return "high"
    if len(cleaned) >= 20:
        return "normal"
    return "low"


def describe(text: str, urgent: bool = False) -> str:
    level = classify(text, urgent)
    return f"{text=!r} -> level={level}"


if __name__ == "__main__":
    samples = ["", "请退款", "这是一条长度超过二十个字符的普通客户消息,用来测试分类"]
    for index, sample in enumerate(samples, start=1):
        print(f"{index}. {describe(sample)}")

运行:

uv run python text_rules.py

预期输出:

1. text='' -> level=empty
2. text='请退款' -> level=high
3. text='这是一条长度超过二十个字符的普通客户消息,用来测试分类' -> level=normal

这里有几项现代而常用的写法:

  • f-string 的 {text=!r} 同时打印表达式名和 repr,便于看见空格与空字符串。
  • enumerate(..., start=1) 直接生成序号和值,避免手动维护索引。
  • 先处理特殊情况并 return,减少深层 elif 嵌套。
  • in 对字符串做子串测试;它表达的是业务规则,不是正则表达式。

和 Go/Rust 的关键差异

Python 的缩进是语法,不使用花括号;for 直接消费 iterable,而不是只提供 C 风格计数循环。range(3) 产生 0, 1, 2,右端不包含。条件表达式写成 a if condition else b,阅读顺序和 C 的 condition ? a : b 不同。

引导实验:找出过宽的 truthiness

把 classify 的签名暂时改成 text: str | None,然后在函数第一行写:

if not text:
    return "empty"

分别调用 classify(None) 与 classify("")。两者都得到 empty。如果业务需要区分“字段没有提供”和“提供了空文本”,应改成:

if text is None:
    return "missing"
cleaned = text.strip()
if not cleaned:
    return "empty"

这就是条件写法背后的决策:先问业务状态是否需要区分,再选择 truthiness 或显式比较。

独立练习

扩展 classify:

  • None 返回 missing;
  • 仅空白返回 empty;
  • 包含“退款”或 urgent=True 返回 high;
  • 其他文本按长度分类。

验收断言:

assert classify(None) == "missing"
assert classify("   ") == "empty"
assert classify("我要退款") == "high"
assert classify("短消息") == "low"
参考答案
def classify(text: str | None, urgent: bool = False) -> str:
    if text is None:
        return "missing"
    cleaned = text.strip()
    if not cleaned:
        return "empty"
    if urgent or "退款" in cleaned:
        return "high"
    return "normal" if len(cleaned) >= 20 else "low"

排错路线

  • f-string 看不到首尾空格:使用 !r,不要只打印字符串本身。
  • 长度边界和预期差一:把 len(cleaned) 打印出来,确认是否先 strip()。
  • None 上出现 AttributeError:说明 .strip() 发生在缺失检查之前。

参考资料