第 1 章:语言和语法¶
“优雅”是用来描述 Python 语言的形容词。优雅的定义是“在外观或举止上令人愉悦的优雅和时尚”。“简单”和“强大”也可以是用来描述这种语言的好词。事实上,Python 是一种优雅的语言,它允许人们以简单的方式创建强大的应用程序。让阅读和编写复杂软件变得更容易是所有编程语言的目标,而 Python 正是做到了这一点。
虽然我们在第一段中已经从广义上定义了编程语言的目标,但我们忽略了一个学习 Python 编程语言的主要优势:Python 已经被扩展到在 Java 平台上运行,因此它可以在任何有 JVM 的地方运行。Python 也有 C 和 .NET 版本,支持多平台。因此,Python 几乎可以在任何地方运行。在这本书中,我们重点关注 Jython,这种语言实现将 Python 的优雅、强大和易用性带到了 JVM 上。
Java 平台对于 Jython 语言来说就像 C 库对于 Python 一样。Jython 几乎可以在任何地方运行,这在决定如何实现应用程序时提供了很大的灵活性。Java 平台不仅在应用程序部署方面提供了灵活性,而且还提供了一个包含数千个 API 的庞大库,这些 API 可以供 Jython 使用。再加上 Java 平台的成熟度,不难看出为什么 Jython 如此吸引人。可以说,任何编程语言的目标都是让其开发者获得与 Jython 相同的体验。简而言之,学习 Jython 将是任何开发者的宝贵财富。
正如我提到的,Jython 语言实现将 Python 带到了 JVM 上,但它远不止于此。一旦你体验了在 Java 平台上编程的强大功能,你将很难离开它。学习 Jython 不仅允许你在 JVM 上运行,而且还允许你学习一种新的方式来利用平台的力量。这种语言提高了生产力,因为它具有易于理解的语法,读起来几乎就像伪代码一样。它还添加了 Java 语言本身没有的动态功能。
在本章中,你将学习如何安装和配置你的环境,你还会概述 Python 语言提供的功能。本章的目的不是深入探讨语法概念,让你感到厌烦,而是让你快速了解语法,让你了解基础知识,并在阅读本书的过程中学习语言。它还将让你有机会将一些 Java 示例与用 Python 编写的示例进行比较,这样你就可以看到这种语言提供的一些优势。
在完成本章后,您应该了解 Python 代码的基本结构和组织方式。您将了解如何使用基本语言概念,例如定义变量、使用保留字和执行基本任务。它将让您体验使用语句和表达式的滋味。由于每个优秀的程序都包含注释,您将学习如何记录单行代码以及整个代码块。随着您阅读本书,您将使用本章作为对基础知识的参考。本章不会涵盖每个功能的完整内容,但它将为您提供足够的入门知识,让您开始使用 Python 语言。
Jython 和 Python 之间的区别¶
Jython 是 Python 语言在 Java 平台上的实现。在本书中,您将学习如何使用 Python 语言,并在此过程中,我们将向您展示 Jython 实现与 CPython 的区别,CPython 是用 C 语言编写的 Python 的规范实现。需要注意的是,Python 语言语法在不同的实现中保持一致。在撰写本书时,Python 有三种主流实现。这些实现是:CPython、用于 Java 平台的 Jython 和用于 .NET 平台的 IronPython。在撰写本书时,CPython 是最流行的实现。因此,如果您在某个地方看到 Python 这个词,它很可能指的是该实现。
本书将在涉及语言语法或语言本身固有的功能的部分中引用 Python 语言。但是,本书将在讨论特定于 Java 平台实现的功能和技术时引用 Jython 这个名称。毫无疑问,本书将深入探讨 Jython 的关键特性,您将学习仅适用于 Jython 实现的概念。在此过程中,您将学习如何用 Python 编程以及高级技术。
来自所有语言和背景的开发人员都将从本书中受益。无论您是第一次学习 Python,还是发现 Jython 技术和高级概念,本书都是一个不错的选择。Java 开发人员和 Python 新手会对阅读本书的第一部分特别感兴趣,因为它将从基础知识到更高级的概念教授 Python 语言。经验丰富的 Python 开发人员可能会对第二部分和第三部分更感兴趣,因为它们更侧重于 Jython 实现的细节。在本参考中,您经常会看到 Java 代码与 Python 代码的比较。
安装和配置 Jython¶
在我们深入研究语言的基础知识之前,我们将学习如何获取 Jython 并为您的环境配置它。首先,您需要从官方网站 www.jython.org 获取 Jython 的副本。由于本书侧重于 2.5.x 版本,因此最好现在访问该网站并下载该版本的最新的版本。您会看到有以前发布的版本可供您使用,但它们不包含 2.5.x 系列中包含的许多功能。
Jython 实现维护一致的功能,这些功能与每个版本的 Python 语言中的功能相匹配。例如,如果您下载 Jython 2.2.1 版本,它将包含 Python 2.2 版本包含的所有功能。同样,在使用 2.5 版本时,您将可以使用 Python 2.5 中包含的相同功能。2.5 版本还包含一些特定于 Jython 的额外内容。我们将在本书中进一步讨论这些额外功能。
请获取最新版本的 Jython 2.5 版本。您会发现该版本打包为跨平台可执行 JAR 文件。您马上就能看到在 Java 平台上运行的明显优势……一个安装程序适用于各种平台。没有比这更简单的了!为了安装 Jython 语言,您需要在您的机器上安装 Java 5 或更高版本。如果您没有安装 Java 5 或更高版本,那么您最好从 www.java.com 下载并安装它,然后再尝试启动 Jython 安装程序。
您可以通过双击 JAR 文件来启动 Jython 安装程序。它将引导您完成一系列标准安装问题。在某个时刻,您需要确定要安装哪些功能。如果您有兴趣查看 Jython 的源代码,或者可能为该项目开发代码,那么您应该选择“全部”选项来安装所有内容……包括源代码。但是,对于大多数 Jython 开发人员,尤其是那些刚开始学习该语言的人来说,我建议选择“标准”安装选项。一旦您选择了选项并提供了安装路径,您就可以开始使用了。
为了运行 Jython,您需要在 Windows 上调用 jython.bat 可执行文件,或在 *NIX 机器和 Mac OS X 上调用 jython.sh 文件。也就是说,您需要进入安装 Jython 的目录,在那里您会找到该文件。最好将此目录放在 Windows、*NIX 或 OS X 机器上的 PATH 环境变量中,这样您就可以从机器上的任何目录启动 Jython。完成此操作后,您应该能够打开终端或命令提示符,然后键入“jython”,然后按回车键调用交互式解释器。这就是我们旅程的开始!Jython 交互式解释器是评估代码和学习该语言的好地方。它是一个实时测试环境,允许您键入代码并立即查看结果。在阅读本章时,我建议您打开 Jython 解释器并跟随代码示例进行操作。
标识符和声明变量¶
每种编程语言都需要包含捕获或计算值并存储它们的能力。Python 也不例外,这样做非常容易。在 Python 中定义变量与其他语言(如 Java)非常相似,但有一些需要注意的差异。
要在 Python 语言中定义变量,您只需使用标识符为其命名。标识符是用于标识对象的名称。该语言将变量名视为指向值的标签。它没有为该值提供任何类型。因此,这允许任何变量保存任何类型的数据。它还允许一个变量在程序的生命周期内包含不同类型的数据。因此,最初分配了整数的变量后来可以包含字符串。Python 中的标识符可以包含字母、数字或下划线的任何顺序。但是,标识符必须始终以非数字字符值开头。我们可以使用标识符来命名 Python 中的任何类型的变量、块或对象。与大多数其他编程语言一样,一旦定义了标识符,就可以在程序中的其他地方引用它。
一旦声明,变量就是无类型的,可以接受任何值。这是使用 Java 等静态类型语言和使用 Python 等动态语言之间的区别之一。在 Java 中,您需要声明要创建的变量的类型,而在 Python 中则不需要。乍一看可能没什么大不了,但这种能力可以带来一些非凡的结果。考虑以下两个列表,让我们在下面定义一个值“x”,并赋予它一个值为零的值。
清单 1-1. Java – 声明变量
int x = 0;
清单 1-2. Python – 声明变量
x = 0
如您所见,我们不必为该变量提供类型。我们只需选择一个名称并为其分配一个值。由于我们不需要为变量声明类型,因此我们可以在程序的后面更改它为不同的值和类型。
清单 1-3.
x = 'Hello Jython'
我们刚刚将变量 'x' 的值从数值更改为字符串,而没有任何后果。实际上发生的是,我们创建了一个新的变量 'Hello Jython' 并将其分配给标识符 'x',而 'x' 失去了对 0 的引用。这是动态语言哲学的关键……更改不应该困难。
让我们利用我们目前所知,将其应用于一些简单的计算。根据 Python 中变量的定义,我们可以将一个整数值分配给一个变量,并在稍后将其更改为浮点数。例如
清单 1-4。
>>> x = 6
>>> y = 3.14
>>> x = x * y
>>> print x
18.84
在前面的示例中,我们演示了可以通过简单地对给定变量执行计算来动态更改其类型。在其他语言(如 Java)中,我们必须首先将浮点类型分配给 'x' 变量,以便我们稍后可以将其值更改为浮点数。在这里则不然,Python 允许我们绕过类型限制,并提供了一种简单的方法来实现这一点。
保留字¶
为了遵守 Python 语言标准,创建标识符还有几个规则需要遵循。某些词语不能用作标识符,因为 Python 语言将它们保留用于在我们的程序中执行特定角色。这些不能使用的词语称为保留字。如果尝试将其中一个保留字用作标识符,我们将看到 Python 抛出 SyntaxError,因为它希望这些保留字作为其自身的一部分。
标识符中不允许使用任何符号。是的,这意味着 Perl 开发人员必须习惯在没有 $ 的情况下定义变量。
表 1-1 列出了所有 Python 语言保留字
表 1-1. 保留字
and | assert | break | class | continue |
def | del | elif | else | except |
exec | finally | for | from | global |
or | pass | raise | return | |
try | while | with | yield |
在命名变量时,务必小心,不要选择与标准库中的模块名称相同的名称。
编码结构¶
Python 与其他语言的不同之处在于其编码结构。过去,我们必须根据非常严格的结构开发程序,这样某些部分必须在某些标点符号内开始和结束。Python 使用缩进而不是标点符号来定义代码的结构。与使用括号来打开或关闭代码块的 Java 等语言不同,Python 使用空格来使代码更易于阅读,并限制代码中不必要的符号。它严格执行有序和组织化的代码,但它允许程序员定义缩进规则,尽管存在四个字符的标准。
例如,让我们提前看看一个简单的 'if' 语句。虽然您可能还不熟悉这种结构,但我认为您会同意它很容易确定结果。先看看用 Java 编写的以下代码块,然后我们将它与 Python 等效代码进行比较。
清单 1-5. Java if 语句
x = 100;
if (x > 0) {
System.out.println("Wow, this is Java");
} else {
System.out.println("Java likes curly braces");
}
现在,让我们看看用 Python 编写的类似代码块。
清单 1-6. Python if 语句
x = 100
if x > 0:
print 'Wow, this is elegant'
else:
print 'Organization is the key'
好吧,这有点俗套,但我们还是会继续讨论,因为它演示了 Python 语言的几个关键点。如您所见,Python 程序评估变量 'x' 的值是否大于零。如果是,它将打印 '哇,这很优雅。' 否则,它将打印 '组织是关键。' 请注意 'if' 块中使用的缩进。这段特定的代码块使用四个空格将 'print' 语句从块的初始行缩进。同样,'else' 跳回到行的第一个空格,其相应的实现也被缩进四个空格。这种技术必须在整个 Python 应用程序中坚持。通过这样做,我们获得了几个主要好处:易于阅读的代码,并且无需使用花括号。大多数其他编程语言(如 Java)使用方括号“[”或花括号“{”来打开和关闭代码块。使用 Python 时无需这样做,因为空格会为您处理这个问题。代码越少,越易于阅读和维护。还值得注意的是,示例中的 Java 代码可以写在一行上,或者更糟,但我们选择将其格式化得很好。
Python 确保每个代码块都以一致的方式遵循其定义的间距策略。定义的间距策略是什么?由你决定。只要代码块的第一行缩进至少一个空格,其余的块就可以保持一致的缩进,这使得代码易于阅读。许多人认为,正是 Python 遵循的结构化技术使它们如此易于阅读。毫无疑问,在整个应用程序中遵循标准间距有助于组织。如前所述,Python 的标准间距技术是使用四个字符进行缩进。如果你遵循这些标准,那么你的代码将易于阅读和维护。你的大脑似乎天生就习惯于某种形式的缩进,所以 Python 和你的大脑以相同的方式连接。
运算符¶
Python 使用的运算符与其他语言中使用的运算符非常相似……简单直观且易于使用。与任何其他语言一样,你拥有 +、-、* 和 / 等常规运算符,可用于执行计算。从以下示例中可以看出,使用这些运算符没有任何特殊技巧。
清单 1-7. 执行基于整数的运算
>>> x = 9
>>> y = 2
>>> x + y
11
>>> x - y
7
>>> x * y
18
>>> x / y
4
也许需要注意的最重要的一点是,如果你正在执行基于整数值的计算,那么你将获得一个四舍五入的结果。如果你正在执行基于浮点数的计算,那么你将获得浮点数结果,依此类推。
清单 1-8. 执行基于浮点数的运算
>>> x = 9.0
>>> y = 2.0
>>> x + y
11.0
>>> x - y
7.0
>>> x * y
18.0
>>> x / y
4.5
需要注意这种区别,因为从清单 1-7 和 1-8 中除法 (/) 运算结果的差异可以看出,我们在整数值上进行了四舍五入,而在浮点数上没有进行四舍五入。一个好的经验法则是,如果你的应用程序需要定义精确的计算,那么最好对所有数值变量使用浮点值,否则你将遇到四舍五入问题。在 Python 2.5 及更早版本中,整数除法总是向下取整,生成地板作为结果。在 Python 2.2 中,引入了 // 运算符,它是另一种在整数或浮点数相除时获得地板结果的方法。引入此运算符是为了在将来的版本中更改整数除法,以便结果是真正的除法。在第 3 章中,我们将讨论使用始终执行真正的除法的技术的除法。
表达式¶
表达式就是它们听起来的样子。它们是可以评估并产生值的 Python 代码片段。表达式不是对解释器的指令,而是对被评估的值和运算符的组合。如果我们希望根据两个变量或数值执行计算,那么我们正在生成一个表达式。
清单 1-9. 表达式的示例
>>> x + y
>>> x - y
>>> x * y
>>> x / y
上面显示的表达式示例非常简单。表达式可以变得非常复杂,并执行强大的计算。它们可以组合在一起以产生复杂的结果。
函数¶
通常,将执行特定任务的代码套件提取到它们自己的功能单元中会很不错,这样就可以在多个地方重复使用代码,而无需每次都重新键入。定义可重用代码片段的一种常见方法是创建函数。函数是执行通常执行一个或多个任务并返回值的命名代码部分。为了定义函数,我们使用def语句。
def语句将成为任何 Python 程序员一生中使用的第二自然语句。def语句用于定义函数。以下是一段简单的伪代码,展示了如何使用它。
清单 1-10.
def my_function_name(parameter_list):
implementation
上面的伪代码演示了如何使用def语句以及如何构建一个简单的函数。如你所见,def在定义函数时位于函数名称和参数列表之前。
清单 1-11.
>>> def my_simple_function():
... print 'This is a really basic function'
...
>>> my_simple_function()
This is a really basic function
此示例是关于可以创建的最基本形式的函数。如你所见,该函数包含一行代码,即 print 语句。我们将在本章后面更详细地讨论 print 语句;但是,你现在需要知道的是,它用于将一些文本打印到屏幕上。在这种情况下,每当调用该函数时,我们都会打印一条简单的消息。
函数可以接受参数,或其他程序变量,这些变量可以在函数的上下文中使用来执行某些任务并返回一个值。
清单 1-12。
>>> def multiply_nums(x, y):
... return x * y
...
>>> multiply_nums(25, 7)
175
如上所示,参数只是在调用函数时分配的变量。具体来说,我们在示例中将 25 分配给 *x*,将 7 分配给 *y*。然后,函数取 *x* 和 *y*,执行计算并返回结果。
Python 中的函数就像其他变量一样,如果需要,可以作为参数传递给其他函数。这里我们展示了一个将一个函数传递给另一个函数的基本示例。我们将 *multiply_nums* 函数传递给下面的函数,然后使用它来执行一些计算。
清单 1-13。
>>> def perform_math(oper):
... return oper(5, 6)
...
>>> perform_math(multiply_nums)
30
虽然这个例子非常基础,但您可以看到另一个函数可以作为参数传递,然后在另一个函数中使用。有关使用 *def* 和函数的更多详细信息,请参阅第 4 章,该章专门介绍函数。
类¶
Python 是一种面向对象的编程语言,这意味着语言中的所有内容都是某种类型的对象。就像积木用于建造建筑物一样,Python 中的每个对象都可以组合在一起构建程序片段或整个程序。本节将简要介绍 Python 类,它是这种语言中面向对象的关键之一。
类使用 *class* 关键字定义。类可以包含函数、方法和变量。方法就像函数一样,使用 *def* 关键字创建,并且接受参数。唯一的区别是方法接受一个称为 *self* 的参数,它指的是方法所属的对象。类包含一个称为初始化方法的内容,它在实例化类时自动调用。让我们看一个简单的例子,然后解释它。
清单 1-14。简单的 Python 类
>>> class my_object:
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def mult(self):
... print self.x * self.y
...
... def add(self):
... print self.x + self.y
...
>>> obj1 = my_object(7, 8)
>>> obj1.mult()
56
>>> obj1.add()
15
在这个类示例中,我们定义了一个名为 *my_object* 的类。该类接受两个参数,*x* 和 *y*。类初始化方法名为 *__init__()*,用于初始化类中可能使用的任何值。初始化程序还定义了可以传递给类以创建对象的哪些值。您可以看到类中的每个方法和函数都接受 *self* 参数。*self* 参数用于引用对象本身,这是类共享变量等的方式。*self* 关键字类似于 Java 代码中的 *this*。示例中的 *x* 和 *y* 变量在初始化程序中分别命名为 *self.x* 和 *self.y*,这意味着它们将在整个类中可用。在使用对象内的代码时,您可以将这些变量称为 *self.x* 和 *self.y*。如果您创建对象并为其分配一个名称,例如 *obj1*,那么您可以将这些相同的变量称为 *obj1.x* 和 *obj1.y*。
如您所见,该类通过向其传递值 7 和 8 来调用。然后,这些值在类初始化方法中分配给 *x* 和 *y*。我们将类对象分配给一个我们称为 *obj1* 的标识符。*obj1* 标识符现在保存对 *my_object()* 的引用,以及我们传递给它的值。*obj1* 标识符现在可以用来调用类中定义的方法和函数。
有关类的更多信息,请参阅第 6 章,该章介绍了 Python 中的面向对象。类非常强大,是构建大型程序的基本构建块。
语句¶
当我们提到语句时,我们实际上指的是包含执行某些操作的指令的代码行。语句告诉 Python 解释器执行任务。最终,程序是由表达式和语句的组合构成的。在本节中,我们将浏览语句关键字并了解如何使用它们。
让我们从列出这些不同的语句关键字开始,然后我们将详细介绍如何使用它们以及不同的示例。我不会在本节中介绍所有语句关键字,因为其中一些更适合在本章或本书的后面介绍,但是您应该对如何在阅读完本节后编写执行任务的操作有一个很好的了解。虽然本节将提供有关不同语句的实现细节,但您应该参考后面的章节以查找这些功能的高级用法。
表 1-2. 语句关键字
if-elif-else | for |
while | continue |
break | try-except-finally |
assert | def |
del | |
raise | import |
现在我们已经了解了每个关键字,是时候详细了解它们了。请记住,您不能将任何这些关键字用作变量名。
if-elif-else 语句¶
if 语句简单地对表达式进行评估,并根据其结果是True还是False执行不同的操作。如果表达式评估为True,则执行一组语句,如果评估为False,则执行另一组语句。if 语句通常用于根据代码中计算或提供的某些值将代码分支到一个方向或另一个方向。
伪代码如下
清单 1-15.
if <an expression to test>:
perform an action
else:
perform a different action
可以将任意数量的if/else语句链接在一起以创建逻辑代码分支。当在同一语句中有多个表达式需要评估时,可以使用elif语句将这些表达式链接在一起*。请注意,*if-elif-*else 语句中的每一组语句都必须缩进,条件语句缩进,结果语句缩进。请记住,在整个程序过程中必须遵循一致的缩进。*if语句很好地说明了一致使用缩进如何提高程序的可读性。例如,如果您使用 Java 编码,您可以根据需要对代码进行空格,只要使用大括号将语句括起来即可。这会导致代码难以阅读……Python 所要求的缩进在这里非常有用。
清单 1-16. if 语句示例
>>> x = 3
>>> y = 2
>>> if x == y:
... print 'x is equal to y'
... elif x > y:
... print 'x is greater than y'
... else:
... print 'x is less than y'
...
x is greater than y
虽然代码很简单,但它表明使用if语句会导致代码逻辑分支。
print 语句¶
print语句用于将程序输出显示到屏幕上(您已经多次看到它在起作用)。它可以用于显示从程序中打印的消息,以及打印可能已计算出的值。为了在 print 语句中显示变量值,我们需要学习如何使用 Python 提供的一些格式选项。本节将介绍使用 print 语句的基础知识以及如何通过格式化文本字符串来显示值。
在 Java 语言中,我们需要调用 System 库才能将内容打印到命令行。在 Python 中,可以使用print语句来完成此操作。print语句最基本的使用方法是显示一行文本。为此,您只需将要显示的文本用单引号或双引号括起来。请查看以下用 Java 编写的示例,并将其与紧随其后的用 Python 重写的示例进行比较。我认为您会明白为什么 Python 中的print语句让生活更轻松。
清单 1-17. Java 打印输出示例
System.out.println("This text will be printed to the command line");
清单 1-18. Python 打印输出示例
print 'This text will be printed to the command line'
从这个示例中可以看出,在 Python 中打印一行文本非常简单。我们还可以使用print语句将变量值打印到屏幕上。
清单 1-19.
>>> my_value = 'I love programming in Jython'
>>> print my_value
I love programming in Jython
再次强调,在打印变量值方面非常简单。只需将变量放在 print 语句中即可。我们还可以使用此技术将变量的值附加到一行文本。为此,只需将连接运算符 (+) 放在要附加到的文本字符串和要附加的变量之间即可。
清单 1-20.
>>> print 'I like programming in Java, but ' + my_value
I like programming in Java, but I love programming in Jython
这很好,但如果您想正确格式化文本或使用int值,则实际上没有用。毕竟,Python 解析器在这种情况下将 (+) 运算符视为连接运算符……而不是加法运算符。Python 根据第一个操作数的类型确定 (+) 运算符的结果。如果您尝试将数值附加到字符串,您将遇到错误。
清单 1-21.
>>> z = 10
>>> print 'I am a fan of the number: ' + z
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
正如您从这个例子中看到的,Python 并不喜欢这种技巧。因此,为了正确地执行此任务,我们需要使用前面提到的 Python 格式化选项。这很容易且功能强大,它允许您将任何内容或值放入打印语句中。在您看到示例之前,让我们先看看一些格式化运算符以及如何选择您需要的运算符。
%s | 字符串 |
%d | 十进制 |
%f | 浮点数 |
如果您希望在您的print语句中包含变量的内容或表达式的结果,您将使用以下语法
清单 1-22。
print 'String of text goes here %d %s %f' % (decimalValue, stringValue, floatValue)
在上面的伪代码中(如果我们真的可以为打印语句使用伪代码),我们希望打印文本字符串,该字符串包含在单引号中,但也包含变量的值,这些值位于格式化运算符所在的位置。每个格式化运算符都包含在文本字符串中,将被打印语句末尾的相应变量值替换。文本行和变量列表之间的 % 符号告诉 Python 它应该期望变量跟随,并且这些变量的值应该放置在文本字符串中的相应位置。
清单 1-23。
>>> string_value = 'hello world'
>>> float_value = 3.998
>>> decimal_value = 5
>>> print 'Here is a test of the print statement using the values: %d, %s, and %f' % (decimal_value, string_value, float_value)
Here is a test of the print statement using the values: 5, hello world, and 3.998000
如您所见,这非常易于使用且非常灵活。下一个示例表明我们也有选择在语句中使用表达式而不是变量的选项。
清单 1-24。
>>> x = 1
>>> y = 2
>>> print 'The value of x + y is: %d' % (x + y)
The value of x + y is: 3
使用的格式化运算符决定了输出的外观,它不关心传递给运算符的输入类型。例如,我们可以将整数或浮点数传递给 %s,它会正常打印,但实际上它将被转换为其精确格式的字符串。如果我们将整数或浮点数传递给 %d 或 %f,它将被正确格式化为分别表示十进制或浮点数。请查看以下示例以查看每个不同格式化运算符的输出。
清单 1-25。
>>> x = 2.3456
>>> print '%s' % x
2.3456
>>> print '%d' % x
2
>>> print '%f' % x
2.345600
print 语句的另一个有用功能是它可以用于调试目的。如果我们只需要在处理过程中找出变量的值,那么使用print语句很容易显示出来。使用这种技术通常可以真正帮助调试和编写代码。
try-except-finally¶
try-except-finally是 Python 应用程序中执行错误处理的受支持方法。其理念是,我们尝试运行一段代码,如果它失败,则会捕获它,并以适当的方式处理错误。我们都知道,如果有人使用一个显示难看的长错误消息的程序,通常不会被欣赏。使用try-except-finally语句来正确捕获和处理我们的错误可以减轻难看的程序转储。
这种方法与许多语言(包括 Java)中使用的概念相同。Python 编程语言中定义了许多错误类型,我们可以利用这些错误类型来促进try-except-finally过程。当捕获到其中一个定义的错误类型时,可以为处理错误编写一组代码,或者可以简单地将其记录、忽略等等。主要的想法是避免那些难看的错误消息,并通过显示格式化的错误消息或执行其他过程来整齐地处理它们。
清单 1-26。
>>> # Suppose we've calculated a value and assigned it to x
>>> x
8.97
>>> y = 0
>>> try:
... print 'The rocket trajectory is: %f' % (x/y)
... except:
... print 'Houston, we have a problem.
...
Houston, we have a problem.
如果在代码块中捕获到一个异常,我们需要一种方法来执行一些清理任务,我们将把清理代码放在块的finally子句中。finally子句中的所有代码总是在异常被抛出之前被调用。有关此主题的详细信息,请参阅第 7 章。在下一节中,我们将看看raise语句,我们可以使用它在程序中的任何地方抛出异常。
raise 语句¶
如上一节所述,raise语句用于在 Python 中抛出或“引发”异常。我们知道,如果 Python 决定抛出异常,则需要一个try-except子句,但是如果您想自己抛出异常怎么办?您可以在您希望抛出指定异常的任何地方放置一个raise语句。语言中定义了许多可以抛出的异常。例如,当特定代码未定义或没有名称时,会抛出 NameError。有关 Python 中异常的完整列表,请参阅第 7 章。
清单 1-27。
>>> raise NameError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError
如果您希望在raise中指定您自己的消息,您可以通过抛出一个通用的 Exception 来做到这一点,然后在语句中指定您的消息,如下所示。
清单 1-28。
>>> raise Exception('Custom Exception')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: Custom Exception
import 语句¶
一个程序可以由一个或多个代码套件组成。为了保存程序以便以后使用,我们将代码放入计算机上的文件中。包含 Python 代码的文件应该包含一个.py后缀,例如 my_code.py 等等。这些文件在 Python 世界中被称为模块。import语句的使用方式与其他语言类似,它将外部模块或代码引入程序,以便使用。此语句最终负责在多个位置重用代码。import语句允许我们将代码保存到平面文件或脚本中,然后在以后的时间在应用程序中使用它。
如果一个类存储在一个与类本身同名的外部模块中,则可以使用import语句将该类显式地引入应用程序。类似地,如果您希望从另一个模块导入特定标识符到当前模块,则可以使用语法from <<module>> import <<specific code>>来命名特定代码。现在让我们看一些例子。
清单 1-29。
# Import a module named TipCalculator
import TipCalculator
# Import a function tipCalculator from within a module called ExternalModule.py
from ExternalModule import tipCalculator
在将模块导入程序时,必须确保要导入的模块不会与当前程序中的其他名称冲突。要导入与当前程序中的另一个标识符同名的模块,可以使用as语法。在下面的示例中,假设我们定义了一个名为tipCalculator.py的外部模块,并且我们希望在当前程序中使用它的功能。但是,我们已经在当前程序中定义了一个名为tipCalculator()的函数。因此,我们使用as语法来引用tipCalculator模块。
清单 1-30。
import tipCalculator as tip
本节只是简单介绍了导入和使用外部模块。有关更详细的讨论,请参阅专门介绍此主题的第 7 章。
迭代¶
Python 语言有几种迭代结构,用于遍历列表、数据库记录或任何其他类型的集合中的项目。Python 中的列表是一个包含对象或值的容器,可以被索引。例如,我们在下面的示例中创建了一个数字列表。然后,我们使用索引值 1 获取列表中的第二个元素(索引从零开始,所以列表的第一个元素是 my_numbers[0])。
清单 1-31。
>>> my_numbers = [1, 2, 3, 4, 5]
>>> my_numbers
[1, 2, 3, 4, 5]
>>> my_numbers[1]
2
有关列表的更多信息,请参阅第 2 章,该章详细介绍了列表和其他可以在 Python 中使用的容器。
语言中最常用的迭代结构可能是for循环,它以其简单的语法和实际用途而闻名。
清单 1-32。
>>> for value in my_numbers:
... print value
...
1
2
3
4
5
但是,while循环在迭代中仍然发挥着重要作用,尤其是在处理数据集合时,而是处理条件表达式。在这个简单的示例中,我们使用while循环来迭代my_numbers的内容。请注意,len()函数只是返回列表中包含的元素数量。
清单 1-33。
>>> x = 0
>>> while x < len(my_numbers):
... print my_numbers[x]
... x = x + 1
...
1
2
3
4
5
本节将带您了解这两种迭代结构,并介绍使用它们的入门知识。while循环的使用相对简单,而使用for循环时,有许多不同的实现和选择。在本入门章节中,我将只从高级角度介绍for循环,但如果您想深入了解,请参阅第 3 章。
While 循环¶
while循环结构用于根据提供的条件语句迭代代码。只要条件为真,循环就会继续处理。一旦条件评估为假,循环就会结束。while循环逻辑的伪代码如下
while True
perform operation
循环从while和条件表达式的声明开始,并在满足条件且表达式为True时结束。表达式在每次循环序列的开始时都会被检查,因此通常表达式中包含的某个值会在循环内部的语句套件中发生改变。最终,该值会以某种方式改变,使表达式评估为 False,否则就会发生无限循环。请记住,我们需要缩进while循环中存在的每一行代码。这不仅有助于代码保持可读性,而且还允许 Python 抛弃大括号!
清单 1-34. Java While 循环示例
int x = 9;
int y = 2;
while (y < x) {
System.out.println("y is " + (x-y) + " less than x");
y += 1;
}
现在,让我们看看用 Python 编写的相同代码。
清单 1-35. Python While 循环示例
>>> x = 9
>>> y = 2
>>> while y < x:
... print 'y is %d less than x' % (x-y)
... y += 1
...
y is 7 less than x
y is 6 less than x
y is 5 less than x
y is 4 less than x
y is 3 less than x
y is 2 less than x
y is 1 less than x
在这个例子中,你可以看到条件表达式 y < x 在每次循环执行时都会被评估。在循环过程中,我们每次迭代都会将 y 的值增加 1,因此最终 y 将不再小于 x,循环结束。
For 循环¶
我们将在本章中简单介绍 for 循环,但你可以在第二章或第三章中深入学习这个主题,届时将讨论列表、字典、元组和范围。现在,你应该知道 for 循环用于遍历一组定义的值。for 循环对于遍历值非常有用,因为这是一个在几乎所有应用程序中都会用到的概念。例如,如果你检索到一个数据库值的列表,你可以使用 for 循环遍历它们并打印出每个值。
for 循环逻辑的伪代码如下所示
for each value in this defined set:
perform suite of operations
正如你在伪代码中看到的,我使用了与其他表达式结构相同的缩进方式。这种统一的缩进习惯在整个 Python 编程语言中都是一致的。我们将在下面将 Java 中的 for 循环与 Python 语法进行比较,以便你了解后者如何使代码更加简洁。
清单 1-36. Java For 循环示例
for (int x = 0; x <= 10; x++) {
System.out.println(x);
}
现在,在 Python 中实现相同的代码
清单 1-37. Python For 循环示例
>>> for x in range(10):
... print x
...
0
1
2
3
4
5
6
7
8
9
在这个例子中,我们使用了一个尚未讨论的结构。范围是 Python 的一个内置函数,它简单地提供从一个特定值到另一个值的范围。在这个例子中,我们将值 10 传递给范围,这将给我们所有介于 0 和 10 之间的值,包括前面的零,但不包括末尾的 10。我们在表达式执行后的打印输出中看到了这一点。
基本键盘输入¶
Python 语言有几个内置函数可以从键盘获取输入,以方便编写允许用户输入的应用程序。具体来说,raw_input() 和 input() 可以用来提示并接受来自命令行的用户输入。这不仅对创建命令行应用程序和脚本很有用,而且对于在应用程序中编写小型测试也很有用。
raw_input() 函数接受键盘输入并将其转换为字符串,同时去除尾部的换行符。类似地,input() 函数接受键盘输入,就像 raw_input() 一样,但它会将其评估为表达式。input() 函数应该谨慎使用,因为它期望输入一个有效的 Python 表达式。如果输入的不是有效的 Python 表达式,它将引发 SyntaxError。使用 input() 可能导致安全问题,因为它基本上允许用户随意运行任意 Python 代码。在大多数情况下,最好避免使用 input(),而只使用 raw_input。让我们看一些使用这两个函数的基本示例。
清单 1-38. 使用 raw_input() 和 input()
# The text within the function is optional, and it is used as a prompt to the user
>>> name = raw_input("Enter Your Name:")
Enter Your Name:Josh
>>> print name
Josh
# Use the input function to evaluate an expression entered in by the user
>>> val = input ('Please provide an expression: ')
Please provide an expression: 9 * 3
>>> val
27
# The input function raises an error if an expression is not provided
>>> val = input ('Please provide an expression: ')
Please provide an expression: My Name is Josh
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
My Name is Josh
^
SyntaxError: invalid syntax
本书后面将提供使用 raw_input() 函数的不同方法的示例。现在让我们看看本章中尚未介绍的其他一些 Python 语句。
其他 Python 语句¶
还有一些其他 Python 语句可以在应用程序中使用,但它们可能更适合在后面的章节中讨论,因为它们提供了更高级的功能。以下是将在后面章节中详细介绍的其他 Python 语句的列表
exec - 以动态方式执行 Python 代码
global — 引用全局变量(第四章)
with - 2.5 中使用 __future__ 的新功能
class - 创建或定义一个新的类对象(第六章)
yield — 与生成器一起使用,返回一个值(第四章)
代码文档¶
代码文档:每个应用程序开发人员生活中一个令人讨厌但又重要的部分。虽然我们中的许多人讨厌代码文档,但对于任何将用于生产目的的应用程序来说,它都是必须存在的。适当的代码文档不仅是管理和长期理解 Python 代码片段的必要条件,而且在调试某些代码时也起着重要作用,正如我们在下面的示例中将看到的那样。
有时我们希望记录整个函数或类,而有时我们只希望记录一两行代码。无论哪种情况,Python 都提供了一种以一种相当不显眼的方式来做到这一点的方法。就像今天存在的许多其他编程语言一样,我们可以在任何代码行的任何部分开始注释。如果我们愿意,我们也可以跨越多行进行注释。就个人而言,我们更喜欢 Python 文档符号 (#) 或哈希,因为它提供了清晰易读的代码。除非你试图进行一些文档记录,否则在代码中很少有地方会使用 (#) 符号。许多其他语言使用 (/) 等符号,这会使代码更难阅读,因为这些符号在许多其他非文档代码片段中都很常见。好了,是时候从我的 Python 讲台上下来,开始干活了。
为了记录代码行,您只需在文档或注释的开头使用 (#) 符号。此符号可以放置在行的任何位置,它后面的任何内容都会被 Python 编译器忽略,并被视为注释或文档。符号之前的任何内容将按预期解析。
清单 1-39。
>>> # This is a line of documentation
>>> x = 0 # This is also documentation
>>> y = 20
>>> print x + y
20
如您所见,Python 解析器会忽略 # 之后的任何内容,因此我们可以轻松地根据需要进行文档记录或注释。
可以使用 # 符号轻松地记录多行代码,方法是在每行的开头放置井号。它很好地将特定块标记为文档。但是,Python 还提供了一种使用三引号 (‘‘‘) 在注释的开头和结尾进行多行注释。这种类型的多行注释也称为文档字符串,它只能在模块、类或函数的开头使用。虽然字符串文字可以放置在代码中的其他位置,但除非在代码的开头使用,否则它们不会被视为文档字符串。让我们在接下来的示例中看看这两个多行文档实例。
清单 1-40。以 # 开头的多行文档
# This function is used in order to provide the square
# of any value which is passed in. The result will be
# passed back to the calling code.
def square_val(value):
return value * value
...
>>> print square_val(3)
9
清单 1-41。以三引号 (‘’’) 括起来的多行文档
def tip_calc(value, pct):
''' This function is used as a tip calculator based on a percentage
which is passed in as well as the value of the total amount. In
this function, the first parameter is to be the total amount of a
bill for which we will calculate the tip based upon the second
parameter as a percentage '''
return value * (pct * .01)
...
>>> print tip_calc(75,15)
11.25
好的,正如我们所见,这两种文档方法都可以用来完成文档记录或注释代码的任务。在清单 1-40 中,我们使用以 # 符号开头的多行文档来记录 square_val 函数。在清单 1-41 中,我们使用三引号方法来跨越多行文档。它们似乎都按定义工作。但是,第二个选项提供了更大的用途,因为它允许您记录特定的命名代码块,并通过调用 help(function) 函数来检索该文档。例如,如果我们想了解 square_val 代码的作用,我们需要访问代码,要么阅读多行注释,要么简单地解析代码。但是,如果我们想了解 tip_calc 函数的作用,我们可以调用 help(tip_calc) 函数,多行注释将被返回给我们。这提供了一个很好的工具,用于了解代码的作用,而无需实际访问代码本身。
清单 1-42。打印 tip_calc 函数的文档
>>> help(tip_calc)
Help on function tip_calc in module __main__:
tip_calc(value, pct)
This function is used as a tip calculator based on a percentage
which is passed in as well as the value of the total amount. In
this function, the first parameter is to be the total amount of a
bill for which we will calculate the tip based upon the second
parameter as a percentage
这些示例和简短的解释应该让您对 Python 语言提供的文档功能有很好的了解。如您所见,使用多行三引号方法非常适合记录类或函数。使用 # 符号进行注释提供了一种很好的方法来组织源代码中的注释,以及记录那些可能“不太容易”理解的代码行。
Python 帮助¶
在使用 Jython 解释器时获得帮助非常容易。交互式解释器中内置了一个出色的 help() 选项,它提供有关 Python 语言中可用的任何模块、关键字或主题的信息。通过在不传入函数名称的情况下调用 help() 函数,将调用 Python 帮助系统。在使用 help() 系统时,您可以使用交互式帮助(通过在解释器中简单地键入 help() 来调用),或者如我们之前所见,您可以通过键入 help(object) 来获取特定对象的文档字符串。
需要注意的是,在交互模式下使用帮助系统时,您的指尖有大量信息可用。如果您想亲眼看看,只需启动 Jython 交互式解释器并键入 help()。在进入交互式帮助后,您可以随时通过键入 quit 退出。为了获得模块、关键字或主题的列表,您只需键入“modules”、“keywords”或“topics”,您将获得完整的列表。您还将获得有关使用交互式帮助系统的帮助……或者也许这应该被称为 元帮助!
虽然 Jython 交互式帮助系统很棒,但您可能仍然需要进一步的帮助。有很多关于 Python 语言的书籍出版,它们一定会帮助您。确保您参考的是一本为您提供有关您正在使用的特定 Python 版本的信息的书籍,因为每个版本都包含一些差异。如本章前面所述,Jython 版本号与其 CPython 对应版本一致。因此,例如,CPython 2.5 中可用的每个功能都应该在 Jython 2.5 中可用,依此类推。
总结¶
本章涵盖了许多 Python 编程基础知识。它应该为 Python 编程的基础知识提供了基础。本章将用于在深入研究本书其余部分的语言时进行反思。
我们首先讨论了 CPython 和 Jython 之间的差异。在 JVM 上运行 Python 有很多很好的理由,包括可以使用优秀的 Java 库和部署目标。在学习了如何安装和配置 Jython 后,我们深入研究了 Python 语言。我们学习了变量的声明,并解释了该语言的动态特性。然后,我们继续介绍了语言的保留字,并讨论了开发 Python 应用程序时必须遵守的编码结构。之后,我们讨论了运算符和表达式。我们了解到表达式通常是用来计算值的代码片段。我们简要地介绍了 Python 函数,涵盖了它们的语法和用法。函数是该语言的基础部分,大多数 Python 开发人员在每个程序中都使用函数。接下来,我们简要介绍了类,即使在第 6 章中还有更多内容要学习,了解类的基础知识也很重要。我们查看了语句,并了解到它们由允许我们在应用程序中执行不同任务的指令组成。我们讨论了每个 Python 语句,并给出了示例。然后讨论了迭代结构,以便我们可以开始使用我们的语句和程序循环任务。
在语言概述之后,我们简要地介绍了使用键盘输入。这是许多程序的功能,对于构建基本程序来说很重要。然后,我们学习了一些关于文档的内容,它是任何应用程序的重要组成部分,Python 使其易于实现。我们不仅学习了如何记录代码行,还学习了如何记录整个模块、函数和类。我们简要地介绍了 Python 的 help() 系统,因为它在学习语言时可能是一个方便的功能。对于需要查找可能不太熟悉的主题的高级程序员来说,它也很有用。
在本书的其余部分,您将学习我们本章讨论的主题的更深入和更高级的用法。您还将学习可以在自己的程序中使用以使它们更强大且易于维护的概念和技术。