Python极简讲义:一本书入门数据分析与机器学习
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.7 Jupyter中的魔法函数

Jupyter的魅力之处,除了体现在能提供丰富多彩的格式化文本显示,还体现在它提供了很多好用的函数。这些函数如同有魔力一般,故也被称为魔法函数(Magic Function)。所谓魔法函数,实际上是IPython预先定义好的具备特定功能的函数被放到Jupyter中使用罢了。

请注意,这是IPython特有的函数,并非Python的内置函数,因此脱离IPython的使用环境(如使用Pycharm或Python自带的IDLE开发环境等),这些函数是无法被解析运行的。

在图1-22中,第14行和第16行就分别涉及了两个魔法函数:%timeit和%matplotlib inline,后面我们会分别介绍它们。

魔法函数分两种:一种是面向行的(line magic),以一个百分号(%)开头,其作用范围就是使用这个魔法函数的当前行,里面可添加其他正常代码(如图1-22中的第14行);另一种是面向整个块的(即Jupyter中左侧给出编号In[n]:的一块区域,这里n为某个具体的编号),其作用范围是整个块。

下面我们简单介绍几个最常见的魔法函数。

1.7.1 %lsmagic函数

%lsmagic函数可以列出(list,简写ls)所有魔法函数。如果我们想使用一个魔法函数,却忘记函数名如何写时,就可以使用%lsmagic来查询(在代码框内输入%lsmagic后按Shift+Enter组合键执行即可),如图1-29所示。

图1-29 Jupyter中的各种魔法函数

1.7.2 %matplotlib inline函数

图1-22的第16行代码中出现过%matplotlib inline函数,它的含义就是告诉Ipython,我们的绘图模式是内嵌(inline)模式,即将绘图直接显示在当前的网页上。有了这个魔法函数,图1-22所示代码的第21行plt.show()其实是可以省略的,读者朋友将其用注释形式去掉,然后尝试再次运行代码,可查看结果有无变化。

其实,这个魔法函数的后置参数“inline”有一个“对标”参数—qt,如果我们使用这个参数,即%matplotlib qt,则表示代码构造的图形是通过独立窗口显示的。在独立窗口中可支持图形的缩放、拖曳及被另存为多种格式的图形文件(如.jpg、.png和.pdf等)。读者朋友可将图1-22中的第16行代码修改为的%matplotlib qt并再次运行,感性认识这两个参数带来的不同。

1.7.3 %timeit函数

魔法函数%timeit的功能是为某行代码的执行提供计时服务此处的time为动词,表示“对……计时”,这里的“it”是指当前代码行。,这在评估机器学习算法的性能(特别是评估运行时间)时特别有用。例如,如果我们想对图1-22中的第14行代码的运行时间进行计时,则可以如下操作。

按Shift+Enter组合键执行,结果如下。

上述输出结果的意思是,对于代码“area=(40 * np.random.rand(20))**2”运行7轮,每轮运行1000个循环,然后求得均值为6.6微秒,方差为1.28微秒这里有一个执行细节需要注意,建议在Jupyter环境下,把待测试运行时长的代码单独放置于一个单元格中。例如,图1-22所示的代码可考虑分为三个代码块,1~13行为一个代码块,14行为一个代码块,15~21行为一个代码块。在这样的配置中,第14行所在的代码循环测试不结束,后续的代码(15~21行)就不会执行。否则,如果1~21行形成一个代码大杂烩,可能会出现问题,第14行的循环还没有执行完毕,Python会“迫不及待”尝试解释14行之后的代码。这时,第14行所示的变量还没有来得及压栈入内存,于是第15行就会出现变量命名错误,如NameError: name 'area' is not defined。

如果我们想运行10轮而非7轮,该怎么办呢?这时就需要为魔法函数添加参数了,具体如下。

需要注意的是,参数选项“-n10”中的“-n”和“10”中间并没有空格。图1-29列出了如此多魔法函数,我们怎么才能知道某个魔法函数的具体用法呢?最简单的办法就是在Jupyter中创建一个新的单元格,然后输入该魔法函数,最后追加一个问号(?),注意函数名和问号之间没有空格,如下所示。

然后按Ctrl+Enter组合键运行这个单元格。

假设某个代码块正好就是一个算法的实现,现在我们想对整个代码块的运行进行计时,而不是对某一行代码的运行计时,该如何做呢?

这时,就需要利用%timeit的姊妹函数—块魔法函数%%timeit,即timeit前面有两个%。如前所述,它的适用范围是整个代码块,因此通常会把这个魔法函数放在某个代码块的首行。

1.7.4 %%writefile函数

我们知道,Jupyter是一个集才华(代码编写)和颜值(图文文档显示)于一身的编程工具。但有时,如在生产环境中,我们还想把调试好的Python代码单独拎出来操作,这时该怎么办呢?

当然,我们可以采用复制的方式,把Jupyter代码块中的代码一块一块地复制到一个IDE(如Spyder)的新建文件中,然后保存为我们所需要的Python源文件。但实际上,Jupyter已经替我们考虑到这个需求。魔法函数%%writefile就是做这项工作的。见名知意,这个魔法函数的主要功能是把整个代码块中的Python代码保存为一个.py文件。

通过该魔法函数前端的两个百分号(%%)就可以看出,这是一个作用域为整块代码的魔法函数。%%writefile后面跟的参数是一个具体的Python文件名。假设我们想保存图1-22所示的代码块中的Python代码,就可以在代码块的首行添加如下代码。

然后,按Ctrl+Enter组合键运行单元格,这个myFirstBook.py源文件就默认保存在与*.ipynb(Jupyter文件)相同的路径下。当然,我们可以为其添加一个非默认路径,如%%writefile/Users/yhilly/ Documents/myFirstBook.py,在这种情况下,单元格执行之后,myFirstBook.py就被存储在“/Users/yhilly/Documents/”路径下。读者也可以单击Jupyter的菜单栏【File】→【Download as】,有多种文件格式可供选择,可将编写好的代码保存到本地。

1.7.5 其他常用的魔法函数

下面我们列出其他常用的魔法函数,如表1-1所示,更多详细使用方法,可参阅IPython的官方文档。

表1-1 其他常用的魔法函数

当然,Jupyter的功能及使用技巧远远不止上面这些,在以后的用得着的日子里,我们还需要边用边摸索,这里就不一一介绍了。

1.7.6 在Jupyter中执行shell命令

我们知道,shell是一种在命令行执行的与计算机进行文本交互的命令方式。一般而言,当我们正在使用Python编译器且需要用到命令行工具时,要在shell和IDLE之间不断切换。

但在Jupyter环境下,一切都显得浑然天成。在代码单元格里,直接在命令之前添加一个“!”(注意:请用英文的惊叹号)就能执行shell命令,如图1-30所示。

图1-30 在Jupyter中执行shell命令在Windows系统中,ls对应的命令是dir,pwd对应的命令是chdir。在这些命令前面添加英文的感叹号,即可执行只有在CMD控制台窗口下才可执行的命令。

我们可以把shell命令返回的结果当作参数传递给Python变量,如图1-31所示。

图1-31 将shell命令返回的结果传递给Python变量