当您选择阅读本书时,我们认为您可能已经掌握 Python 的使用知识,如果不是,那是一位亲自动手的专家,他恰巧可以生存和呼吸 Python。 如果至少您对 Python 有一定的了解,则可以选择跳过此附录。 如果您不熟悉 Python 或正在寻找如何开始使用编程语言,阅读本附录将帮助您克服最初的障碍。 这也将为您带来享受本书各章所需的知识。 因此,事不宜迟,让我们开始吧!
Python 是一种通用的高级解释型编程语言,于 1991 年问世。它的创建者 Guido van Rossum 于 1989 年圣诞节开始编写该语言的解释,并以他最喜欢的电视之一命名该语言。 展示了 Monty Python 的飞行马戏团。
Python 强调通过空格缩进来界定代码块而不是大括号,从而强调代码的可读性,而在 C,C ++ 和 Java 中,大括号被广泛使用。 Python 的另一个强大功能是它的简洁性,它使程序员可以用比 C,C ++ 和 Java 更少的代码行来表达概念。 例如,在 Python 开发人员中,使用 lambda 函数作为仅一行声明函数的一种快速有效的方法就很受 Python 开发人员的欢迎。 (不用担心;稍后我们将介绍 lambda 函数。)除这些以外,Python 支持动态类型绑定并自动为您处理内存。 此外,Python 解释器可用于所有主要操作系统。 CPython 是解释器的最流行的开源实现。 此外,Python 受到数百种广泛功能包的支持,这些功能包包括网络开发,GUI 构建,高级内存管理,用于多种文件格式的文件处理,科学和数值计算,图像处理,机器学习,深度学习,大数据, 和许多其他。 PyPI 是 Python 软件包的官方存储库,几乎所有知名软件包都可以在那儿找到。 指向 PyPI 网站的链接为这个页面。 但是,在安装之前,我们不必从此网站下载软件包。 有命令行(CL)工具可以为我们完成工作。 一旦安装了该语言的基本版本,即可使用这些工具。 而且,通过确保所请求的软件包与当前版本的 Python 兼容并且已经安装或需要安装依赖项,这些 CL 工具需要我们大量工作。
本附录涵盖以下主题:
- 安装
- 基本数据类型
- 关键字,控制语句和功能
- 迭代器和生成器
- 类和对象
在您的计算机上设置 Python 需要安装三个组件-解释程序,集成开发环境(IDE)和支持应用开发的软件包。 值得庆幸的是,我们不必单独安装它们。 有将这三个捆绑在一起的软件包,并且一次安装可以最大程度地利用您的计算机。
有两种广泛使用的安装程序选项,它们将解释器,IDE 和有用的 Python 软件包捆绑在一起:
- 选项 1:捆绑了所有三个组件的安装程序可从这个页面下载。 该网站提供了几种不同版本的语言的安装程序。 在编写本书时,最新版本是 Python 3.2.6 和 Python 2.7.13。 安装程序附带一个基本的 IDE,是编写一些代码并了解该语言工作方式的好地方。 这些安装程序提供了一些软件包,例如文件处理,内存管理,数学计算等。 但是,有关科学计算,统计建模和机器学习的大多数软件包都需要与它们的依赖项一起单独安装。 这使此选项很耗时。
- 选项 2:我们可以从这个页面下载免费的安装程序。 Continuum Analytics 在将解释器,IDE 和数百个有用的软件包组合到同一安装程序中的工作非常出色。 这些软件包涵盖了您在数据科学项目上工作可能需要的大部分内容。 捆绑包中还包括 Jupyter Notebook 和 Jupyter Lab,这是流行的基于 Web 的 Python 开发工具。 软件包的完整列表位于这个页面。 这些安装程序被称为 Python 的 Anaconda 发行版。 Python 2.7 和 3.6 版本均可用。 本书示例中使用的大多数软件包都是 Anaconda 发行版的一部分。 我们只需要分别安装 Keras 和 Tensorflow。
下一节将介绍本书示例的所需步骤。
本书的代码示例是使用 Jupyter Notebook 开发环境编写的。 所有代码文件都具有.ipynb 扩展名,可以在该书的 GitHub 存储库的代码文件夹中找到。
要运行 Jupyter Notebook,您需要安装 Anaconda Python Distribution。 我们从这个页面下载了 Python 3.6 版本的发行版。
下载安装程序后,需要执行以下步骤来为示例设置环境:
- 安装 Anaconda Python 发行版。 按照标准安装的提示进行操作。 安装程序会将 Python 可执行文件的路径添加到 PATH 环境变量中。 安装程序会提示您添加到 PATH 变量。 阅读说明后,请确保单击“是”或“确定”,这将允许安装程序更新 PATH。
- 打开一个新的命令提示符窗口,然后运行以下命令:
python --version
- 这是为了确保将 Python 可执行文件添加到 PATH 变量中。
- 现在是时候设置编程环境来运行 Jupyter Notebook 了:
- 将图书的 GitHub 存储库“实用时间序列”克隆或下载到本地磁盘,例如 D。
- 打开一个新的命令提示符,然后运行以下命令:
D: (optional if default location is some other drive)
cd "Practical Time Series"
jupyter notebook -notebook-dir="."
- 第三步启动 Jupyter Notebook 服务器,并在默认浏览器中自动打开主页。 主页显示磁盘文件夹
D:\Practical Time Series
的文件夹和文件。 单击主页中的code
文件夹,您将看到 Jupyter 笔记本。 每个笔记本都有以下行,用于设置笔记本的当前工作目录:
os.chdir('D:/Practical Time Series')
- 如果已将
Practical Time Series
文件夹保存在 D 驱动器中,则无需更改此行。 否则,必须更改它以反映实际的当前工作目录。 例如,如果共享文件夹另存为C:\Local\Practical Time Series
,则将前一行代码更改为以下内容:
os.chdir('C/Local/Practical Time Series')
- Jupyter 笔记本中的代码段显示在带有灰色背景的矩形单元格中,如以下屏幕截图所示。 要运行笔记本,请单击“运行单元”按钮(按钮面板左侧的第八个按钮),从顶部开始依次执行每个单元:
像所有主要的编程语言一样,Python 支持基本的数字数据类型,例如 int,long 和 float。 None 表示 Python 中的空指针。
字符串是 Python 中的顺序数据类型。 Python 中常用的其他顺序数据类型是列表和元组。 列表和元组之间的区别在于,前者是可变的,而后者是不可变的类型。 因此,如果您尝试修改元组,则解释器将引发错误。 让我们更深入地研究列表和元组。
列表是元素的集合。 元素可以是任何数据类型,列表可以包含不同数据类型的元素。 列表具有几个重要功能,例如append
,extend
,insert
,index
,pop
等。 下表总结了这些功能的功能:
| 功能名称 | 功能 |
| append
| 在列表末尾添加一个新元素。 |
| extend
| 从迭代器添加新元素。 可迭代元素的成员分别输入到列表中。 在此表后面的代码示例中对此进行了演示。 |
| insert
| 在列表中的特定位置添加一个新元素。 |
| index
| 返回参数在列表中的位置。 如果在列表中找不到该参数,则将引发 ValueError。 |
| pop
| 从函数的参数指示的位置删除元素。 如果找不到此索引,则抛出 IndexError。 |
列表还具有其他一些功能。 有关更全面的摘要,我们建议使用任何教授 Python 语言的材料。
上表中提到的功能在 Jupyter Notebook code/Getting_started.ipynb
中进行了演示。 请注意,Python 使用零作为序列第一个元素的索引。 因此,mylist[0]
是第一个元素,mylist[1]
是第二个元素,依此类推。
与列表不同,元组是不可变的序列,并且在声明后就不允许进行任何更改。 元组仅支持两个函数,即 count 和 index,它们返回元组中元素的数量和现有元素的索引。 请求不存在的元素的索引将引发ValueError
。
通过将变量作为参数传递给函数,len
函数可用于查找列表的长度以及元组。
此外,列表和元组是可迭代的。 可迭代的技术定义是返回迭代器的任何对象。 在以下各节中,我们将详细讨论可迭代器和迭代器。 但是,暂时请记住,迭代器是对象,可以通过为对象运行循环来评估其各个元素。 以下代码演示了对列表和元组的迭代:
#iterating over a list
print('Elements in mylist:')
for i in mylist:
print(i)
print('Elements in mytuple:')
for i in mytuple:
print(i)
前面的代码段的输出如下:
Elements in mylist:
-1
2
3
4
5
6
[7, 8]
7
8
Elements in mytuple:
1
2
3
4
列表和元组中的元素也可以切成一定范围的索引。 切片是从原始序列创建子集的有效方法:
#slicing lists and tuple
print('Second to fifth elemnts of mylist:', mylist[1:6])
print('Last three elemnts of mytuple:', mytuple[-3:])
这将返回以下输出:
Second to fifth elements of mylist: [2, 3, 4, 5, 6]
Last three elements of mytuple: (2, 3, 4)
请注意,在前面的代码中用于切片mytuple
的负索引。 负索引允许从末尾开始遍历。 因此,-3
指示从末端开始的第三个位置。 从末尾开始的第一个位置是-1
的索引。
集是唯一元素的有序序列,并支持标准集操作,例如联合,交集和差异。 通过传递可迭代对象来创建集合。 集合支持弹出操作,但与列表不同,弹出功能仅删除集合的第一个成员。 在 Jupyter 笔记本code/Getting_started.ipynb
中给出了集合的示例。
字符串在 Python 2.x 中是 8 位字符的可迭代,在 Python 3.x 中是 Unicode 字符。 可以用多种方式声明字符串,以下代码片段中显示了其中的一些方式:
#string declarations
mystring = 'Practical Time Series'
print(mystring)
mystring = "Practical Time Series"
print(mystring)
mystring = """Practical Time Series"""
print(mystring)
mystring = '''Practical Time Series'''
print(mystring)
前面的所有四个声明均导致相同的字符串,并且print
函数在每种情况下均提供相同的输出:
Practical Time Series
字符串是 class,str 类型的对象,并支持使字符串处理变得容易的几个函数。 我们在 Jupyter 笔记本code/Getting_started.ipynb
中显示了一些示例。
Python 支持哈希图或关联数组。 哈希图中的每个元素都与定义或键相关联。 Dict 是 Python 中的基本 hashmap 实现。 字典中的元素称为值,它们映射到称为键的引用。 可以从键值对的可迭代实例化 dict。 这个可迭代的对象可以是列表,元组或迭代器,我们将在接下来的部分中进行讨论。 以下代码段显示了创建字典的多种方法:
mydict = dict([(0,1), (1,2), (2,3), (3,4), (4,5)])
mydict = dict([[0,1], [1,2], [2,3], [3,4], [4,5]])
mydict = {0:1, 1:2, 2:3, 3:4, 4:5}
可以通过调用将键作为输入的 get 方法来检索字典中的元素。 另一种方法是使用dictionary_variable[key]
。 对于不存在的键,get 函数返回 None,但是第二种方法抛出KeyError
错误。 函数项返回键-值对的迭代器。 所有对都不会在列表中返回,而是可以在迭代器上循环。
Python 是一种面向对象的编程语言,因此支持诸如对象的复杂数据类型,这些对象是类的实例,并具有属性和方法。 以下各节之一将介绍类和对象。
关键字是保留字,不能用作变量名。 下表列出了关键字及其用途:
| 关键字 | 解释 |
| False
| 布尔假值:>>bool_var = False
|
| True
| 布尔值真值:>>bool_var = True
|
| and
| 仅当两个操作数均为 True 或计算为 True 时,才返回 True 的逻辑运算符:>>a = 2``>>if a > 0:``print(a)``>>2
|
| as
| 为要导入的模块创建别名:import pandas as pd``import scikit-learn as skl
|
| assert
| 用于对逻辑表达式求值以在运行时检查变量的值,如果表达式的求值为 False,则会引发 AssertionError:>>a = -2``>> assert a > 0
前面的 assert 关键字引发 AssertionError。 |
| break
| 当满足条件时,用于退出循环,例如 for 循环或 while 循环。 |
| class
| 指示类声明的关键字。 |
| continue
| 指示解释器移至for
或while
循环中的下一个迭代,而无需在 continue 语句之后的循环中执行代码。 |
| def
| 指示函数声明。 |
| del
| 用于删除变量并释放与其关联的内存。 |
| if
| 用于检查以下变量或表达式是否满足条件,并在满足条件时执行代码。 |
| else
| 如果不满足前面的 if 语句检查的布尔条件,则执行代码。 |
| elif
| 如果不满足 if 语句中的前一个条件,则检查布尔条件。 |
| try
| 声明异常处理的范围,并在发生错误时将控制权传递给以下关键字除外的范围。 |
| except
| 定义作用域和其中的代码,当前面的 try 块引发错误时将执行该作用域。 |
| finally
| 定义范围和需要始终执行的代码,而不管在前面的 try 关键字中声明的代码产生异常如何。 |
| for
| 声明在序列的元素上进行迭代的迭代循环的范围。 |
| while
| 声明运行直到while
语句中的条件满足的迭代循环的范围。 |
| in
| 用于检查值是否存在于列表或元组之类的序列中:>>mylist = [1, 2, 3]``>>var = 1``>>var in mylist``>>True
也用于遍历序列:>>for i in mylist:``print(i)``>>1
|
| import
| 用于导入包:import os``import sys
|
| is
| 测试两个变量是否引用同一对象。 ==运算符检查两个变量是否相等。 |
| lambda
| 用于创建内联函数:>>func = lambda x: x+1``>>func(2)``>>3
|
| with
| 在上下文管理器定义的方法中包装代码块的执行,上下文管理器是实现__enter__
和__exit__
方法的类。 在嵌套的代码块的末尾调用__exit__
方法:with open('foo.txt', 'w') as f:``f.write('Practical Time Series')
执行此行后,文件将关闭。 这是可能的,因为文件对象具有__enter__
和__exit__
方法。 |
| yield
| 返回一个生成器,在以下部分之一中进行了介绍。 |
| return
| 退出函数并从中返回一个值。 |
| raise
| 用于显式引发错误:>>a = -2``>>if a < 0:``raise ValueError
前面的代码行生成 ValueError。 |
在 Python 中,函数分为三种类型:
- 内联函数
- 正常功能
- 内建功能
内联函数使用 lambda 关键字声明。 这种类型的函数声明可以命名或匿名。 匿名内联函数用于在另一个函数或代码块内声明一个函数,该函数或代码块循环一个序列并将内联函数应用于其元素。 命名的内联函数是单行函数声明,但具有函数名称:
#Inline anonymous function
mylist = [0, 1, 2, 3, 4, 5]
processed_list = list(map(lambda x: x+1, mylist))
#Inline named function
myfunc = lambda x: x+1
processed_list = [myfunc(i) for i in mylist]
print(processed_list)
请注意,在前面的代码块中使用了map
函数。 map
是 Python 中的预定义函数之一。 它接受一个匿名内联函数和一个 Iterable 作为输入,并将该内联函数应用于 Iterables 的每个元素。 map
函数的输出是一个新的可迭代函数,具有针对输入序列的每个元素的,由内联函数返回但由内联函数转换的值。
普通功能是使用 def 关键字定义的。 如果没有return
语句,普通函数将在其范围内执行代码并返回 None。 使用 return 语句,可以在调用函数时在函数外部获取普通函数的输出:
#Normal function which returns None
def myfunc(a):
print(Within the function:', a+1)
print('Return value of the function:', myfunc(5))
打印功能的输出如下:
Within the function: 6
Return value of the function: None
#Normal function which returns an output
def myfunc(a):
a = a+1
print('Wihtin the function:', a)
return a
print('Return value of the function:', myfunc(5))
最后一个打印功能的输出如下:
Within the function: 6
Return value of the function: 6
最后,Python 具有几个预定义的功能,例如range
,map
,filter
,zip
,enumerate
等。 富有表现力和简洁是 Python 设计哲学的两个关键要素。 为此,预定义功能仅需几行代码就可以帮助我们实现更多目标。 下表描述了预定义功能的功能:
| 功能 | 使用 |
| range
| 返回从开始到结束的整数序列。 在 Python 2.x 中,range 给出了一个列表,但是在 python 3.x 中,它返回了一个迭代器。 |
| map
| 遍历一个序列,并应用一个函数来转换每个元素。 函数和序列都作为映射的输入给出。 |
| filter
| 将一个序列作为输入并返回另一个序列,该序列由通过条件的元素组成。 函数和序列都作为输入传递到过滤器。 |
| zip
| 将两个或多个序列作为输入,并生成一个元组序列,每个元组都包含来自输入序列的元素。 |
| enumerate
| 从序列的元素生成(索引,值)对。 |
在 Python 2.x 中,所有这些函数都将列表作为输出返回,但是在 Python 3.x 中,它们返回迭代器。 为了获得实际的输出,必须在迭代器上循环。 如果输入序列太大而又太大而无法容纳计算机的内存,则此设计很有用。 例如,考虑一个巨大的文本文件,它必须与行号一起逐行读取。 在 Python 中,可以通过遍历文件读取器返回的迭代器逐行读取文件。 为了获得行号以及行号,我们可以使用文件迭代器调用枚举。 枚举函数将文件迭代器视为一个序列,并生成一个(line_number
,行)对的迭代器,可以将其逐个循环,而无需将整个文件加载到内存中。 我们刚刚提到的其他内置函数也可以采用类似的方法。 在 Jupyter Notebook code/Getting_started.ipynb
中,我们展示了如何将这些功能与文件阅读器一起使用。 我们建议您对其他类型的序列尝试类似的方法。
我们已经介绍了一些最常用的内置函数。 但是,建议您参考有关 Python 编程语言的书或教程以获取详尽的列表。
在 Python 中,我们经常遇到迭代器,可迭代器和生成器,因为它们是循环作为序列的数据类型或数据结构或可以从中创建序列的有效方法。 使用这些循环技术的一个明显优势是它们需要更少的内存。 因此,当您必须逐个元素地访问序列时,这些技术将变得非常有用,因为不需要将大序列立即全部加载到内存中。 例如,如果您需要找到前一万亿个正整数的平方,则无需创建一个数据结构来同时将所有数字保存在内存中。 迭代器,可迭代器和生成器可用于顺序生成和处理这些数字。 另一个示例是处理大型文本文件。 整个文件可能不适合内存。 因此,如果我们需要处理文件,例如查找文件每行的字数,则可以迭代遍历这些行并逐行处理它们。 由于迭代器,可迭代对象和生成器是如此有用,因此让我们了解它们是什么以及如何使用它们。
迭代器是具有__iter__
和 next 函数的类的实例的对象,并且可以与 for 循环一起使用以逐个顺序地遍历序列。 __iter__
函数可将对象识别为迭代器。 调用下一个函数以逐个获取序列的元素。 每次调用下一个函数时,它都会从预定义的序列中返回一个元素,或者创建一个元素。 因此,下一个功能可以实现创建元素的逻辑。 没有更多元素时,__next__
函数将引发 StopIteration 错误。
让我们通过示例来了解迭代器是如何工作的。 我们创建一个迭代器以从预定义的序列中返回元素:
class MyIterator(object):
def __init__(self, seq):
self.seq = seq
self.i = 0
def __iter__(self):
return self
def next(self):
if self.i < len(self.seq):
i = self.i
self.i += 1
return self.seq[i]
else:
raise StopIteration()
创建 MyIterator 类的对象,然后调用下一个函数五次。 前四个调用从序列中返回一个整数,但是最后一个调用导致下一个函数抛出StopIteration
错误,因为到目前为止已经遍历了序列的整个长度:
itr = MyIterator([1,2,3,4])
print(itr.next())
print(itr.next())
print(itr.next())
print(itr.next())
print(itr.next())
现在让我们声明一个迭代器,该迭代器在下一个函数中实现数据生成逻辑,而不是从预定义序列中返回元素:
class MyIterator(object):
def __init__(self, n):
self.n = n
self.count = 0
def __iter__(self):
return self
def next(self):
if self.count < self.n:
i = self.count
self.count += 1
return i
else:
raise StopIteration()
创建MyIterator
类的对象,然后调用下一个函数六次。 前五个调用返回下一个函数生成的正整数,但最后一次调用引发 StopIteration 错误:
itr = MyIterator(5)
print(itr.next())
print(itr.next())
print(itr.next())
print(itr.next())
print(itr.next())
print(itr.next())
不具有__iter__
或 next 函数但可用于创建迭代器的对象是可迭代的。 内置的__iter__
函数将顺序对象作为输入并返回迭代器。 然后,另一个内置函数接下来将使用迭代器,并在每次调用时返回迭代器的元素。 列表和元组不是迭代器,但可用于使用 next 函数创建迭代器。 以下代码片段演示了如何使用列表作为迭代器:
mylist = [1,2,3,4]
mylist_iter = iter(mylist)
print(type(mylist))
print(type(mylist_iter))
<class 'list'>
<class 'list_iterator'>
请注意,mylist
的类型为 list,而由 iter 函数创建的mylist_iter
的类型为list_iterator
。
生成器提供了迭代器的功能,但无需编写整个类。 在许多情况下,创建序列元素的逻辑是在迭代器的下一个功能中实现的。 例如,需要在迭代器的下一个函数中编写用于逐行读取文本文件并返回每一行中特定单词的出现的代码。 仅在满足开发迭代器的要求的情况下,在该类中实现了其他功能,例如__init__
和__iter__
。
生成器是简化开发的特殊功能。 函数中的 yield 关键字表示 Python 解释器该函数是生成器。 使用生成器函数,我们仅实现在 while 循环中在生成器函数中创建序列元素的逻辑。 每次调用函数时,yield 函数都会返回元素。
让我们实现一个生成器函数,该函数在每次被调用时返回一个整数:
def int_gen():
count = 0
while True:
i = count
count += 1
yield i
我们将生成器函数分配给一个变量,并在该变量上调用内置的 next 函数。 下一个函数将变量作为参数运行五次:
ig = int_gen()
print(next(ig))
print(next(ig))
print(next(ig))
print(next(ig))
print(next(ig))
打印输出如下:
0
1
2
3
4
每次在 ig 上调用下一个函数时,它都会返回 count 变量的当前值并将其递增 1。 计数变量保持在生成器的内部状态,因此可以返回其最新值。
类是变量和函数的逻辑分组。 class
关键字在 Python 中用于定义此类逻辑分组。 类通常代表现实生活中的实体,例如,书籍,作者,出版商等。 实体具有属性,这些属性由类中定义的变量表示。 类中的函数(通常称为方法)定义了如何捕获和转换有关实体实例的数据。 类的实例是实体的单个实现。 例如,书是一个实体,而实践时间序列分析是书的一个实例。 要创建实例,我们初始化一个类的对象。 对象定义涉及通过构造函数将值分配给类的变量。 该工作由__init__
方法完成,该方法接受输入并将其分配给类变量。 __init__
方法可以基于创建对象的逻辑在内部调用其他函数。 让我们定义一个关于书籍的类:
import datetime
class Book(object):
def __init__(self, name, date_of_publication, nb_pages, publisher):
self.name = name
self.date_of_publication = datetime.datetime.strptime(date_of_publication, '%Y-%m-%d')
self.nb_pages = nb_pages
self.publisher = publisher
self.authors = []
def add_author(self, author_name):
self.authors.append(author_name)
def print_date_of_publication(self, print_format='%Y-%m-%d'):
print(self.date_of_publication.strftime('%d-%m-%Y'))
现在,我们将创建Book
类的对象:
mybook = Book('Practical Time Series Analysis', '2017-09-15', 200, 'Packt')
请注意,__init__
方法未指定书的作者,而是创建了一个空列表,即作者。 我们可以在mybook
对象上调用 add_author 函数以添加作者。 另外,date_of_publication
最初设置为%Y-%m-%d
格式。 print_date_of_publication
函数以 print_format 作为输入,并以另一种格式显示日期。 例如,我们可以将发布日期打印为%d-%m-%Y
:
mybook.print_date_of_publication(print_format='%d-%m-%Y')
本附录介绍了 Python 编程语言的基础。 已经讨论了诸如数据类型,关键字,函数,类,迭代器,可迭代和生成器之类的主题。 这些编程技术构成了 Python 的构建块。
本书的各章使用了此处已讨论的几种概念和编程技术。