📊 第2章 搭建 Python 数据分析环境
📄 一句话概括

内省的意思是程序看自己。三个函数够用:dir 看有什么、signature 看怎么调、doc 看干什么。 str 有 12 个以 is 开头的方法;replace 的签名是 replace(self, old, new, /, count=-1)。 排查顺序是签名 → 文档 → 源码。前两步不够,第三步一定够。

📝 本章和前面几章的关系

上一篇讲了三把钥匙,这一篇把第一把(问号)拆开:问号背后就是内省。 这一节看着零碎,但它是全书唯一一个「不用联网就能求助」的技能。断网时特别值钱。

一、三个问题,三个函数

想问什么 用什么 返回什么
它有哪些属性和方法 dir(obj) 名字列表
它该怎么调用 inspect.signature 参数与默认值
它是干什么的 obj.doc 文档字符串

这三个够用了。inspect 里还有十几个函数,那是给写框架的人准备的,日常用不上。 内省是排查问题最快的一条路,比搜索快。因为搜索要组织关键词,内省不用。

二、现场查一个陌生对象

拿 str 举例,看它有哪些以 is 开头的方法:一共 12 个——isalnum、isalpha、isascii、 isdecimal、isdigit、isidentifier、islower、isnumeric、isprintable、isspace、istitle、isupper。 这一串名字本身就说明了能干什么:判断是不是数字、是不是小写、是不是标题格式。

再看 replace 的签名:replace(self, old, new, /, count=-1)。 意思是:old 和 new 必填,count 可选,默认 -1(全部替换)。这比读一整页文档快。

三、签名里的符号要看懂

签名里有几种符号,认得它们能省很多猜:

符号 含义
self 实例方法的第一个参数,调用时不写
/ 前面的参数只能按位置传,不能按名字传
= 值 有默认值,可以不传
*args 任意多个位置参数
两个星号加 kwargs 任意多个关键字参数

这一篇只要求认出 / 和 =。看到 /,就别写 str.replace(old="a", new="b")。

四、文档字符串不总是有用

len 的文档就一句话:Return the number of items in a container. 够清楚。 但很多第三方库的文档字符串是空的,或者只写了 TODO。 这时候去看源码:inspect.getsource 能把函数实现打出来。

排查顺序:签名 → 文档 → 源码。前两步便宜,第三步一定够。

五、为什么值得单独一节

因为它是唯一一个「不用联网、不用搜索、随时可用」的求助方式。 断网、装不上包、文档版本对不上,这三种情况下它照样能用。 实践建议:每接触一个新库,先 dir 一下、挑三个函数看签名、跑一个最小例子。十分钟能建立基本地图。

这也是第 3 章学 Pandas 的方法:不背 API,先摸清它有哪些动词。

六、动手 Demo:内省:不用翻文档也知道它能干什么

用 dir 列出 str 的 is 系列方法,用 inspect.signature 查 replace 的签名。 再读 len 的文档字符串,看看内省能给出多少信息。

import inspect

is_methods = [n for n in dir(str) if n.startswith("is")]
print("str 的 is 系列有 %d 个" % len(is_methods))
print("、".join(is_methods))

print("签名 %s" % str(inspect.signature(str.replace)))
print("签名 %s" % str(inspect.signature(str.split)))

doc = (len.__doc__ or "").strip()
print("len 的文档:%s" % doc)

print("参数 %s" % list(inspect.signature(str.replace).parameters))

实跑输出:

--------------------------------------------------------------------
内省:不用翻文档也知道它能干什么
--------------------------------------------------------------------

  ① 三个问题,三个函数
  --------------------------------------------------------------------

| 想问什么 | 用什么 | 返回什么 |
|---|---|---|
| 它有哪些属性 | dir(obj) | 名字列表 |
| 它怎么调用 | inspect.signature | 参数与默认值 |
| 它是干什么的 | obj.__doc__ | 文档字符串 |

  这三个够用了。剩下的 inspect 函数是给写框架的人准备的。
  ! 内省的意思是「程序看自己」。它是排查问题最快的一条路,比搜索快。

  ② 现场查一个陌生对象
  --------------------------------------------------------------------
  拿 str 举例,看它有哪些以 is 开头的方法:
    isalnum、isalpha、isascii、isdecimal、isdigit、isidentifier、islower、isnumeric、isprintable、
    isspace、istitle、isupper
  再看 replace 的签名:
    replace(self, old, new, /, count=-1)
  签名告诉你:它要 old 和 new 两个必填,count 可选。这比读一整页文档快。
  ! 签名是接口,文档是说明,dir 是目录。排查时按这个顺序问,最快。

  ③ 文档字符串不总是有用
  --------------------------------------------------------------------
  len 的文档就一句话:Return the number of items in a container. 够清楚。
  但很多第三方库的文档字符串是空的,或者只写了个 TODO。
  这时候就去看源码:inspect.getsource 能直接把函数的实现打出来。
  ! 所以内省的顺序是:签名 → 文档 → 源码。前两步不够,第三步一定够。

  ④ 这个东西为什么值得单独一节
  --------------------------------------------------------------------
  因为它是唯一一个「不用联网、不用搜索、随时可用」的求助方式。
  断网、装不上包、文档版本对不上,这三种情况下它照样能用。
  ! 学到后面会发现:会用 dir 和 signature 的人,学新库的速度明显快一档。

  ⑤ 一条实践建议
  --------------------------------------------------------------------
  每接触一个新库,先做三件事:dir 一下、挑三个函数看签名、跑一个最小例子。
  十分钟之内能建立基本地图,比从头读文档快。
  ! 这也是后面第 3 章开始学 Pandas 的方法:不背 API,先摸清它有哪些动词。

dir(str) 返回几百个名字,用列表推导式一筛就干净了——这也是内省的常见用法:先筛再问。 inspect.signature 在 C 实现的内建函数上有时拿不到,会抛 ValueError。 拿不到就退回看文档,不必纠缠。

30 秒实验

  1. 用 dir(list) 筛出所有以 sort 或 append 开头的方法,看列表能做什么。
  2. 查 dict 的 get 方法签名,看它的默认值是什么。
  3. 想一想:为什么内省比搜索更适合排查「这个对象有没有这个方法」这种问题?

常见误区

  1. 只会 dir 不会筛:几百个名字打出来没法看,要配列表推导式。
  2. 以为文档一定有:第三方库里空文档很常见,得会看源码。
  3. 忽略签名里的 /:按名字传参会报 TypeError,报错还很难懂。
  4. 不查就猜参数名:猜错一次的成本,比查一次高得多。
自测三问(点开对答案) 1. dir、signature、__doc__ 分别回答什么问题? —— 有什么、怎么调、干什么。三个问题覆盖了日常排查的绝大部分需求。 2. replace 签名里的 `/` 是什么意思? —— 它前面的参数只能按位置传。写 str.replace(old="a") 会报错。 3. 为什么说内省是断网时唯一能用的求助方式? —— 它读的是本地对象自带的元数据,不需要网络、不需要文档站、不依赖版本对应。

第 2 章到此结束,环境算搭好了。第 3 章开始正式用 Pandas——第一件事是把一张 Excel 表读进来。

相关笔记