读懂别人的类 —— 看懂库文档和源码片段的能力
普通课约 55 分钟
本课导读
摊开真相:你未来 90% 的面向对象时间不是写类,而是读类——读 pandas 文档决定怎么调用,读 AI 生成的类代码决定敢不敢用,读开源片段搞懂示例在干什么。本课就练这一件事:拿标准库的真实类当标本,建立一套"陌生类三问"的阅读框架,再配上 dir()/help() 两件自助探索工具。这是本单元最实用的一课。预计 55 分钟。
陌生类三问
拿到任何一个没见过的类,只需要回答三个问题:
- 怎么造?——构造函数(
__init__)收什么参数 - 它有什么?——属性(名词:它身上存着的数据)
- 它会什么?——方法(动词:它能执行的动作,各返回什么)
就这三问。文档再长、源码再花哨,都是在回答它们。下面用一个你只打过照面的标准库类实练:datetime.date。
标本解剖:datetime.date
几个阅读要领,全部来自前三课的知识:
- 属性不带括号、方法带括号——
d.year是读数据,d.weekday()是干活。看别人代码时,这个括号就是"名词/动词"的分界线 d.replace(month=12)返回新对象而不是改自己——注意方法的两种脾气:改自己(如列表的.sort(),返回 None)vs 交新的(如sorted()、这里的.replace())。读文档时看清返回值,就不会踩"接了个 None"的坑print(d)输出漂亮 → 它实现了__str__。你上上课刚写过同款
再看一个"不用造对象也能调"的特例:
date.today() 点在类名上而不是对象上——这类"从类直接调用、帮你造对象"的方法叫类方法,本质是官方给的便捷出厂通道。见到 类名.方法() 的姿势不必慌:它通常就是个特殊的工厂入口。
自助探索:dir() 和 help()
没有文档在手边?两件工具让类自己交代:
dir(对象)吐出全部成员名单——配合推导式过滤掉__家族,剩下的就是"它有什么 + 它会什么"的速览help(对象.方法)打印那个方法的 docstring——上上课让你给函数写 docstring,回报在这一刻兑现:你写的说明,也会这样服务未来的读者
提示
实战工作流:拿到陌生对象 → type(它) 看是什么类 → dir(它) 扫一眼成员 → 对感兴趣的成员 help() 细看。这三板斧在任何 Python 环境都好使,包括你将来在 Jupyter 里对着一个不认识的 DataFrame 时。
读文档:把三问映射到页面上
真实文档(比如 Python 官方文档、将来的 pandas 文档)的结构,恰好就是三问的答案:
- 类签名:
class date(year, month, day)——怎么造(参数表 + 哪些有默认值) - Attributes/属性区:
year、month、day——它有什么 - Methods/方法区:
weekday()、replace(...)、每条后面跟着返回什么 ——它会什么
读文档的正确姿势不是从头精读,而是带着三问跳读:先看签名知道怎么造,再扫方法区找你要的动词,最后确认返回值类型。五分钟能定位,就不要读半小时。
实战:读一段"别人写的"源码
下面是一段你从没见过的类(模拟你在开源项目 / AI 回答里遇到的场景)。先别运行,用三问读懂它,回答:① 造一个要传什么 ② 它有哪些属性 ③ hit() 返回什么、什么时候返回 False。然后再运行验证。
✅ 对照三问答案
① 造:RateLimiter(name, max_calls=3)——name 必填,配额默认 3。② 有:name、max_calls、used 三个属性(全在 __init__ 里声明,规范)。③ hit() 返回布尔值:配额没用完返回 True 并记一次,用完了返回 False(注意它是"先检查后计数"——卫语句的味道)。另外 __str__ 让 print 直接出状态——所以循环里能直接打印 api。
这套"三问 + 看返回值 + 认钩子"的读法,就是你以后读一切库代码的模板。
说明
AI 时代的用法:让 AI 帮你写了一个类之后,用三问审它——怎么造、有什么、会什么、每个方法返回什么。三问答不顺(比如属性没在 __init__ 声明齐、方法命名看不出动词),就让它重写。三问是你的验收清单。
✍️ 练习
练习 1:三板斧探索字符串
用 type()、dir()、help() 三板斧探索一个字符串对象:打印它的类型;列出所有不带下划线的方法里以 "is" 开头的(这批方法都是"判断题");再用 help 看看 isdigit 是干嘛的,最后试用它。
✅ 参考答案
s = "12345"
print(type(s))
checks = [m for m in dir(s) if m.startswith("is")]
print(checks)
help(s.isdigit)
print(s.isdigit()) # True:全是数字字符
print("12a".isdigit()) # False
isdigit 正是上单元"验证用户输入"场景的预防式工具——三板斧不但能读懂类,还经常顺手挖到宝。
练习 2:文档式阅读
下面是某个类的"文档摘要"(只有签名和方法说明,没有源码)。据此写代码:造一个 8:30 的闹钟,推迟两次,打印最终时间。
class Alarm(hour, minute=0)
闹钟。hour 为 24 小时制。
属性
hour, minute
方法
snooze(minutes=10) -> None 推迟 minutes 分钟(就地修改,不返回新对象)
display() -> str 返回 "HH:MM" 格式的时间字符串
✅ 参考答案
class Alarm: # (Playground 里已有,答案自带一份方便对照)
def __init__(self, hour, minute=0):
self.hour = hour
self.minute = minute
def snooze(self, minutes=10):
total = self.hour * 60 + self.minute + minutes
self.hour = (total // 60) % 24
self.minute = total % 60
def display(self):
return f"{self.hour:02d}:{self.minute:02d}"
alarm = Alarm(8, minute=30)
alarm.snooze() # 文档说默认 10 分钟
alarm.snooze(25)
print(alarm.display()) # 09:05
两个文档阅读点你用上了吗:snooze 返回 None(就地修改)——所以不能写 alarm = alarm.snooze();display 返回字符串——所以要 print 它的返回值。
练习 3:审 AI 的类(挑战)
假设 AI 帮你生成了下面的类。用三问审查,找出两处不规范(都是本单元讲过的规矩),说出改法并动手修好。
💡 提示
毛病一:有个属性没在 __init__ 里声明(藏在 add 里搞"第一次才创建"的小动作——如果先调 Total 会怎样?)。毛病二:看方法的命名风格。
✅ 参考答案
class ShoppingCart:
def __init__(self, owner):
self.owner = owner
self.items = [] # 属性在 __init__ 声明齐——空车也是车
def add(self, item, price):
self.items.append((item, price))
def total(self): # 方法用蛇形小写(动词)
return sum(p for _, p in self.items)
cart = ShoppingCart("小雨")
cart.add("键盘", 299)
cart.add("鼠标", 89)
print(cart.total())
原版若先调 Total() 再 add() 会直接 AttributeError——"属性在 __init__ 声明齐"不是洁癖,是在消灭一整类时序 bug。审 AI 代码时,这两处是高频雷点。
📝 随堂测验
1. “陌生类三问”指的是?
2. d.year 不带括号、d.weekday() 带括号,区别是?
3. 文档写着某方法“-> None(就地修改)”,意味着调用时要注意什么?
4. 想快速看看一个陌生对象都有哪些方法,用什么?
5. 审查 AI 生成的类时,“属性没有在 __init__ 里声明齐”为什么算雷点?
本课小结
- 陌生类三问:怎么造 / 有什么 / 会什么——读文档、读源码、审 AI 代码通用
- 括号分名词动词:属性直接读,方法带括号调;方法两种脾气——改自己(返回 None)vs 交新的
- 三板斧自助探索:
type()→dir()→help();你写的 docstring 会在别人的 help() 里显灵 类名.方法()(如date.today())是官方便捷出厂通道,见了不慌
下一课是本单元关卡:综合测验 + 亲手设计一个"待办任务"类——版图里第一个完全由你建模的对象。
划选正文任意文字可高亮、批注或加入复习卡
讨论
载入中…