摘选自《利用Python进行数据分析·第2版》第2章 Python语法基础,IPython和Jupyter Notebooks,中文Gitbook请访问:https://shixiangwang.github.io/py4ds-CN/ (觉得不错不妨分享和Star下)
一些Python程序员总是使用标准的Python执行Python代码的,从事数据分析和科学计算的人却会使用IPython,一个强化的Python解释器,或Jupyter notebooks,一个网页代码笔记本,它原先是IPython的一个子项目。
你可以用ipython
在命令行打开IPython Shell,就像打开普通的Python解释器:
$ ipython
Python 3.6.0 | packaged by conda-forge | (default, Jan 13 2017, 23:17:12)
Type "copyright", "credits" or "license" for more information.
IPython 5.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: a = 5
In [2]: a
Out[2]: 5
你可以通过输入代码并按Return(或Enter),运行任意Python语句。当你只输入一个变量,它会显示代表的对象:
In [5]: import numpy as np
In [6]: data = {i : np.random.randn() for i in range(7)}
In [7]: data
Out[7]:
{0: -0.20470765948471295,
1: 0.47894333805754824,
2: -0.5194387150567381,
3: -0.55573030434749,
4: 1.9657805725027142,
5: 1.3934058329729904,
6: 0.09290787674371767}
前两行是Python代码语句;第二条语句创建一个名为data
的变量,它引用一个新创建的Python字典。最后一行打印data
的值。
许多Python对象被格式化为更易读的形式,或称作pretty-printed
,它与普通的print
不同。如果在标准Python解释器中打印上述data
变量,则可读性要降低:
>>> from numpy.random import randn
>>> data = {i : randn() for i in range(7)}
>>> print(data)
{0: -1.5948255432744511, 1: 0.10569006472787983, 2: 1.972367135977295,
3: 0.15455217573074576, 4: -0.24058577449429575, 5: -1.2904897053651216,
6: 0.3308507317325902}
IPython还支持执行任意代码块(通过一个华丽的复制-粘贴方法)和整段Python脚本的功能。你也可以使用Jupyter notebook运行大代码块,接下来就会看到。
Tab补全
从外观上,IPython shell和标准的Python解释器只是看起来不同。IPython shell的进步之一是其它IDE和交互计算分析环境都有的tab补全功能。在shell中输入表达式,按下Tab,会搜索已输入变量(对象、函数等等)的命名空间:
In [1]: an_apple = 27
In [2]: an_example = 42
In [3]: an<Tab>
an_apple and an_example any
在这个例子中,IPython呈现除了之前两个定义的变量和Python的关键字和内建的函数any
。当然,你也可以补全任何对象的方法和属性:
In [3]: b = [1, 2, 3]
In [4]: b.<Tab>
b.append b.count b.insert b.reverse
b.clear b.extend b.pop b.sort
b.copy b.index b.remove
同样也适用于模块:
In [1]: import datetime
In [2]: datetime.<Tab>
datetime.date datetime.MAXYEAR datetime.timedelta
datetime.datetime datetime.MINYEAR datetime.timezone
datetime.datetime_CAPI datetime.time datetime.tzinfo
在Jupyter notebook和新版的IPython(5.0及以上),自动补全功能是下拉框的形式。
除了补全命名、对象和模块属性,Tab还可以补全其它的。当输入看似文件路径时(即使是Python字符串),按下Tab也可以补全电脑上对应的文件信息:
In [7]: datasets/movielens/<Tab>
datasets/movielens/movies.dat datasets/movielens/README
datasets/movielens/ratings.dat datasets/movielens/users.dat
In [7]: path = 'datasets/movielens/<Tab>
datasets/movielens/movies.dat datasets/movielens/README
datasets/movielens/ratings.dat datasets/movielens/users.dat
结合%run
,tab补全可以节省许多键盘操作。
另外,tab补全可以补全函数的关键词参数(包括等于号=)。
自省
在变量前后使用问号?,可以显示对象的信息:
In [8]: b = [1, 2, 3]
In [9]: b?
Type: list
String Form:[1, 2, 3]
Length: 3
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
In [10]: print?
Docstring:
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
Type: builtin_function_or_method
这可以作为对象的自省。如果对象是一个函数或实例方法,定义过的文档字符串,也会显示出信息。假设我们写了一个如下的函数:
def add_numbers(a, b):
"""
Add two numbers together
Returns
-------
the_sum : type of arguments
"""
return a + b
然后使用?符号,就可以显示如下的文档字符串:
In [11]: add_numbers?
Signature: add_numbers(a, b)
Docstring:
Add two numbers together
Returns
-------
the_sum : type of arguments
File: <ipython-input-9-6a548a216e27>
Type: function
使用??会显示函数的源码:
In [12]: add_numbers??
Signature: add_numbers(a, b)
Source:
def add_numbers(a, b):
"""
Add two numbers together
Returns
-------
the_sum : type of arguments
"""
return a + b
File: <ipython-input-9-6a548a216e27>
Type: function
?还有一个用途,就是像Unix或Windows命令行一样搜索IPython的命名空间。字符与通配符结合可以匹配所有的名字。例如,我们可以获得所有包含load的顶级NumPy命名空间:
In [13]: np.*load*?
np.__loader__
np.load
np.loads
np.loadtxt
np.pkgload
%run命令
你可以用%run
命令运行所有的Python程序。假设有一个文件ipython_script_test.py
:
def f(x, y, z):
return (x + y) / z
a = 5
b = 6
c = 7.5
result = f(a, b, c)
可以如下运行:
In [14]: %run ipython_script_test.py
这段脚本运行在空的命名空间(没有import和其它定义的变量),因此结果和普通的运行方式python script.py
相同。文件中所有定义的变量(import、函数和全局变量,除非抛出异常),都可以在IPython shell中随后访问:
In [15]: c
Out [15]: 7.5
In [16]: result
Out[16]: 1.4666666666666666
如果一个Python脚本需要命令行参数(在sys.argv
中查找),可以在文件路径之后传递,就像在命令行上运行一样。
笔记:如果想让一个脚本访问IPython已经定义过的变量,可以使用
%run -i
。
在Jupyter notebook中,你也可以使用%load
,它将脚本导入到一个代码格中:
>>> %load ipython_script_test.py
def f(x, y, z):
return (x + y) / z
a = 5
b = 6
c = 7.5
result = f(a, b, c)
从剪贴板执行程序
如果使用Jupyter notebook,你可以将代码复制粘贴到任意代码格执行。在IPython shell中也可以从剪贴板执行。假设在其它应用中复制了如下代码:
x = 5
y = 7
if x > 5:
x += 1
y = 8
最简单的方法是使用%paste
和%cpaste
函数。%paste
可以直接运行剪贴板中的代码:
In [17]: %paste
x = 5
y = 7
if x > 5:
x += 1
y = 8
## -- End pasted text --
%cpaste
功能类似,但会给出一条提示:
In [18]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:x = 5
:y = 7
:if x > 5:
: x += 1
:
: y = 8
:--
使用%cpaste
,你可以粘贴任意多的代码再运行。你可能想在运行前,先看看代码。如果粘贴了错误的代码,可以用Ctrl-C中断。
Jupyter notebooks有另外一套庞大的快捷键。因为它的快捷键比IPython的变化快,建议你参阅Jupyter notebook的帮助文档。
魔术命令
IPython中特殊的命令(Python中没有)被称作“魔术”命令。这些命令可以使普通任务更便捷,更容易控制IPython系统。魔术命令是在指令前添加百分号%前缀。例如,可以用%timeit
(这个命令后面会详谈)测量任何Python语句,例如矩阵乘法,的执行时间:
In [20]: a = np.random.randn(100, 100)
In [20]: %timeit np.dot(a, a)
10000 loops, best of 3: 20.9 µs per loop
魔术命令可以被看做IPython中运行的命令行。许多魔术命令有“命令行”选项,可以通过?查看:
In [21]: %debug?
Docstring:
::
%debug [--breakpoint FILE:LINE] [statement [statement ...]]
Activate the interactive debugger.
This magic command support two ways of activating debugger.
One is to activate debugger before executing code. This way, you
can set a break point, to step through the code from the point.
You can use this mode by giving statements to execute and optionally
a breakpoint.
The other one is to activate debugger in post-mortem mode. You can
activate this mode simply running %debug without any argument.
If an exception has just occurred, this lets you inspect its stack
frames interactively. Note that this will always work only on the last
traceback that occurred, so you must call this quickly after an
exception that you wish to inspect has fired, because if another one
occurs, it clobbers the previous one.
If you want IPython to automatically do this on every exception, see
the %pdb magic for more details.
positional arguments:
statement Code to run in debugger. You can omit this in cell
magic mode.
optional arguments:
--breakpoint <FILE:LINE>, -b <FILE:LINE>
Set break point at LINE in FILE.
魔术函数默认可以不用百分号,只要没有变量和函数名相同。这个特点被称为“自动魔术”,可以用%automagic
打开或关闭。
一些魔术函数与Python函数很像,它的结果可以赋值给一个变量:
In [22]: %pwd
Out[22]: '/home/wesm/code/pydata-book
In [23]: foo = %pwd
In [24]: foo
Out[24]: '/home/wesm/code/pydata-book'
IPython的文档可以在shell中打开,我建议你用%quickref
或%magic
学习下所有特殊命令。表2-2列出了一些可以提高生产率的交互计算和Python开发的IPython指令。
集成Matplotlib
IPython在分析计算领域能够流行的原因之一是它非常好的集成了数据可视化和其它用户界面库,比如matplotlib。不用担心以前没用过matplotlib,本书后面会详细介绍。%matplotlib
魔术函数配置了IPython shell和Jupyter notebook中的matplotlib。这点很重要,其它创建的图不会出现(notebook)或获取session的控制,直到结束(shell)。
在IPython shell中,运行%matplotlib
可以进行设置,可以创建多个绘图窗口,而不会干扰控制台session:
In [26]: %matplotlib
Using matplotlib backend: Qt4Agg
在Jupyter中,命令有所不同(图2-6):
In [26]: %matplotlib inline
重点是一些魔术命令,比如%run, %timeit, %load, %pdb, %who, %xdel等。跟测试运行、查看和删除变量、查看和设定工作区的一些命令都值得关注。
不记得就多%quickref或%magic,帮助命令?,??也很重要。