python与数据思维基础笔记第一章_《Python数据科学手册》抄书笔记,第一章: Ipython 超越Python...

首先启动IPython shell 和Jupyter Notebook

在命令行输入ipython启动IPython

mac启动Jupyter使用Python3 -m IPython notebook

在IPython中,符号?用于浏览文档,??用于浏览源代码,而Tab用于自动补全。

每一个Python对象独有一个字符串的引用,该字符串即为docstring。大多数情况下,该字符串包含对象的简要介绍和使用方法。

内置的help()函数可以获取这些信息。

?可以查看对象的相关信息

In [5]: len?

Signature: len(obj, /)

Docstring: Return the number of items in a container.

Type: builtin_function_or_method

In [6]: l = []

In [7]: l?

Type: list

String form: []

Length: 0

Docstring:

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list.

The argument must be an iterable if specified.

In [8]: l.index?

Signature: l.index(value, start=0, stop=9223372036854775807, /)

Docstring:

Return first index of value.

Raises ValueError if the value is not present.

Type: builtin_function_or_method

In [9]:

无论是函数,方法还是具体实例对象。

在自己编写函数的时候,写好相关docstring

1.2.2通过符号??获取源代码。

1.2.3用Tab补全的方式探索模块

1.对象内容的Tab自动补全(相对简单)

2.导入时的Tab自动补全

3.超越Tab自动补全:通配符适配

当想适配中间或者末尾的几个字符时,可以通过*符号来实现

列举除名字空间中以Warning结尾的所有对象。

In [11]: *Warning?

BytesWarning

DeprecationWarning

FutureWarning

ImportWarning

PendingDeprecationWarning

ResourceWarning

RuntimeWarning

SyntaxWarning

UnicodeWarning

UserWarning

Warning

不要忘记了后面有一个?

寻找一个字符串方法,它的名字中有find

In [12]: str.*find*?

str.find

str.rfind

In [13]:

1.3IPython shell中的快捷键

书中分为:导航快捷键、文本输入快捷键、命令历史快捷键和其他快捷键

1.3.1 导航快捷键

Crrl+a 光标移到本行开始处

Ctrl+e 光标移动本行结尾处

Ctrl+b(或左箭头键) 光标向后移动一个

Ctrl+f(或右箭头键) 光标向前移动一个

1.3.2 文本输入快捷键

Backspace键   删除前一个字符

Ctrl + d        删除后一个字符

Ctrl + k     从光标开始剪切至行的末尾

Ctrl + u     从行的开头剪切至光标

Ctrl + y     yank(即粘贴)之前剪切的文本

Ctrl + t     transpose(即交换)前两个字符

1.3.3 命令历史快捷键

Ctrl + p  (向上箭头)  获取前一个历史命令

Ctrl + n  (向下箭头)  获取下一个历史命令

Ctrl + r        对历史命令的反向搜索

这是一个非常好用的功能,对话框中输入关键字会自动匹配相关信息。

使用Ctrl + P与Ctrl + N 可以上下查看相关搜索记录。

使用上下箭头可以查看匹配到的相关信息。

1.3.4 其他快捷键

Ctrl + l 清楚终端屏幕的内容

Ctrl + c 中断当前的Python命令

Ctrl + d  退出IPython会话

1.4 IPython魔法命令

1.4.1粘贴代码块: %paste和%cpaste

当复制,粘贴的时候,出现了多于的符号,解释器报错

可以用%paste与%cpaste来进行复制,粘贴

1.4.2 执行外部代码: %run

执行外部的模块文件

In [2]: %run myscript.py

1 squared is 1

2 squared is 4

3 squared is 9

In [3]: square(55)

Out[3]: 3025

In [4]:

square函数定义在myscript.py模块中,这感觉也是一种比较好的加载模块内对象的方式。

myscript.py文件内容:

def square(x):

"""square a number"""

return x ** 2

for N in range(1, 4):

print(N, "squared is", square(N))

1.4.3 计算代码运行时间: %timeit

In [4]: %timeit L = [n ** 2 for n in range(1000)]

241 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [5]:

这个命令会多次执行简短命令,以获取更加稳定的结果。

多行的输入测试,可以使用两个%%来实现.

%%timeit

...: L = []

...: for n in range(1000):

...: L.append(n ** 2)

## -- End pasted text --

278 µs ± 2.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

1.4.4 魔法函数的帮助:?、%magic、 %lsmagic

获取文档注释

%timeit?

为了获得可用魔法函数的通用描述以及一些示例,可以输入一下命令

%magic

为了快速而简单地获取所有可用魔法函数的列表,可以输入以下命令:

%lsmagic

1.5 输入和输出历史

前面已经讲过可以使用Ctrl+p或者Ctrl+n来翻看历史

1.5.1IPython的输入和输出对象

In [1]: import math

In [2]: math.sin(2)

Out[2]: 0.9092974268256817

In [3]: math.cos(2)

Out[3]: -0.4161468365471424

In [4]: print(in)

File "", line 1

print(in)

^

SyntaxError: invalid syntax

In [5]: print(In)

['', 'import math', 'math.sin(2)', 'math.cos(2)', 'print(in)', 'print(In)']

In [6]: print(Out)

{2: 0.9092974268256817, 3: -0.4161468365471424}

In [7]:

Ipython里面有一对In与Out的输入与输出。,在Ipython中会自动添加In和Out的Python变量,其中In为list实例,Out为Dict实例

任何返回值是None的命令都不会加到Out变量中(所以print输出不会添加到Out中)。

In [7]: print()

In [8]: print

Out[8]:

In [9]: print(In)

['', 'import math', 'math.sin(2)', 'math.cos(2)', 'print(in)', 'print(In)', 'print(Out)', 'print()', 'print', 'print(In)']

In [10]: print(Out)

{2: 0.9092974268256817, 3: -0.4161468365471424, 8: }

In [11]:

这样,如果利用之前的结果可以方便的拿出来使用。

1.5.2 下划线快捷和以前的输出

如果想获取上一次的输出可以用_来表示,倒数第二个用__,以此类推

通过_x,其中的x为Out输出中的key,开获取第几次的值

In [27]: Out[2]

Out[27]: 0.9092974268256817

In [28]: _2

Out[28]: 0.9092974268256817

1.5.3 禁止输出

就是在输入命令行中,在末尾添加;分号

In [32]: math.sin(2) + math.cos(2);

In [33]: 32 in Out

Out[33]: False

In [34]:

在Out的输出字典中,根本没有key32的存在,说明没有输出。

1.5.4 相关的魔法命令

%history 来获取所有的历史命令输入。

通过-n可以显示命令行的输入索引编号,通过n-m开业获取n到m号的输入命令情况。

In [35]: %history 1-4

import math

math.sin(2)

math.cos(2)

print(in)

In [36]: %history -n 1-4

1: import math

2: math.sin(2)

3: math.cos(2)

4: print(in)

In [37]:

1.6 IPython和shell命令

1.6.2 IPython中的shell命令

只需要在命令之前+!感叹号

In [45]: !pwd

/Users/shijianzhong

In [46]: !echo "printing from the shell"

printing from the shell

In [47]:

1.6.3 在shell中传入或传出值

通过变量接收shell命令的输出值

contents = !ls

In [48]: print(contents)

['Applications', 'Compute-Question', 'Desktop', 'Documents', 'Downloads', 'Java_Home', 'Library', 'Movies', 'Music', 'Pictures', 'Postman', 'Public', 'PycharmProjects', 'Untitled Folder', '__pycache__', 'books', 'c_study', 'codeintel', 'django_venv', 'dump.rdb', 'eclipse-workspace', 'exec_new3.sh', 'flasky', 'group_git_tips', 'image', 'java_error_in_pycharm.hprof', 'java_error_in_pycharm_958.log', 'learn_crystal', 'learn_django', 'learn_git', 'learn_ruby', 'learn_shell', 'learngit', 'mbox', 'mprun_demo.py', 'my_home', 'my_software', 'mycentos.tar', 'myscript.py', 'nohup.out', 'pyalgo_two', 'pyalgotrade', 'ruby_study', 'scrapy_venv', 'show_p_path.py', 'ssh_test', 'study', 'tmp', 'work_space']

In [49]: contents

Out[49]:

['Applications',

'Compute-Question',

'Desktop',

'Documents',

'Downloads',

'Java_Home',

'Library',

'Movies',

'Music',

'Pictures',

'Postman',

'Public',

'PycharmProjects',

'Untitled Folder',

'__pycache__',

'books',

'c_study',

'codeintel',

'django_venv',

'dump.rdb',

'eclipse-workspace',

'exec_new3.sh',

'flasky',

'group_git_tips',

'image',

'java_error_in_pycharm.hprof',

'java_error_in_pycharm_958.log',

'learn_crystal',

'learn_django',

'learn_git',

'learn_ruby',

'learn_shell',

'learngit',

'mbox',

'mprun_demo.py',

'my_home',

'my_software',

'mycentos.tar',

'myscript.py',

'nohup.out',

'pyalgo_two',

'pyalgotrade',

'ruby_study',

'scrapy_venv',

'show_p_path.py',

'ssh_test',

'study',

'tmp',

'work_space']

In [50]: type(contents)

Out[50]: IPython.utils.text.SList

In [51]: message = "hello from the Python"

In [52]: !echo {message}

hello from the Python

变量接收的shell命令输出的对象是一个类似与列表的对象,Python中的变量名,也可以通过{}的形式传递给shell

1.7与shell相关的魔法方法

Notebook中的shell命令是在一个临时的分支shell中执行的。如果你希望以一种更持久的方式运行,可以使用%魔法命令

通过%后面执行的命令,不能与Python进行交互

一般的shell命令,会通过%automagic模范函数进行翻转。当automagic被打开,一些常用的命令直接省略%就可以跟shell中使用一样

cd cat cp ls man mkdir more mv pwd rm rmdir

In [76]: mkdir tmpe

In [77]: cp myscript.py tmp

In [78]: cp myscript.py tmpe/

In [79]: ls tmpe

myscript.py

In [80]:

In [80]: rm -r tmpe

In [81]:

1.8错误和调试

1.8.1控制异常:%xmode

当一个Python脚本未执行通过时,会抛出一个异常。当解释器捕获到这些异常中的一个时,可以在轨迹追溯(traceback)中找到引起这个错误的原因。

利用%xmode魔法函数,IPython允许你在异常发生时控制打印信息的数量。

In [1]: def func1(a, b):

...: return a / b

...:

...: def func2(x):

...: a = x

...: b = x - 1

...: return func1(a, b)

...:

In [2]: func2(1)

---------------------------------------------------------------------------

ZeroDivisionError Traceback (most recent call last)

in

----> 1 func2(1)

in func2(x)

5 a = x

6 b = x - 1

----> 7 return func1(a, b)

8

in func1(a, b)

1 def func1(a, b):

----> 2 return a / b

3

4 def func2(x):

5 a = x

ZeroDivisionError: division by zero

In [3]: %xmode?

Docstring:

Switch modes for the exception handlers.

Valid modes: Plain, Context, Verbose, and Minimal.

If called without arguments, acts as a toggle.

File: /Library/Python/3.7/site-packages/IPython/core/magics/basic.py

xmode有4中选项,默认就时Context

接下来显示Plain

In [4]: %xmode Plain

Exception reporting mode: Plain

In [5]: func2(1)

Traceback (most recent call last):

File "", line 1, in

func2(1)

File "", line 7, in func2

return func1(a, b)

File "", line 2, in func1

return a / b

ZeroDivisionError: division by zero

接下来显示Verbose

In [7]: func2(1)

---------------------------------------------------------------------------

ZeroDivisionError Traceback (most recent call last)

in

----> 1 func2(1)

global func2 =

in func2(x=1)

5 a = x

6 b = x - 1

----> 7 return func1(a, b)

global func1 =

a = 1

b = 0

8

in func1(a=1, b=0)

1 def func1(a, b):

----> 2 return a / b

a = 1

b = 0

3

4 def func2(x):

5 a = x

ZeroDivisionError: division by zero

In [8]:

最后时Minimal模式

In [8]: %xmode Minimal

Exception reporting mode: Minimal

In [9]: func2(1)

ZeroDivisionError: division by zero

显然Verbose时显示最丰富的。

1.8.2 调试:当阅读轨迹追溯不足以解决问题时

IPython的调试器时Ipdb,Python的时pdb,我现在还不是很熟悉pdb。。。

IPython中最方便的调试界面可能就时%debug魔法命令了。如果你在捕获异常后调用该调试器,它会在异常点自动打开一个交互式调试提示符。

ipdb提示符让你可以探索栈空间当前状态,探索可用变量,设置运行Python命令

In [10]: %debug

> (2)func1()

1 def func1(a, b):

----> 2 return a / b

3

4 def func2(x):

5 a = x

ipdb> print(a)

1

ipdb> print(b)

0

ipdb>

这个交互式调试器的功能不止如此,我们甚至可以设置单步入栈和出栈来查看各变量的值

In [11]: %debug

> (2)func1()

1 def func1(a, b):

----> 2 return a / b

3

4 def func2(x):

5 a = x

ipdb> up

> (7)func2()

4 def func2(x):

5 a = x

6 b = x - 1

----> 7 return func1(a, b)

8

ipdb> print(x)

1

ipdb> up

> (1)()

----> 1 func2(1)

ipdb> down

> (7)func2()

4 def func2(x):

5 a = x

6 b = x - 1

----> 7 return func1(a, b)

8

ipdb> down

> (2)func1()

1 def func1(a, b):

----> 2 return a / b

3

4 def func2(x):

5 a = x

ipdb> print(x)

*** NameError: name 'x' is not defined

ipdb> quit

ipdb 中的提示框后面的(2)func1()

这种, 表示运行的栈的区域,上面的就是表示运行在func1区域。

如果你希望在任何异常时都自动启动调试器,可以用%pdb魔法函数来启动这个自启动过程

In [15]: %pdb on

Automatic pdb calling has been turned ON

In [16]: func2(1)

ZeroDivisionError: division by zero

> (2)func1()

1 def func1(a, b):

----> 2 return a / b

3

4 def func2(x):

5 a = x

ipdb> print(b)

0

ipdb> q

部分调试命令

list    显示文件的当前路径

h(elp)   显示命令列表,或查找特定命令的帮助信息

q(uit)   退出调试器和程序

c(ontinue)    退出调试器,继续运行程序

n(ext)     跳到程序的下一步

  重复前一个命令

p(rint)    打印变量

s(tep)     步进子进程

r(eturn)     从子进程跳出

1.9 代码的分析和计时

%time

对单个语句的执行时间进行计时

%timeit

对单个语句的重复执行进行计时,以获取更高的精准度

%prun

利用分析器运行代码

%lprun

利用逐行分析器运行代码

%memit

测量单个语句的内存使用

%mprun

通过逐行的内存分析器运行代码

%time: Time the execution of a single statement

%timeit: Time repeated execution of a single statement for more accuracy

%prun: Run code with the profiler

%lprun: Run code with the line-by-line profiler

%memit: Measure the memory use of a single statement

%mprun: Run code with the line-by-line memory profiler

1.9.1 代码段计时:%timeit和%time

首先使用%timeit 使用很简单

In [1]: %timeit sum(range(100))

1.1 µs ± 27.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

因为这个操作很快,所以%timeit自动让代码重复运行了很多次。对于慢的,会自动调整并减少重复执行的次数。

In [2]: %%timeit

...: total = 0

...: for i in range(1000):

...: for j in range(1000):

...: total += i * (-1) ** j

...:

303 ms ± 2.79 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

有时候重复操作并不是一个最佳选择。例如,如果有一个列表需要排序,我们可能会被重复操作误导。对一个预先排好序的列表进行排序,比对一个无序的列表进行排序要快,所以重复运作将使结果出现偏差。

In [16]: import random

...: L = [random.random() for i in range(100000)]

...: %timeit L.sort()

410 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

1000次循环,第一次排序了以后,后面的L就使一个有序的列表了。

这样的情况下,可以使用%time来尝试

In [16]: import random

...: L = [random.random() for i in range(100000)]

...: %timeit L.sort()

410 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [17]: %time L.sort()

CPU times: user 896 µs, sys: 24 µs, total: 920 µs

Wall time: 970 µs

In [18]:

上面是对已经排序的列表再次进行排序,下面是全新的随机列表进行排序的时间

In [18]: L = [random.random() for i in range(100000)]

In [19]: %time L.sort()

CPU times: user 14.7 ms, sys: 49 µs, total: 14.7 ms

Wall time: 14.8 ms

%time就执行一次,由于%timeit会进行一些优化,比如阻止清理未利用的Python对象(即垃圾回收),所有通常情况下%timeit会比%time得到的结果要快

In [20]: %%time

...: total = 0

...: for i in range(1000):

...: for j in range(1000):

...: total += i * (-1) ** j

...:

CPU times: user 354 ms, sys: 1.57 ms, total: 356 ms

Wall time: 356 ms

1.9.2分析整个脚本

一个程序右很多的单个语句组成,有时候对整个脚本计时比单个语句计时更重要。IPython可以通过%prun这个魔法函数实现

In [24]: def sum_of_lists(N):

...: total = 0

...: for i in range(5):

...: L = [j ^ (j >> i) for j in range(N)]

...: total += sum(L)

...: return total

...:

In [25]: %prun sum_of_lists(1000000)

14 function calls in 0.530 seconds

Ordered by: internal time

ncalls tottime percall cumtime percall filename:lineno(function)

5 0.452 0.090 0.452 0.090 :4()

5 0.041 0.008 0.041 0.008 {built-in method builtins.sum}

1 0.028 0.028 0.521 0.521 :1(sum_of_lists)

1 0.009 0.009 0.530 0.530 :1()

1 0.000 0.000 0.530 0.530 {built-in method builtins.exec}

1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}

1.9.3 用%lprun进行逐行分析

用%prun对代码中的每个函数分析非常有用,但有时候逐行代码分析报告更加方便。该功能需要通过安装第三方的包来实现。首相安装line_profier包

pip install line_profiler

接着用IPython导入line_profiler包提供的IPython扩展

本来mac电脑装了老半天一直装不上去这个包,后面查寻后通过pip3 install Cython git+https://github.com/rkern/line_profiler.git --user进行了安装

In [3]: %load_ext line_profiler

In [5]: %lprun -f sum_of_lists sum_of_lists(5000)

Timer unit: 1e-06 s

Total time: 0.004989 s

File:

Function: sum_of_lists at line 1

Line # Hits Time Per Hit % Time Line Contents

==============================================================

1 def sum_of_lists(N):

2 1 3.0 3.0 0.1 total = 0

3 6 6.0 1.0 0.1 for i in range(5):

4 5 4820.0 964.0 96.6 L = [j ^ (j >> i) for j in range(N)]

5 5 159.0 31.8 3.2 total += sum(L)

6 1 1.0 1.0 0.0 return total

1.9.4 用%memit和%mprun进行内存分析

与前面line_profiler差不多,首先进行导包,后面进行魔法函数进行运行

内存分析扩展包有两个有用的魔法函数:%memit魔法函数(它提供的内存消耗计算功能类似于%timeit)和%mprun魔法函数(它提供的内存消耗计算功能类似于%lprun)。

%menit的使用很简单

In [7]: %load_ext memory_profiler

In [8]: def sum_of_lists(N):

...: total = 0

...: for i in range(5):

...: L = [j ^ (j >> i) for j in range(N)]

...: total += sum(L)

...: return total

...:

In [9]: %memit sum_of_lists(1000000)

peak memory: 152.33 MiB, increment: 79.62 MiB

这个函数消耗了150m内存

对于逐行代码内存消耗,可以用%mprun魔法函数。但很可惜,这个魔法函数仅仅对独立模块内部的函数有效,而对于Notebook本身不起作用。

所以后面先生成一个文件

In [14]: %%file mprun_demo.py

...: def sum_of_lists(N):

...: total = 0

...: for i in range(5):

...: L = [j ^ (j >> i) for j in range(N)]

...: total += sum(L)

...: del L # remove reference to L

...: return total

...:

Overwriting mprun_demo.py

In [15]: from mprun_demo import sum_of_lists

In [17]: %mprun -f sum_of_lists sum_of_lists(10000)

Filename: /Users/shijianzhong/mprun_demo.py

Line # Mem usage Increment Line Contents

================================================

1 91.4 MiB 91.4 MiB def sum_of_lists(N):

2 91.4 MiB 0.0 MiB total = 0

3 91.4 MiB 0.0 MiB for i in range(5):

4 91.4 MiB 0.0 MiB L = [j ^ (j >> i) for j in range(N)]

5 91.4 MiB 0.0 MiB total += sum(L)

6 91.4 MiB 0.0 MiB del L # remove reference to L

7 91.4 MiB 0.0 MiB return total

你可能感兴趣的:(python与数据思维基础笔记第一章_《Python数据科学手册》抄书笔记,第一章: Ipython 超越Python...)