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

IPython 是 Python 的交互式外壳,装完用 ipython 命令进。Tab 补全从这里开始有用。 三个前缀是三把钥匙:名字加问号查文档,% 开头跑魔法命令,! 开头调系统命令。 三把都不属于 Python 语言,都是外壳提供的便利——离开 IPython 就不存在。

📝 本章和前面几章的关系

上一篇讲 Notebook 这个壳,这一篇讲壳下面的 IPython。两者是同一套东西的两种界面。 本沙箱装了 IPython 9.18.0,文中的三把钥匙都是脚本里真跑出来的输出。

一、装上、进去、写第一句

装:python -m pip install ipython。装完命令行敲 ipython 就进去了。 进去之后提示符变成 In [1]:。敲一行,回车就出结果,不用建文件。 这就是交互式的价值:试一个想法,从想到看到只要一秒。

退出用 exit 或 Ctrl+D。Tab 补全是这个环境最常用的功能,打完前几个字母按 Tab。

二、第一把:问号查文档

名字后面加一个问号,打印签名和文档;加两个问号,连源码一起打。 比如 len?,输出三行:Signature: len(obj, /)、 Docstring: Return the number of items in a container.、Type: builtin_function_or_method。 签名那一行的 / 表示后面的参数只能按位置传,不能写 len(obj=...) 这种。

这一个动作省掉的查文档时间,比任何插件都多。

三、第二把:百分号跑魔法命令

以 % 开头的是魔法命令,是 IPython 自己实现的快捷方式,不是 Python 语法。

命令 作用
%timeit 测一行代码跑多久,自动决定跑几次
%run 跑一个 .py 文件,变量留在当前会话里
%who 列出当前定义了哪些变量
%pwd / %cd 看和切换工作目录
%matplotlib inline 让图直接显示在页面里(Notebook 专用)

最常用的是 %timeit。 本篇实测一次 sum(range(1000)),输出形如 18.5 us ± 0 ns per loop——具体时间每次都不一样。 魔法命令只在 IPython 和 Notebook 里有效。存成 .py 用 python 跑,% 那行会报语法错。

四、第三把:叹号调系统命令

以 ! 开头的行,直接交给操作系统执行,输出当成字符串返回。 跑 !echo hello-from-shell,拿到 hello-from-shell。 还能把结果接回来:files = !dir 之后,files 就是一个列表,可以继续用 Python 处理。

这一把让 Notebook 里能顺手做 shell 的事:看目录、解压、调 git,不用来回切窗口。 别拿它跑危险命令。!rm 是真删,没有回收站,也没有撤销。

五、三把钥匙的共同点

都不属于 Python 语言,都是 IPython 这个壳提供的便利。 换句话说:离开 IPython,这三样都不存在;离开 Python,IPython 也不存在。 分清「语言的语法」和「工具的便利」,就不会把 %timeit 写进正式脚本然后纳闷为什么报错。

本沙箱怎么用:没装 Jupyter,但装了 IPython,用 InteractiveShell 对象在脚本里跑这三把钥匙。 机制是同一个。

六、动手 Demo:IPython 的三把钥匙

用 InteractiveShell 在脚本里模拟交互式会话,分别试问号、% 和 ! 三种前缀。 捕获它们的输出打出来——注意时间类的输出每次都不一样。

from IPython.core.interactiveshell import InteractiveShell
from IPython.utils.capture import capture_output

sh = InteractiveShell.instance()

with capture_output() as cap:
    sh.run_cell("len?")
print("[问号]")
for line in cap.stdout.strip().split(chr(10))[:4]:
    print("  " + line)

with capture_output() as cap:
    sh.run_line_magic("timeit", "-n 100 -r 3 sum(range(1000))")
print("[百分号] %s" % cap.stdout.strip())

with capture_output() as cap:
    sh.run_cell("!echo hello-from-shell")
print("[叹号] %s" % cap.stdout.strip())

实跑输出:

--------------------------------------------------------------------
IPython 的三把钥匙
--------------------------------------------------------------------

  ① 第一把:问号查文档
  --------------------------------------------------------------------
  在名字后面加一个问号,打印它的签名和文档;加两个问号,连源码一起打。
  比如 len? 的输出是这样的:
    Signature: len(obj, /)

    Docstring: Return the number of items in a container.

    Type:      builtin_function_or_method
  ! 这一个动作省掉的查文档时间,比任何插件都多。

  ② 第二把:百分号跑魔法命令
  --------------------------------------------------------------------
  以 % 开头的是「魔法命令」,是 IPython 自己实现的快捷方式,不是 Python 语法。

| 命令 | 作用 | 频率 |
|---|---|---|
| %timeit | 测一行代码跑多久 | 常用 |
| %run | 跑一个 .py 文件 | 常用 |
| %who | 列出当前定义的变量 | 常用 |
| %pwd / %cd | 看和切换工作目录 | 常用 |
| %matplotlib inline | 让图直接显示在页面里 | 画图时用 |

  实测一条 %timeit(时间每次都变,只作形式示例):
    16.8 us +- 1.71 us per loop (mean +- std. dev. of 3 runs, 100 loops each)
  ! 魔法命令只在 IPython 和 Notebook 里有效。存成 .py 用 python 跑,% 那行会报语法错。

  ③ 第三把:叹号调系统命令
  --------------------------------------------------------------------
  以 ! 开头的行,直接交给操作系统执行,输出当成字符串返回。
  跑 !echo hello-from-shell,拿到:hello-from-shell
  还能把结果接回来用:files = !dir 之后,files 就是一个列表。
  ! 这一把让 Notebook 里能顺手做 shell 的事:看目录、解压、调 git,不用来回切窗口。

  ④ 三把钥匙共同点
  --------------------------------------------------------------------
  都不属于 Python 语言,都是 IPython 这个壳提供的便利。
  换句话说:离开 IPython,这三样都不存在;离开 Python,IPython 也不存在。
  ! 分清「语言的语法」和「工具的便利」,就不会把 %timeit 写进正式脚本然后纳闷为什么报错。

  ⑤ 本沙箱怎么用这三把钥匙
  --------------------------------------------------------------------
  这台机器没装 Jupyter,但装了 IPython 9.18.0。上面三段都是脚本里真跑出来的。
  机制是同一个:InteractiveShell 对象负责解释 ?、% 和 ! 这三种前缀。
  ! 平台原样标一句:教材里的 Jupyter 页面交互本沙箱不执行,等价能力已用 IPython 复刻。

capture_output 是 IPython 自带的输出捕获器,专门用来在脚本里拿交互式的输出。 %timeit 那一行的时间每次都不一样,所以正文里从不写死具体数字,只写它长什么样。

30 秒实验

  1. 试试 str.replace?,看它的签名里有几个参数。
  2. 用 %run 跑一个写好的 .py 文件,再在会话里打 %who 看变量名。
  3. 想一想:为什么 %timeit 要跑很多次再取平均,而不是只跑一次?

常见误区

  1. 把魔法命令写进 .py 文件:那不是 Python 语法,用 python 跑直接报错。
  2. 拿 ! 跑删除命令:没有回收站,删了就没了。
  3. 只看文档不看签名:文档讲用途,签名讲怎么调用,两个都要看。
  4. timeit 结果当基准数据:它受机器、负载、缓存影响,只能跟自己比。
自测三问(点开对答案) 1. 问号、百分号、叹号三种前缀,分别是谁提供的? —— 都是 IPython 这个外壳提供的,不是 Python 语言的语法。 2. 为什么 %timeit 的输出不能写死在文章里? —— 因为它依赖机器、当前负载和缓存状态,每次跑都不一样。 3. !echo 和 print 有什么区别? —— !echo 调的是操作系统的 echo 程序,print 是 Python 的函数。前者输出能被当字符串接回来。

三把钥匙是入口。真正让人学得快的是下一层:不看文档也能问出「它能干什么」。下一篇讲内省。

相关笔记