第一章 IPython

《Python Data Science Handbook》

Chapter 1

IPython: Beyond Normal Python

IPython (interactive Python) 是一个增强的Python解释器,提供了一些有用的Python语法附加功能。IPython Notebook是通用Jupyter Notebook结构的特例。Jupyter Notebook不仅支持Python, 还包括用于Julia、R和其他编程语言的Notebook。

魔法函数

获取可用的魔法函数及示例:

1
%magic

获得魔法函数列表:

1
%lsmagic
  • 如果命令是magic关键字,就由IPython处理。否则就由 Python标准解释器去处理。
  • 通常情况下,automagic是打开的,所以可以省略%。可以使用%automagic on (off)控制automagic的开关。

获取帮助信息

Python内置help()函数可以获取帮助,如:

1
help(len)

IPython引入了?号来获取帮助,如:

1
len?

对象方法和对象都可以用
我觉得和使用shift + Tab快捷键效果一样

通过 “ ?? “ 获取源代码

可以通过??获取函数的源代码,但是,有些情况下并不能生效。这是因为查询的对象并不是用Python实现的,而是用C语言或其他编译扩展语言实现的。在这种情况下,??后缀将等同于?后缀。

比如len()就不是用Python实现的。

关于Tab补全

  1. Tab补全的候选列表不直接显示私有方法和特殊方法。先输入一条下划线再按Tab就可以显示这些私有的属性或方法:__future__、 __init__、 __del__、 __new__、 ...
    这些大部分是Python的双下划线方法 (dunder方法),由别的方法调用。
    for i in x这个语句背后调用的是x.__iter__方法。

通配符匹配

当不知道想适用的方法的第一个字符,只知道后面的字符时,Tab补全就不好使了,IPython提供了*号来实现通配符匹配。

1
2
3
>> str.*find*?
str.find
str.rfind

执行外部代码

1
%run a.py

执行上面语句之后,a.py里所有的函数都可以在notebook中使用。
Ipython提供了几种方式来调整代码如何执行,使用%run?查看文档。

计算代码运行时间

对几行代码的计时

%timeit自动计算接下python语句的执行时间。

1
2
>> %timeit a = 3+4
12.6 ns ± 0.0689 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

%timeit自动多次执行简短的命令(所以这一行代码运行的时间稍微长一点),获得统计数据。

1
2
>> %timeit L = [n**2 for n in range(1000)]
318 µs ± 13 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

计算多行语句的运行时间,用%%timeit

1
2
3
4
5
6
7
%%timeit
L = []
for n in range(1000):
L.append(n**2)

output:
360 µs ± 3.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

可以看出for的耗时更长。
注意,%timeit%%timeit都是重复运行多次,对于较慢的统计的方式计算运行时间!

  • 有些代码运行一次之后,元素的值就被改变了 (比如排序),那么排好序之后在重复运行多次排序,计算平均一次的时间显然不合理。于是就有了%time
  • %timeit在底层会阻止系统调用对需要计时的程序的影响 (例如阻止清理未利用的Python对象),少了系统的一些介入过程,所以用%timeit统计的时间比用%time统计的时间更短 (正确使用的情况也是)。
  • %%time也可以实现多行代码的计时。

对整个脚本的计时

IPython提供了%prun

1
%prun function()

可以显示每部分的耗时,方便针对性的优化。

还可以用%lprun进行逐行分析运行时间,需要安装line_profiler包。

内存分析

%memit%mprun,需要安装line_profiler包。

输入和输出对象

IPython创建了叫做InOut的Python变量,记录命令历史,随着新的输入输出自动更新。
Notebook中的In [1] / Out[1]中的序号是获取输入输出历史的线索。
如果要查看输入历史,可以用:

1
print(In)

输出的是一个包含所有输入(字符串形式)的列表。
查看所有输出:

1
print(Out)

因为不是每次输入都有输出,所以输出的是一个字典value是输出值 (类型与真实输出相同),key是整数,代表着对应的第几次输入。这样的话,可以直接查询第几次输出:

1
print(Out[2])

可以直接调用输出的结果:

1
Out[2] + Out[3]

奇怪的是,我使用print,是有输出,但是不产生Out. 只有最后一行的非print语句的结果才算是Out.
原因:print的返回值是None,任何返回值是None的命令都不会加到Out变量中

可以用一条下划线表示最后一个输出,两条下划线表示倒数第二个输出,三个…。但是没有超过三个下划线的表示,需要用到数字标号。

1
2
In [3]: __
Out[3]: 3.141

Out[X]的简写是_X:

1
2
In [4]: _3
Out[4]: 3.141
  • 如果想要禁止输出 (不想将结果存到Out中),最简单的方式就是在语句后面加一个分号;

  • 如果想要一次性获取所有的历史输入,用%history比较好,打印前4条输入命令 (-n是显示行号):

    1
    %history -n 1-4

相关的魔法命令还有%rerun%save (保存历史命令到文件)。

shell命令

IPython中,一行中任何在!之后的内容将不会通过Python内核运行,而是通过系统命令行运行,这样可以减少在Python解释器和shell之间来回切换的次数。

在shell传入或传出值:
通过一个赋值符=将shell命令的输出保存到“列表”中

1
contents = !ls

生成“列表”contents,保存的是ls的输出内容。
但是,shell命令的输出并不以列表的形式返回,而是以IPython中定义的一个特殊的形式返回:

1
2
3
4
In : directory = !dir
type(directory)

Out: IPython.utils.text.SList

这个类型可以像列表一样操作,但拥有更多的功能,自行搜索。
将Python变量传入Shell,通过{varname}实现:

1
2
command = 'dir'
!{command}

直接使用!cd并不能更改所在目录位置,因为Notebook中的shell命令是在一个临时的分支shell中执行的,应该使用命令%cd ...
甚至不需要%符号,直接用cd也能实现同样效果。这种方式被称为自动魔法 (auto magic)函数,可以通过%automagic魔法函数进行翻转。类似shell魔法函数的还有%cat、%cp、%env、%ls、%man、%mkdir、%more、%mv、%pwd、%rm、%rmdir%automagic默认打开,所有魔法命令都可以省略%

错误和调试

%xmode可以控制报错时显示信息的数量:
%xmode Plain 信息显示较少
%xmode Context 中等 (默认)
%xmode Verbose 较多

调试:

标准的Python交互式调试工具是pdb,IPython增强版本的调试器是ipdb。
%debug命令可以启动调试器。


----------over----------