Python 3.0科学计算指南(txt+pdf+epub+mobi电子书下载)


发布时间:2020-05-29 02:26:04

点击下载

作者:(瑞典)克劳斯·福勒(Claus Führer)简· 埃里克·索利姆(Jan Erik Solem)奥利维尔·维迪尔(Olivier Verdier)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python 3.0科学计算指南

Python 3.0科学计算指南试读:

前言

Python不仅可用于通用编程,其免费开源的语言和环境使得它在科学计算领域也具有巨大的潜力。本书呈现了Python与数学应用程序的紧密联系,展示了如何将Python中的各种概念用于科学计算目的,并给出了最新版的Python 3.0代码示例。在衔接科学计算和数学时,Python可以作为一个有效的工具来使用。本书将向读者介绍将其应用于线性代数、数组、绘图、迭代、函数以及多项式等的方法。本书内容

第1章介绍了Python的主要语法元素。本章不深入细节,仅对全书进行了概览。对于想要直接开始的读者来说,本章是一个好的起点。希望在后面的章节中理解某个示例(在深入解释函数之前可能会使用类似函数的结构)的读者可以将本章作为一个快速参考。

第2章介绍了Python中最重要的基本数据类型。浮点类型以及特殊数值类型nan和inf是科学计算中比较重要的数据类型。其他基本数据类型以及布尔类型、整型、复合类型和字符串类型都会在本书中用到。

第3章解释了如何使用容器类型,主要是列表的使用。本章分别以索引和循环的方式来访问容器对象,以便解释字典和元组。有时甚至会使用集合作为一个特殊的容器类型。

第4章介绍了如何使用线性代数中最重要的对象——向量和矩阵。本书选择NumPy数组作为描述矩阵甚至高阶张量的核心工具。该数组具有许多高级特征,还允许将通用函数作用于矩阵或向量元素。本书重点说明了数组索引、切片和点积等大多数计算任务中的基本操作。为了说明SciPy子模块linalg的用法,本章提供了一些线性代数的示例。

第5章解释了数组一些更高级的方面。对于数组副本和视图之间的区别,人们普遍认为视图让程序使用数组非常快,但这通常是错误的来源,而且很难调试。本章展示和说明了使用布尔数组来编写有效、紧凑和可读的代码,最后通过类比对函数执行的操作解释了阵列广播的技术(NumPy数组的一个独特特征)。

第6章展示了如何绘图,主要是经典的x / y二维绘图,还有三维绘图和直方图。科学计算需要好的工具将结果可视化。本章从其子模块pyplot便捷的绘图命令开始介绍Python中的Matplotlib模块。通过创建诸如axes的图形对象,可以实现对绘图的精细调整和修改。我们将说明如何更改这些对象的属性,并对其进行注释。

第7章介绍了构成编程中的基本构件——函数,函数可能是最接近底层的数学概念。函数定义和函数调用可以理解为设置函数参数的不同方式。我们在本书的各种示例中引入并使用了匿名的lambda函数。

第8章介绍了类的相关内容。类的实例即为对象,我们为其提供了方法和属性。在数学中,类的属性通常相互依赖,这需要对setter函数和getter函数使用特殊的编程技术。针对特殊的数学数据类型,可以定义基本的数学运算,例如+。继承和抽象是面向对象编程所反映的数学概念。本章通过一个简单的求解常微分方程的类展示了类继承的用法。

第9章使用循环和迭代器展示了迭代的用法。本书中没有专门设置循环和迭代的章节,但是讨论了迭代器的原理并创建了自己的生成器对象。在本章中,读者将了解为什么生成器可以被用尽以及如何编写无限循环程序。对本章来说,Python的itertools模块是一个不错的伴侣。

第10章介绍错误处理的内容,涵盖错误和异常以及查找和修复它们的方法。错误或异常是一个事件,它会中断程序单元的执行。本章展示了处理异常的方法。读者将学会定义自己的异常类以及如何提供可用于捕获这些异常的有价值的信息。异常处理不仅仅是打印一条错误消息。

第11章介绍了命名空间、范围和模块,涵盖了Python的模块。什么是局部变量和全局变量?变量对程序单元什么时候可知以及什么时候不可知?本章将就这些内容进行了讨论。变量可以通过参数列表传递给函数,也可以通过利用其作用域来默认注入。该技术什么时候应该使用以及什么时候不该使用?本章将试图对这一核心问题给出答案。

第12章介绍了输入和输出,涵盖了处理数据文件的一些选项。数据文件用于为一个给定的问题存储和提供数据,通常是大规模存储量。本章介绍了使用不同的格式来访问和修改这些数据的方法。

第13章重点关注科学计算程序的测试。核心工具是单元测试,它允许我们进行自动化测试和参数化测试。通过思考计算数学中的经典二分算法,我们举例说明了设计有用测试的不同步骤,副作用就是需要发布一段代码的使用文档。详细的测试会提供测试协议,这些测试协议在之后调试一段通常由多名程序员编写的复合代码时非常有用。

第14章展示了一些综合且较长的实例,并简要介绍了其理论背景及完整实现。这些例子使用了本书展示的所有结构,并将它们放在一个更大、更复杂的上下文中。读者可以随意地扩展它们。

第15章主要讨论符号计算。科学计算主要是伴随不精确数据和近似结果的数值计算。这与通常是正式操作的符号计算形成鲜明的对比,符号计算的目标是在闭合的表达式中得到精确的答案。在本书的最后一章中,我们介绍了Python的这项技术,其经常用于推导和验证理论上的数学模型和数值结果。我们将重点介绍符号表达式的高精度浮点评估。本书的阅读前提

读者需要安装Python 3.5或更高的版本、SciPy、NumPy、Matplotlib、IPython shell(我们强烈建议通过Anaconda安装Python及其软件包)。本书的示例在内存和显卡方面没有任何特殊的硬件要求。读者对象

本书是自2008年以来在隆德大学教授的Python科学计算课程的教学成果。多年来,课程不断地扩展,这些课程资料的简明版本曾用于科隆大学、特隆赫姆大学、斯塔万格大学、索伦大学、拉普兰塔大学的教学,同时也用于公司层面的计算任务。

我们坚信Python及其周边的科学计算生态系统——SciPy、NumPY和Matplotlib将在科学计算环境中取得巨大的进步。Python和前面提到的库都是免费和开源的。更重要的是,Python是一种可以添加一系列额外附加功能的现代语言。这些附加功能包括面向对象编程、可测试、IPython的高级shell命令等。在写这本书时,我们考虑到如下两类读者。● 选择将Python作为其第一门编程语言的读者将在教师主导的课程

中使用这本书。本书囊括了不同的主题,并提供背景阅读和实验。

教师通常会依据入门课程的学习效果来选择和订购本书的材料。● 已经具有编程经验以及喜欢科学计算或数学的读者,在潜心研究

SciPy 和 NumPy时可以将该书作为参考资料。比如说Python中的

编程与MATLAB中的编程有很大的不同。这本书想要说明“pythonic”的编程方式可以使编程成为一种享受。

我们的目标是阐明在科学计算环境中以Python开始的步骤。读者可以按顺序阅读,或者挑选你最感兴趣的部分阅读。毋庸置疑,提高一个人的编程技能需要大量的实践,因此实践书中所提供的示例和练习是非常明智的。

我们希望读者能使用Python、SciPy、NumPY和Matplotlib进行编程,并享受其中。Python vs.其他语言

要决定一本涉及科学计算的书籍使用什么编程语言,需要考虑许多因素。语言本身的学习门槛对初学者来说是非常重要的。脚本语言通常是最好的选择。对数值计算来说,大量的模块是必需的,最好还要有强大的开发者社区。如果这些核心模块建立在经过良好测试且优化过的快速库(例如 LAPACK)的基础之上,就会更好。最后,如果语言在更广泛的应用范围内也可以使用,读者更有机会在学术背景之外使用本书所学到的技能。因此我们很自然地选择了Python语言。

简单来说,Python具有如下特点。● 免费和开源。● 一种脚本语言,意味着它是解释型语言。● 一种现代语言(面向对象、异常处理、动态类型等)。● 简明、易读、易学。● 大量免费可用的库,特别是科学计算库(线性代数、可视化工具、

绘图、图像分析、微分方程求解、符号计算、统计等)。● 可用于更广泛的环境中:科学计算、脚本、网站、文本解析等。● 广泛应用于工业界。

有一些Python的替代语言,这里列出了其中一些,并给出了它们与Python的区别。● Java、C ++:面向对象的编译型语言。与Python相比,Java和C

++显得更加冗长和低级,几乎没有科学计算库。● C、FORTRAN:低级编译型语言。这两种语言都广泛应用于科

学计算。对于科学计算来说,计算时间很重要。现在通常将这些

语言与Python混合在一块。● PHP、Ruby以及其他解释型语言。PHP是面向Web开发的。

Ruby与Python一样灵活,但几乎没有科学计算库。● MATLAB、Scilab、Octave:MATLAB是用于科学计算的矩阵计

算工具,其拥有庞大的科学计算库,语言特性并不像Python那样

先进,既不免费,也不开源;SciLab和Octave是与MATLAB语法

相似的开源工具。● Haskell:Haskell是一种现代的函数式语言,与Python相比,其

遵循不同的编程范式。有一些通用的结构,比如列表解析。

Haskell很少用于科学计算,参见文献[12]。关于Python的其他文献

我们给出了一些有关Python文献的建议。这些文献可以作为补充资源或者作为并行阅读的文本材料。大多数有关Python的入门书籍都致力于将这种语言作为通用的工具。我们想在这里明确提出一个很好的例子就是文献[19],它通过简单的例子来解释语言,例如,用一个组建比萨店的例子来解释面向对象编程。

目前专门针对科学计算和工程的Python专著很少。我们想提一下Langtangen所著的两本书,这两本书将科学计算与现代的“pythonic”编程风格相结合,参见文献[16、17]。

这种“pythonic”编程风格也是我们教授数值算法编程方法的指导原则。我们试图展示在计算机科学中有多少成熟的概念和结构可应用于科学计算中的问题。比萨店的例子由拉格朗日多项式(Lagrange polynomials)代替,生成器成为ODE的时间步长方法等。

最后我们不得不提到网络上数不胜数的文献。在编写这本书时,网络也是一个主要的知识来源。网络文献通常包含新事物,但也可能是完全过时的。网络还会展示可能相互矛盾的解决方案和解释。我们强烈建议将网络作为附加资源,但更好的切入点是“传统的”教科书加上“编辑过的”网络资源,这足以帮助读者通往丰富且全新世界。排版约定

本书用不同的文本样式来区分不同种类的信息。下面给出了这些文本样式的示例及其含义。

文本中的代码文字、数据库表名、文件夹名称、文件名、文件扩展名、路径名以及用户输入表示如下:“install additional packages with conda install within your virtual environment”。

代码块的样式如下所示:from scipy import *from matplotlib.pyplot import *

任何命令行的输入或输出如下所示:jupyter notebook

新的术语和重要的单词都会以粗体显示。读者在页面上看到的单词,例如在菜单或对话框中,会像这样出现在文本中:“The Jupyter notebook is a fantastic tool for demonstrating your work.”此图标表示警告或需要特别注意的内容。  此图标表示提示或者技巧。  下载本书彩图

我们还为读者提供了一个PDF文件,其中包含了书中所使用的截图/图表的彩图。彩图将帮助读者更好地理解输出中的变化。读者可以从以下网站下载该文件,网址为www.epubit.com。勘误

如果读者在本书里发现了错误,可能是文字的或者代码中的错误,请访问http://www.epubit.com,选择相应图书,提交勘误详情。一经证实,读者所提出的勘误将被接收并上传至我们的网站,或加入已有的勘误列表中。第1章 入门

本章将简要介绍Python的主要语法元素,用以指导刚刚开始学习编程的读者。这里介绍的每一个主题都是以how-to的方式呈现的,本书稍后将以更深层概念的方式来解释它们,同时会用许多应用和拓展来丰富这些内容。

本章将会以Python的方式来构建经典的语言结构,以便帮助那些掌握了一门其他编程语言的读者快速入门Python编程。

我们鼓励以上两类读者将本章作为一个简明扼要的指南。然而在开始之前,我们必须确保一切准备就绪,并确保你安装了正确版本的Python以及用于科学计算的主要模块和工具,例如一个性能良好的代码编辑器和一个shell工具,这些将有助于代码的开发和测试。

即便你用的是已经安装过Python的计算机,也请阅读下面的内容,因为可能需要调整一些东西,以便使工作环境适合本书的演示内容。1.1 安装和配置说明

在深入本书主题之前,你应该在计算机上安装好所有相关的工具。我们会给你一些建议,并推荐一些你可能想要使用的工具,但仅限于通用和免费的工具。1.1.1 安装

Python目前有两个主要的版本:2.x分支和新的3.x分支。这些分支之间存在语言不兼容性,必须注意使用的是哪个分支。考虑到最新的发布版本是3.5,因此本书采用了基于3.x的分支。

你需要安装以下内容。● 解释器:Python 3.5(或以上版本)。● 用于科学计算的模块:SciPy和NumPy。● 用图形表示数值结果的模块:matplotlib。● Shell:IPython。● Python代码编辑器:Spyder见图1.1和Geany。

通过所谓的分发包,以上这些内容的安装将变得非常轻松。推荐使用Anaconda。Spyder代码编辑器的默认屏幕由位于左边的编辑窗口、右下角的可访问IPython shell命令的控制台窗口以及右上角的帮助窗口所组成,如图1.1所示。图1.1 Spyder代码编辑器1.1.2 Anaconda

即使你的计算机预先安装了Python,也推荐你创建自己的Python开发环境,以便你能“无意外风险”(不受计算机所依赖软件的影响)地工作。在一个虚拟的环境中,例如Anaconda,你可以随意地更改语言的版本并安装软件包,却不会有意外的副作用。

如果出现了最坏的情况,而且你把事情全部搞砸了,只需要删除Anaconda目录并重启。运行Anaconda安装包将安装Python、Python开发环境以及代码编辑器(Spyder)、Shell IPython以及最重要的数值计算包,如SciPy、NumPy和Matplotlib。

在Anaconda创建的虚拟环境中,可以使用conda install来安装其他附加的软件包(见参考文献[2]的官方文档)。1.1.3 配置

大多数Python代码都保存在文件中,因此建议在所有的Python文件中使用如下开头:from scipy import *from matplotlib.pyplot import *

经过这一步,应确保导入了本书用到的所有标准模块和函数,如SciPy。缺少这一步,本书中的大多数示例都会报错。许多代码编辑器,如Spyder,可用于为文件创建模板。找到此功能,并将上述开头放入模板中。1.1.4 Python Shell

Python Shell很好,但不是最佳的脚本交互方式,因此建议使用IPython来进行替代(见参考文献[26]的官方文档)。我们可以用不同的方式启动Ipython。● 在终端Shell中运行命令ipython。● 直接单击一个名为Jupyter QT Console的图标。● 使用Spyder代码编辑器时,应该使用IPython控制台(见图

1.1)。1.1.5 执行脚本

通常用户想要运行一个程序文件中的内容。这依赖于文件在计算机上的位置,在运行程序文件的内容之前,导航到正确的文件位置是非常有必要的。● 使用IPython中的命令cd,以便移动到文件所在的目录。● 要运行名为myfile.py的程序文件的内容,只需在IPython Shell中

运行如下命令:run myfile1.1.6 获取帮助

下面是一些关于如何使用IPython的小贴士。● 要获取有关对象的帮助信息,只需要在对象名后输入“?”,然

后返回。● 使用上下箭头键可以重用上一次执行的命令。● 可以使用Tab键完成输入(也就是说,写入变量或方法的第一个

字母,IPython会显示一个包含所有可能输入的菜单)。● 使用“Ctrl + D”组合键退出。● 使用IPython的魔法功能。可以通过在命令提示符上使用“%magic”来找到一个列表及其相关说明。可以在其在线文档中找到更多有关IPython的信息,见参考文献[15]。1.1.7 Jupyter – Python笔记本

Jupyter notebook是演示你工作的绝佳工具。学生可能想用它来制作、记录作业和练习;老师可以用它来备课,甚至制作幻灯片和网页。

如果已经通过Anaconda安装了Python,那么就拥有了Jupyter的所有功能。可以通过在终端窗口中运行以下命令来调用笔记本:jupyter notebook

此时将会打开一个浏览器窗口,用户可以通过Web浏览器与Python进行交互。1.2 程序与控制流

程序是按自上而下顺序执行的一系列语句。这个线性执行顺序会有一些重要的例外。● 可能有条件执行的语句组(块),我们将其称为分支。● 有重复执行的块,称为循环(见图1.2)。图1.2 程序流● 有一些函数调用是引用另一段代码,它在主程序流程返回之前执

行。函数调用打破了线性执行,并在程序单元将控制权传递到另

一个单元(即一个函数)时暂停执行。当被调用的函数执行完后,

它的控制权被交回到调用单元。

Python使用特殊语法来标记语句块:一个关键字、一个冒号和一个缩进的语句序列,它们属于一个块(见图1.3)。图1.3 块命令1.2.1 注释

如果程序的一行代码包含符号#,则同一行代码#后面的内容都将被视为注释:# 这是如下语句的注释a = 3 # ... 这里可能有更进一步的注释1.2.2 行连接

行末尾的反斜杠(\)将下一行标记为连续行,即显式行连接。如果行在所有圆括号关闭之前结束,则以下行将自动被识别为连续行,即隐式行连接。1.3 基本类型

本节介绍Python中的基本数据类型。1.3.1 数值类型

数字可以是整数、实数或复数。常用的运算符有以下几种。● 加法和减法:+和 − 。● 乘法和除法:*和/。● 幂:**。

这里有一个例子:2 ** (2 + 2) # 161j ** 2 # -11. + 3.0j复数的符号j是用于表示复数的虚部的符号。它是一个句法元素,不应该与变量的乘法混淆。有关复数的更多信息,请参见第2章的数值类型部分,变量和基本类型。  1.3.2 字符串

字符串是放在单引号或双引号中间的一系列字符序列:'valid string'"string with double quotes""you shouldn't forget comments"'these are double quotes: ".." '

还可以对多行的字符串使用三重引号:"""This is a long, long string"""1.3.3 变量

变量是对某个对象的引用。一个对象可能有好几个引用。可以使用赋值运算符“=”给一个变量赋值:x = [3, 4] # 创建了一个列表对象y = x # 该对象现在有两个标签:x和ydel x # 我们将其中一个标签删除del y # 两个标签均被删除:对象被删除

可以通过print函数来显示变量的值:x = [3, 4] # 创建了一个列表对象print(x)1.3.4 列表

列表是一个非常有用的数据结构,也是Python的基本类型之一。Python列表是放在方括号里面的有序对象列表,可以把从零开始的索引放在方括号里来访问列表的元素:L1 = [5, 6]L1[0] # 5L1[1] # 6L1[2] # 引发索引错误L2 = ['a', 1, [3, 4]]L2[0] # 'a'L2[2][0] # 3L2[-1] # 最后的元素: [3,4]L2[-2] # 倒数第二个元素: 1

元素的索引从零开始。可以将任何类型的对象放在列表中,甚至是其他的列表。一些基本的列表函数如下。● list(range(n))创建一个n个元素的列表, 元素从零开始:print(list(range(5))) #返回 [0, 1, 2, 3, 4]● len 给出一个列表的长度:len(['a', 1, 2, 34]) #返回4● append用于将元素添加到列表当中:L = ['a', 'b', 'c']L[-1] # 'c'L.append('d')L #L现在是['a', 'b', 'c', 'd']L[-1] # 'd'1.3.5 列表运算符● 运算符“+”连接了两个列表:L1 = [1, 2]L2 = [3, 4]L = L1 + L2 # [1, 2, 3, 4]● 正如人们所期望的那样,将列表与整数相乘,列表将重复自身几

次:● n*L相当于执行了n次加法操作L = [1, 2]3 * L # [1, 2, 1, 2, 1, 2]1.3.6 布尔表达式

布尔表达式是值可能为True或False的表达式。一些可以生成条件表达式的常用操作符如下。● ==(等于)。● !=(不等于)。● <、<=(小于、小于等于)。● >、>=(大于、大于等于)。

可以用or或者and来组合不同的布尔值。

关键字not给出了其后续表达式的否定逻辑值。比较可以被链接,例如使得x < y < z等价于x < y and y < z。不同的是,第一个例子中y只被求了一次值。

在这两种情况下,z都没有被计算,对于第一个条件x < y,算出的值为False:2 >= 4 # False2 < 3 < 4 # True2 < 3 and 3 < 2 # False2 != 3 < 4 or False # True2 <= 2 and 2 >= 2 # Truenot 2 == 3 # Truenot False or True and False # True!优先规则<,>、<=、> =、!=和==操作符的优先级比not更高。操作符and或or优先级最低。具有较高优先级规则的操作符在较低优先级规则之前进行计算。  1.4 使用循环来重复语句

循环用于重复执行一系列语句,同时将变量从一个变量修改为另一个变量。该变量称为索引变量。它依次分配给列表中的元素(见第9章):L = [1, 2, 10]for s in L: print(s * 2) # 输出: 2 4 20

在for循环中要重复的部分必须正确缩进:for elt in my_list: do_something something_elseprint("loop finished") # 在for块之外1.4.1 重复任务

for循环的典型用法是将某个任务重复执行固定的次数。n = 30for iteration in range(n): do_something # 此任务被执行n次1.4.2 break和else

for语句有两个重要的关键字:break和else。即使正在迭代的列表没有迭代完,break也将退出for循环:for x in x_values: if x > threshold: break print(x)

else检查for循环是否被break关键字中断,如果没有中断,则执行else关键字之后的代码块:for x in x_values: if x > threshold: breakelse: print("all the x are below the threshold")1.5 条件语句

本节介绍了如何使用条件语句来对代码进行分支、中断或者其他方式的控制。当条件语句为真时,其界定的代码块将被执行。如果条件不满足,将执行以关键字else开始的可选块(见图1.3)。下面通过打印x的绝对值| x |来展示这个过程:

等效的Python代码如下所示:x = ...if x >= 0: print(x)else: print(-x)

任何对象都可以被测试真值,用于if或while语句。有关如何获取真值的规则将在第2.3.5节进行说明。1.6 使用函数封装代码

函数用于将相似的代码收集在一个地方。考虑以下数学函数:

等效的Python代码如下所示:def f(x): return 2*x + 1

图1.4解释了一个函数块的组成要素。图1.4 函数解剖● 关键字def告诉Python解释器要定义一个函数。● f为函数的名称。● x是函数的参数或者称为函数的输入。● return语句后面的被称为函数的输出。

一旦定义了函数,就可以用以下方式的代码来调用它:f(2) # 5f(1) # 31.7 脚本和模块

文件(通常有一个py扩展名)中的语句集合称为脚本。假设将以下代码的内容放入名为smartscript.py的文件中:def f(x): return 2*x + 1z = []for x in range(10): if f(x) > pi: z.append(x) else: z.append(-1)print(z)

在Python或IPython Shell中,当打开和读取文件后,可以使用exec命令来执行这个脚本。代码如下:exec(open('smartscript.py').read())

IPython Shell提供了魔法命令%run,作为执行脚本的一种方便的替代方式:%run smartscript1.7.1 简单的模块——函数的集合

通常人们将函数收集在一个脚本文件中。这将创建一个具有额外功能的Python模块。为了说明这一点,下面通过将函数集合在一个单独的文件中来创建一个模块,如smartfunctions.py:def f(x): return 2*x + 1def g(x): return x**2 + 4*x – 5def h(x): return 1/f(x)● 这些函数现在可以由任意外部的脚本所使用,也可以直接在

IPython环境中使用。● 模块内的函数可以相互依赖。● 将函数按共同的主题或目的进行分组,使得模块可以被其他人共

享和使用。

再次强调,命令exec(open('smartfunctions.py'). read())使这些函数可用于你的IPython Shell(注意还有IPython的魔法函数run)。在Python术语中,一般说它们被放到了实际的命名空间中。1.7.2 使用模块和命名空间

另外,可以通过命令import导入模块。它创建了一个有名字的命名空间。命令from将函数放到了通用的命名空间中:import smartfunctionsprint(smartfunctions.f(2)) # 5from smartfunctions import g #仅输入此函数print(g(1)) # 0from smartfunctions import * #输入所有函数print(h(2)*f(2)) # 1.0Import命令import和from将函数导入相应的命名空间中。在导入之后更改函数对当前的Python会话没有影响。有关模块的更多信息,请参见第11章。  1.8 解释器

Python解释器按以下步骤执行。(1)运行语法。(2)逐行执行代码。(3)不执行函数或类声明中的代码(但是要检查语法)。def f(x): return y**2a = 3 # a和f在这里均被定义

因为没有语法错误,所以可以运行以上程序。只有当调用函数f时,才会出现错误。f(2) # 错误,y未被定义1.9 小结

本章简单地介绍了Python的主要语法元素而没有深入细节。

读者现在应该能够开始尝试一些简短的代码并测试不同的程序结构。所有这些都将作为以下章节的“开胃菜”。在后续章节中,我们将为你提供详细的资料、示例、练习以及更多的背景知识。第2章 变量和基本数据类型

本章将介绍Python中最重要和最基本的数据类型。什么是数据类型?它是由数据内容、表达式以及所有可能的操作符所组成的集合。稍后在本书的第8章介绍类的概念时,我们将会更精确地定义这一概念。2.1 变量

变量是对Python对象的引用,可以通过赋值运算符来创建变量,例如:a = 1diameter = 3.height = 5.cylinder = [diameter, height] #引用列表

变量名可以由任意的大小写字母、下画线和数字组合而成。变量名不能以数字开头。注意变量名是区分大小写的。好的变量命名是描述你工作的重要组成部分,因此我们建议使用描述性的变量名。

Python中有一些保留的关键字不能用作变量名(见表2.1)。尝试使用这些关键字作为变量名将会引发语法错误。表2.1  Python中的保留关键字andasassertbreakclasscontinuedefdelelifelseexceptexecFalsefinallyforfromglobalifimportinislambdaNonenonlocalnotorpassraisereturnTruetrywhileyield

与其他编程语言不同的是,Python变量不需要进行类型声明。可以用一个多重赋值语句来创建多个变量:a = b = c = 1 #变量 a、b、c 的值均为1

变量在它们定义后也可以被修改:a = 1a = a + 1 #a的值变为2a = 3 * a #a的值变为6

最后两个语句是通过使用增量运算符,将两个运算符分别直接与赋值运算符组合在一起来书写的:a += 1 #相当于 a = a + 1a *= 3 #相当于 a = 3 * a2.2 数值类型

在某些时候,你不得不与数字打交道,因此首先考虑Python中不同形式的数值类型。在数学中,我们区分了自然数(ℕ)、整数(ℤ)、有理数(ℚ)、实数(ℝ)和复数(ℂ),它们都是无限数集。这些集合之间的运算符各不相同,甚至可能还未被定义。例如,ℤ中两个数的通用除法运算可能得不到一个整数值——因为它并没有在ℤ上定义。

像其他计算机语言一样,Python中也有数值类型。● 数值类型int:理论上至少是整个ℤ。● 数值类型float:是ℝ的有限子集。● 数值类型complex:是ℂ的有限子集。

有限集有最大值和最小值,并且两个数值之间存在最小间距。更多详细信息,请参阅第2.2.2节。2.2.1 整数类型

整数类型是最简单的数值类型。普通整数

语句k = 3将一个整数赋值给变量k。

将+、− 或*运算符应用于整数会返回一个整数,除法运算符//会返回一个整数,而除法运算符/可能返回一个浮点数:6 // 2 # 37 // 2 # 37 / 2 # 3.5

Python中的整数集是无限的,没有最大的整数。这里的限制是计算机的内存,而不是语言给出的任何固定值。如果示例中的除法运算符(/)返回3,那么可能没有安装正确的Python版本。2.2.2 浮点数

如果在Python中执行语句a = 3.0,就创建了一个浮点数(Python数据类型:float)。这些浮点数是有理数ℚ的一个子集。

另外,常数可以用指数符号表示为a = 30.0e-1或简化为a = 30.e-1。符号e将指数与尾数分开,表达式显示为数学形式则为a = −130.0×10。浮点数指的是这些数字的内部表示,并在大范围内考虑数字时反映了小数点的浮动位置。

将基本数学运算符+、−、*和/作用于两个浮点数或一个整数与一个浮点数时,将返回一个浮点数。浮点数之间的运算很少返回像有理数运算一样精确的预期结果:0.4 - 0.3 #返回 0.10000000000000003

在浮点数比较时,这个事实很重要:0.4 - 0.3 == 0.1 #返回False1.浮点数表示法

浮点数在内部由4个量表示:符号、尾数、指数符号和指数。

其中,β∈ℕ,并且x≠0、0xβ。0i

x …x称为尾数,β为基数,e为指数| e |U,t称为尾数长度。0t−1条件x≠0使得其表示法是唯一的,并且在二进制( β = 2)的情况下0保存一位。

这里有两个浮点数零,分别是+0和−0,均以尾数0表示。

在一个典型的Intel处理器上, β = 2。要将数字用float类型表示,我们要使用64位,即符号为2位、尾数为t = 52位、指数| e |为10位。10因此,指数的上限U为2−1 = 1023。−1023−308

使用该数据,最小的可表示的正数为fl=1.0×2≈10,min1023308最大的可表示的正数为fl = 1.111…1×2≈10。max

注意,浮点数不是等距分布在[0,fl]里的,特别是0的间隙max−1023(见参考文献[29])。0和第一个正数之间的距离是2,而第一个−52−16正数和第二个正数之间的距离被因子2≈2.2×10缩小了。这种由标准化x≠0造成的影响如图2.1所示。0

这个间隙被低于正常的浮点数等距地填充,其结果由四舍五入获得。低于正常的浮点数具有最小的可能指数,并且不遵循前导数字x0必须与0不同的约定(见参考文献[13])。2.无穷与非数字

浮点数总共有个。有时执行一个数值算法可以得到这个范围之外的浮点数。

这将会产生数字的上溢或下溢。在SciPy中,将特殊浮点数inf赋值给溢出结果:exp(1000.) # infa = inf3 - a # -inf3 + a # inf

使用inf可能得不到数学意义上的结果。这在Python中是通过将另一个特殊的浮点数nan赋值给运算结果来表示的,nan代表非数字,也就是数学运算的一个未定义结果:a + a # infa - a # nana / a # nan

使用nan和inf执行运算时有一些特殊的规则。例如,nan与任意数值(甚至其本身)作比较,总是返回False:x = nanx < 0 # Falsex > 0 # Falsex == x # False

关于“nan永远不会等于它自己”这一令人吃惊的事实和结论,请参考练习4。

浮点数inf的计算结果比预期的要多得多:0 < inf # Trueinf <= inf # Trueinf == inf # True-inf < inf # Trueinf - inf # nanexp(-inf) # 0exp(1 / inf) # 1

检测浮点数nan和inf的一种方法是使用isnan和isinf函数。通常当一个变量值为nan或inf时,我们希望直接响应。这可以通过使用NumPy包的命令seterr来实现。如果某次计算的返回值是二者中的一个,则如下命令就会抛出一个错误:seterr(all = 'raise')3.下溢数——机器精度

如果某次运算得到一个落在0附近间隙的有理数,则发生下溢,如图2.1所示。图2.1 0上的浮点间隙,在这里t =3,U=1

机器精度或舍入单位ε 为最大数使得浮点数(1.0 + ε)= 1.0。1−−16t

注意,今天大部分计算机的ε ≈ β / 2 = 1.1102×10。在实际运行代码的计算机上,可以使用如下命令来访问有效值:import syssys.float_info.epsilon # 2.220446049250313e-16 (类似这样)

变量sys.float_info包含了更多关于计算机上的浮点类型的内部信息。

函数float可以将其他数据类型转换为一个浮点数(如有可能)。在将一段适当的字符串转换为数字时,该函数特别有用:a = float('1.356')4.NumPy中的其他浮点类型

NumPy还提供了其他的浮点类型,在其他编程语言中称为双精度和单精度数,即float64和float32:a = pi # 返回 3.141592653589793a1 = float64(a) # 返回 3.1415926535897931a2 = float32(a) # 返回 3.1415927a - a1 # 返回 0.0a - a2 # 返回 -8.7422780126189537e-08

倒数第二行表明变量a和a1的精度是相同的。在前两行中,它们只是展示的方式不同。精度的真正差异存在于变量a与其单精度副本a2之间。

NumPy包的函数finfo可用于展示有关这些浮点类型的信息:f32 = finfo(float32)f32.precision # 6 (十进制)f64 = finfo(float64)f64.precision # 15 (十进制)f = finfo(float)f.precision # 15 (十进制)f64.max # 1.7976931348623157e+308 (最大值)f32.max # 3.4028235e+38 (最大值)help(finfo) #查看更多选项2.2.3 复数

复数在许多科学和工程领域中经常被使用,它是对实数的扩展。1.数学中的复数

复数由两个浮点数组成,包括其实部a和虚部b。在数学中,复2数写作z = a + bi,通过i = −1将i定义为虚数单位。z的共轭复数对应的是。

如果实部a为零,则该数称为虚数。2.符号j

在Python中,虚数的特征在于其为后缀带有字母j的浮点数,例如z = 5.2j。复数是浮点数与虚数的总和,例如z = 3.5 + 5.2j。

在数学中,虽然虚部表示为实数b与虚数单位i的乘积,但在Python中,虚数的表示方式不是乘积——j只是一个后缀,表明该数为虚数。

下面的小实验证明了这一点:b = 5.2z = bj # 返回错误z = b*j # 返回错误z = b*1j # 正确

方法conjugate返回z的共轭:z = 3.2 + 5.2jz.conjugate() # 返回 (3.2-5.2j)3.实部和虚部

通过使用其属性real和imag,可以访问复数z的实部和虚部。这些属性是只读的:z = 1jz.real # 0.0z.imag # 1.0z.imag = 2 # 返回AttributeError: readonly attribute

复数是不可能被转化成实数的:z = 1 + 0jz == 1 # Truefloat(z) # 返回TypeError

有趣的是,real和imag属性以及共轭方法同样适用于复数数组(参见第4章)。下面通过计算z=i2πk/N,(k=0,…,N−1)的N次单位根来kN证明这一点,即方程z=1中N的解。N = 10# 以下矢量含有N次方根:unity_roots = array([exp(1j*2*pi*k/N) for k in range(N)])# 用real或者imag访问所有的实部或虚部:axes(aspect='equal')plot(unity_roots.real, unity_roots.imag, 'o')allclose(unity_roots**N, 1) # True

结果图(见图2.2)展示了单位根与单位圆的统一(有关绘图方法的更多详细信息,请参阅第6章)。图2.2 单位根与单位圆

当然,也可以与上面提到的方法一起使用,如下例所示:z = 3.2+5.2j(z + z.conjugate()) / 2. # 返回 (3.2+0j)((z + z.conjugate()) / 2.).real # 返回 3.2(z - z.conjugate()) / 2. # 返回 5.2j((z - z.conjugate()) / 2.).imag # 返回 5.2sqrt(z * z.conjugate()) # 返回 (6.1057350089894991+0j)2.3 布尔类型

布尔类型是以乔治·布尔(George Boole,1815—1864)命名的数据类型。一个布尔类型的变量只能取两个值,即True或False。这种数据类型主要用在逻辑表达式中,一些示例如下所示:a = Trueb = 30 > 45 #b的值为False

布尔表达式通常与if语句一起使用:if x > 0: print("positive")else: print("nonpositive")2.3.1 布尔运算符

在Python中,可以使用关键字and、or和not来执行布尔运算:True and False # FalseFalse or True # True(30 > 45) or (27 < 30) # Truenot True # Falsenot (3 > 4) # True

运算需要遵循一些优先级原则(见第1.1.5节),这会使第三行和最后一行中的括号过期(不管怎样,使用它们来增强代码的可读性是一个好的习惯)。注意,and运算符被隐式链接在以下布尔表达式中:a < b < c #相当于 a < b and b < ca == b == c #相当于 a == b and b == c

布尔值的转换规则见表2.2。表2.2  转换为布尔值的规则

BoolFalseTruestring"'not empty'numb0≠erlist[][…](not empty)tuple()(……)(not empty)arrayarray([])array([a])(a≠0)arrayarray([0]) array若数组含有一个以上的元素,则引发异常 2.3.2 布尔类型转换

大多数Python对象均可被转换为布尔类型,这被称作布尔类型转换。内置函数bool可执行该转化。注意大多数对象都被转换为True(0除外),而空元组、空列表、空字符串或空数组则被转换为False。

数组是不可能被转换为布尔值的,除非该数组不包含或只包含一个元素。我们将在第5章中进一步解释这个概念。表2.2汇总了一些布尔类型转换的规则。如下是一些使用示例:bool([]) # Falsebool(0) # Falsebool(' ') # Truebool('') # Falsebool('hello') # Truebool(1.2) # Truebool(array([1])) # Truebool(array([1,2])) # Exception raised!2.3.3 布尔类型自动转换

使用if语句作用于一个非布尔类型的数据,可使其转换为布尔值。换句话说,以下两个语句总是等效的:if a: ...if bool(a): # 与上面完全一样 ...

一个典型的示例是测试列表是否为空:# L 是一个列表if L: print("list not empty")else: print("list is empty")

空数组、空列表或空元组将返回False。还可以在if语句中使用一个变量,例如整数:# n是一个整数if n % 2: print("n is odd")else: print("n is even")

注意,在这里将%用于取模运算,将返回整数除法的余数。在该例中,将返回0或1作为对2执行取模运算之后的余数。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载