本文转自:http://www.ibm.com/developerworks/cn/education/java/j-jython1/index.html
关于本教程
本教程介绍哪些内容?
这个两部分的教程将介绍 Jython 脚本语言,并提供开始开发基于 Jython 的应用程序所需的足够知识。Jython 是 Python 的一种实现,已无缝集成到 Java 平台中。Python 主要在 UNIX 环境中使用,是一种强大的面向对象的脚本语言。
Jython 非常有用,因为它运行于 JVM 上,且具有成熟脚本语言所具有的高生产率。与 Python 程序不同,Jython 程序可以运行在任何支持 JVM 的环境中。现在这意味着可在大多数计算系统上使用,包括 Microsoft Windows、Mac OS、大多数 UNIX 变体(包括所有 Linux 系统)和所有的 IBM 系统。
本教程采用渐进步骤介绍 Jython。本文(即本教程的前半部分)将介绍使用 Jython 的概念和编程基础知识,包括访问选项和文件编译、语法和数据类型、程序结构、过程语句和函数。 本教程的第 2 部分将开始对采用 Jython 的面向对象编程进行概念性介绍。之后,我们将进行更具体的讨论,包括类语句、属性和方法、抽象类和运算符重载。这个高级讨论还包括调试、字符串处理、文件 I/O 和 Jython 中的 Java 支持。本教程结束时,将一步步演示如何用 Jython 构建一个可以工作的 GUI 应用程序。
在本教程的开始部分,示例代码非常简单,但在第 2 部分结束时,您将会完全掌握函数、类和程序。本教程还包括一组附录,详细介绍了 Jython 的内部工作原理。
我是否应该学习本教程?
本教程面向各个层次的软件开发人员,从偶尔的涉足者到专业人员。但它特别适合那些希望利用脚本语言所具有的高生产率优势的 Java 开发人员。那些希望轻松进入 Java 开发世界的 Visual Basic 和 C++/C# 程序员,也可以学习本教程。
总之,我们将讨论 Jython 脚本编程的以下方面:
第 1 部分
- 下载和安装
- 对 Jython 的概念性介绍
- 使用命令行与使用源文件
- 语法和数据类型
- 程序结构
- 过程语句
- 函数
第 2 部分
- 用 Jython 进行面向对象编程
- 调试
- Java 支持
- 字符串处理
- 文件 IO
- 用 Jython 构建 GUI 应用程序
要从本讨论中获益,应该至少熟悉一门过程编程语言和计算机编程的基本概念,包括命令行处理。要完全利用 Jython 的特性,还应该熟悉面向对象编程的基本概念。如果具有 Java 平台的实际知识,也是很有帮助的(尽管本教程不要求具备这些知识),因为 Jython 运行在该平台上。
注意,本教程面向 Windows 系统。所有命令示例均采用 Windows 语法。在大多数情况下,类似命令在 UNIX 系统上执行相同的功能,尽管不会演示这些命令。
工具、代码和安装要求
要学完本教程,必须在开发系统上安装 Jython 2.1 或更高版本。开发系统可以是任何 ASCII 文本编辑器(如 Windows Notepad)和命令提示符的组合。本教程包括获得并安装 Jython 的详细说明。
要使用 Jython,还必须在系统上安装 Java 运行时环境(Java Runtime Environment,JRE)。建议采用能得到的最新的 JRE(编写本文时为 1.4.2 版),但采用 Java 1.2 和更高版本都可正常工作。如果打算从浏览器使用 Jython(即作为 applet),浏览器必须可以使用 JRE 1.1。请参阅参考资料下载 Java 开发工具包 (JDK) 的最新版本。
本教程中的所有代码示例都已在 Windows 2000 的 Sun Java 1.4.1 JRE 上运行的 Jython 上进行了测试。无须在其他操作系统上更改任何类似配置,这些例子都能正常工作。
入门
安装说明
本节将逐步介绍在开发系统上下载、安装和验证 Jython 的每个步骤。
下载 Jython
可以从 Jython 主页下载 Jython 2.1。您会发现下载页面上的下载说明非常容易。
正如前面所提到的,本教程基于当前稳定的 Jython 级别,即版本 2.1。可以从 Jython 主页获得更高级的开发级别。
安装 Jython
安装 Jython 很简单:只须执行从 Jython 主页下载的类文件即可。假设已安装了 JRE 且已将类文件下载到当前目录中(下面的例子中是 C:\),下列命令将安装 Jython(注意,<java_home> 是安装 JRE 的目录):
C:\><java_home>\bin\java jython-21 |
请按照安装应用程序的提示执行。建议选择默认值,并选择 c:\Jython-2.1 作为目标目录。
验证安装
要验证是否安装了 Jython,请输入命令:
C:\>dir c:\Jython-2.1 |
命令执行后的结果应与下面的清单类似:
Volume in drive C is C_DRIVE |
测试运行
最后的步骤是确保配置了 Jython。要运行 Jython,请输入下列命令启动 Jython:
C:\>c:\jython-2.1\jython |
执行该命令后应该产生一个与下面类似的介绍:
Jython 2.1 on java1.4.1_01 (JIT: null) |
最后退出 Jython。在 Jython 提示符下,输入下列命令:
>>> import sys; sys.exit() |
或者,可以按 Ctrl+C 两次。
我们的生活更便捷
在结束“入门”一节之前,还应了解一件事:不必通过将 Jython 命令路径 (<d>:\jython-2.1
) 添加到 PATH
变量来指定该路径,现在只需在命令提示符下键入 jython 即可。
Jython 的基本概念和优点
什么是 Jython?
上文提到,Jython 是用 Java 语言编写的 Python 实现,并与 Java 平台集成在一起。Python 是一种脚本语言,经常在基于 UNIX 的系统(包括 Linux)中使用。Python 由 Guido van Rossum 发明并在 1991 年被引入到开发人员社区中。Jython 当前支持级别 2.1 的 Python 语法。
什么是脚本语言?
与 Java 编程语言不同,Jython 是一种脚本语言。脚本语言通常具有如下特点:
- 很容易学习和编码
- 意图明确且简练,但功能强大
- 具有最小的必需结构来创建一个运行的“程序”
- 支持交互式(一次一个命令)执行
- 不要求执行编译步骤
- 支持反射式程序设计
- 支持函数式程序设计
- 支持源代码(即 eval 函数)的动态执行
- 运行外部程序
一般而言,可以说脚本语言对程序员效率的贡献是建立在机器效率和性能之上的。与编程语言(如 Java 语言)相比,Jython 易于学习且编码效率很高。
Jython 还可以被描述为轻巧灵活的语言。这种语言通常被认为是能执行各种各样的任务,在解决许多不同类型的问题时很有用,易于使用且功能强大、意图明确。它们也是理想的快速原型开发语言。
Jython 的优点
与基于 C 的兄弟 Python 一样,Jython 大多数是在小场合中用来开发小型程序和脚本;它有许多特性,允许在几分钟内创建简单而实用的程序。但这并不意味着 Jython 不能用于大规模的程序设计。实际上,Jython 支持复杂的打包方案,类似于 Java 语言。依赖其面向对象的特点,Jython 具有高度的可扩展性,并为有效的软件工程提供了最新结构。
Jython 与 Java 语言相似,但不像其他一些脚本编程语言,如 Perl 和 Rexx,它从一开始就设计成一种面向对象的语言。因此,它提供易于理解的强大的面向对象编程 (OOP) 特性。
Jython 最大的优点之一是运行于任何 JVM 上,因此采用 Jython 编码的应用程序几乎可以在任何计算系统上运行。
Jython 和 Java 平台
Jython 内置在 Java 平台中。从平台的角度看,Jython 运行时仅仅是另一个 Java 类。如果您深入了解 JYTHON.BAT 文件,这一点就非常明显,该文件启动 Java 运行时,而将 Jython 解释器作为其主类(main class),如下所示:
@echo off |
一切都是解释型的
Jython 在本质上是一种解释型语言。 Jython 中没有预编译步骤(而 Java 和 C++ 中有这一步),所以每次运行 Jython 代码时,都会进行重新解释。同样,代码可以快速进行更改和测试。Jython 代码还可以交互输入(即一次一行)。此外,您可以动态构造 Jython 代码(即作为字符串)并直接执行。这样就可以灵活地进行编码,而这一点在 Java 编码中是不可能的。
Jython 解释器将 Jython 源代码转换为内部形式,以便更有效地进行处理。它在检查语法的第一次传递期间执行该项工作。一旦该传递完成,则内部化的源文件就被解释了。Jython 还在磁盘上缓存这种内部化形式。在 Java 类文件中,对于 Jython 模块 <name>.py
,缓存文件将是 <name>$py.class
。
解释执行方式也确实或多或少有些缺点。例如,使用未定义的变量不是编译器错误,因此,只有在使用变量的语句执行时才能被检测出来。虽然这一点与编译型语言相比可能是个缺点,但您可以编辑程序,然后立即执行并遇到错误(如果存在的话),这一事实会弥补这一缺点。一个简单的测试-调试步骤所花费的时间和重复进行编辑-编译步骤来删除错误所费的时间大致相同。
关于性能
由于 Jython 是解释型语言,所以它可能比编译型语言(如 Java)慢。在大多数应用程序(如脚本和 GUI)中,这一速度差别几乎注意不到。在大多数情况下,Jython 所增加的设计和编码灵活性弥补了任何小的性能损失。
由于 Jython 代码被动态转换为 Java 字节码,所以最新的对 Java 平台(如 JIT 和 Sun 的 HotSpot JVM)的功能增强也可以消除许多性能问题。
为获得额外的性能,可以采用 Java 语言实现代码部分并从 Jython 调用它们。例如,可以采用 Jython 设计程序的原型,进行测试并在有性能问题时将关键部分转换为 Java 代码。该技术是 Jython 和 Java 语言优势的组合,因为采用 Jython 进行原型化比采用 Java 语言有用得多。在本教程的第 2 部分更多地讨论 Java 语言和 Jython 的结合。
使用 Jython
将 Jython 用作命令行解释器
使用 Jython 最容易的方式之一是用作命令行解释器。在这种方式下,一次输入一行代码行,并可以立即看到结果。这是学习 Jython 并用最小开销尝试新编码技术的一种理想方式。
我们从简要介绍 Jython 交互会话开始。在 ">>>" 或 "..." 提示符后输入下列命令:
C:\>c:\jython-2.1\jython
应该接收到类似于下面的输出:
Jython 2.1 on java1.4.1_01 (JIT: null) |
通过这个例子,可以看到输入会很快得到执行。而输入包括简单表达式和更复杂的操作,如函数定义(即 fac
函数)。已定义的值和函数可以立即使用。还应注意,Jython 通过 long
类型支持非常大的整数。
注意上例中 fac
函数的缩进非常重要。在本教程的后面,您将了解有关该要求的更多信息(请参见 块)。
通过源文件使用 Jython
如果 Jython 只接受命令行输入,那它的用处就不太大;因此,它还允许接受源文件。Jython 源文件以扩展名 .py 结束。Jython 文件必须包含一系列 Jython 语句。表达式,如 1 + 2,并不是有效的语句(虽然执行,但不生成显示的输出)。
要显示表达式,必须将其放在 print
语句中。因此,上一节的序列可以编码在源文件中,如下所示:
print 1 + 2 |
上述代码产生的输出与 将 Jython 用作命令行解释器 例子中的相同。而实际上,这些语句可能已采用交互方式输入了(在 fac
函数后另加了一个空行),并产生相同的结果。
print 语句
如前一屏所示,我们使用 print
语句来输出表达式。该语句采用下列形式:
print expression {, expression}... {,} -- or -- print |
上述 print
语句还可以包含由逗号分隔的表达式的列表。表达式输出时,会自动在两个表达式之间添加一个空格。因此, print "Hello", "Goodbye"
输出 Hello Goodbye
。
如果 print
语句以逗号结束,则不输出换行。print
行本身输出一个换行。
“Hello World”示例
在 Jython 中,典型的示例程序――Hello World――是一个单行文件(名称为 hello.py),如下所示:
print "Hello World!" |
要运行该程序,应输入命令:C:\>c:\jython-2.1\jython hello.py
注意必须要有 .py 扩展名,否则将出现 "file not found" 错误。jython
命令包含几个选项。要获得更多信息,请参见 Jython 主页(在参考资料中)。
Jython 源文件是模块
Jython 源文件可以包含一系列要执行的语句。它们还可以包含函数(请参见 Jython 函数 )和类定义(本教程的第 2 部分将讨论有关类定义的更多内容)。 实际上,Jython 源文件可以是模块(稍后将在 模块和包 中介绍更多内容),而模块不能直接使用,要由其他程序导入。单个源文件可以扮演两种角色。请考虑上一屏中该文件的变体,如下所示:
def fac(x): |
同样,运行该文件会产生与以前相同的结果。但如果文件被导入到另一个只希望重用fac
函数的程序中,则 if
(请参见 if 语句)测试条件下的任何一个语句都不执行。
还要注意,每个模块都有一个名称,从命令行直接执行的名称为 "__main__
"。该特性可用于为每个模块创建测试案例。
编译 Jython
Jython 源文件可以被编译成 Java 源代码(它自动编译成字节码)以生成独立的类或 Java Archive Files (JAR) 文件。要创建直接从 Java 平台调用的 Jython 代码(比如创建 applet 或 servlet 时),必须执行该步骤。这对于提供 Jython 应用程序而不用发布 Jython 源代码也很有用。
通过使用 jythonc
命令(即假设您在 Java CLASSPATH
中有必需的 Jython JAR),Jython 可以被编译成可以直接在任何 JVM 上运行的纯 Java 类。有关使用 jythonc
的更多信息,请参见 Jython 主页(参考资料)。
编译示例
我们将 factor.py 文件(请参见 参考资料)作为独立的示例程序。要编译该程序,请使用命令:
c:\>c:\jython-2.1\jythonc factor.py |
如果没有出现错误,将创建 Java 类文件 factor.class
和 factor$_PyInner.class
。您将在 参考资料 中找到实际生成的 Java 源代码。要运行该(现在是 Java)应用程序,请使用命令:
c:\><java_home>\bin\java -cp .;c:\jython-2.1\jython.jar factor |
最终输出与下列内容类似:
factor running... |
注意,这个输出与直接使用 factor.py
程序生成的输出相同。
Jython 基本数据类型
一切都是对象
与 Java 语言不同,Jython 将所有东西,包括所有数据和代码,都视作对象。这意味着您可以使用 Jython 代码操纵这些对象,使得采用 Jython 可以很容易地进行反射式和函数式程序设计。有关更多信息,请参见 附录 G:Jython 类型汇总。
某些选择类型,如数字和字符串,更便于被视作值而非对象。Jython 也支持这一概念。
Jython 仅支持一个 null 值,具有保留名称 None
。
常见运算符
所有 Jython 数据类型都支持下列基本运算:
运算 | 测试用法 | 注释 |
x and y |
x 与 y 的布尔与 | 如果 x 为 false,则不对 y 求值 将 x 或 y 作为结果返回 |
x or y |
x 与 y 的布尔或 | 如果 x 为 true,则不对 y 求值 将 x 或 y 作为结果返回 |
not x |
x 的布尔非 | 返回 0 或 1 |
x < y |
严格的小于比较 | 返回 0 或 1 |
x > y |
严格的大于比较 | 返回 0 或 1 |
x <= y |
小于或等于比较 | 返回 0 或 1 |
x >= y |
大于或等于比较 | 返回 0 或 1 |
x == y |
等于比较 | 返回 0 或 1 |
x != y x <> y
|
不等于比较 | 返回 0 或 1 |
x is y |
同一性 | 如果 x 与 y 是同一个对象,则返回 1;否则返回 0 |
x is not y |
差异性 | 如果 x 与 y 不是同一个对象,则返回 1,否则返回 0 |
注意与 Java 语言不同,所有类型都是可比较的。一般来说,如果操作数的类型不匹配,则结果不相等。复杂类型的小于或大于关系是一致而随意的。
布尔类型
Jython 没有单独的布尔类型。下列各节描述的所有其他类型都可用作布尔类型。对于数值类型,0 被认为是 false,而所有其他值都认为是 true。对于结构类型(即序列和映射),空结构被认为是 false,而其他结构被认为是 true。None
值始终为 false。
数值类型
数字是不变的(即在创建后一直保持不变)。Jython 支持三种数值类型,如下所示:
-
整数没有小数部分。整数有两种衍生形式:
-
普通:范围为 -2**31 到 2**31 - 1 之间的小值(类似于 Java
int
)。
例如:-1, 0, 1, 10000 -
长整数:只受 JVM 的可用内存限制的大值(类似于 Java 的
BigInteger
)。
例如:-1L, 0L, 1L, 10000000000000000000000000000000L
-
普通:范围为 -2**31 到 2**31 - 1 之间的小值(类似于 Java
-
浮点值可以有小数部分。浮点数支持与 Java
double
类型相同的值。
例如: 0.0, -1.01, 2.5004E-100, -35e100 -
复数值是一对浮点值,称为实部和虚部。如果 x 是复数值,则
x.real
是实部,而x.imag
是虚部。任一部分都可以是 0.0。方法x.conjugate
生成一个新复数,该值有+x.real
和-x.imag
。
例如: 1J, -1j, 1+2j, -3.7+2e5j
其他数值类型运算和函数
数值类型还支持下列运算和函数:
运算/函数 | 用法 |
-x |
负 x(即 0 - x) |
+x |
正 ―― 没有改变(即 0 + x) |
x + y |
将 y 添加到 x |
x - y |
从 x 中减去 y |
x * y |
x 乘以 y |
x / y |
x 除以 y |
x % y divmod(x, y)
|
取 x 除以 y 所得的模数 Return (x / y, x % y) |
x ** y pow(x, y)
|
将 y 作为 x 的幂 将 y 作为 x 的幂 |
abs(x) |
If x < 0, then -x; else x |
int(x) |
将 x 转换为整数 |
long(x) |
将 x 转换为长整数 |
float(x) |
将 x 转换为浮点数 |
complex(r, i) complex(x)
|
将 r 和 i 转换为复数 将 x 转换为复数 |
注意:对于数值类型,操作数被提升到下个较高的类型。对于整数操作数, /、% 和 ** 都产生整数结果。对于 int
、long
、float
和complex
转换函数,x 可以是字符串,也可以是任何数字。
其他整型运算
整型还支持下列运算:
运算 | 用法 | 注释 |
x << y |
将 x 左移 y 位 | 类似于 x * pow(2, y) |
x >> y |
将 x 右移 y 位 | 类似于 x / pow(2, y) |
x & y |
x 和 y 按位与 | 对 x 中与 y 中的 0 位对应的位清零。 |
x | y |
x 和 y 按位或 | 将 x 中与 y 中的 1 位对应的位置 1。 |
x ^ y |
x 和 y 按位异或 | 将 x 中与 y 中的 1 位对应的位取反 |
~x |
将 x 位取反 | 将所有位都取反 |
其他浮点类型函数
浮点类型另外支持下列函数(在 math
模块中):
函数 | 注释 |
ceil(v) floor(v)
|
计算 v 的最大值和最小值。 |
sin(v) cos(v) tan(v)
|
计算 v 的正弦、余弦和正切。 |
acos(v) asin(v) atan(v) atan2(v, w)
|
计算 v(或 v / w)的反正弦、反余弦和反正切。 |
sinh(v) cosh(v) tanh(v)
|
计算 v 的双曲正弦、双曲余弦和双曲正切。 |
exp(v) pow(v, w) sqrt(v) log(v) log10(v)
|
计算 v 的幂和对数。 |
fabs(v) |
计算 v 的绝对值。 |
fmod(v, w) |
计算 v 和 w 的模。可能与 v % w 不同。 |
modf(v) |
返回(作为 tuple (i, f))v 的整数部分和小数部分(两者都为浮点数)。 |
frexp(v) |
返回(作为 tuple (m, e))v 的浮点尾数和整型指数。结果类 似于 v == m * 2 ** e 。 |
ldexp(v, w) |
计算 v * 2 ** w (w 必须为整数)。 |
hypot(v, w) |
计算 v 和 w 斜边(即sqrt(v * v + w * w) )。 |
Math 模块示例
我们运行一个例子来演示上一屏中的 math
模块中的函数。有关更多信息,请参见 import 语句 和 格式化字符串和值。
from math import * print "PI = %f, e = %f" % (pi, e) print "Sine of %f = %f" % (0.5, sin(0.5)) |
示例代码产生下列输出:
PI = 3.141593, e = 2.718282 |
Jython 集合
集合类型
您经常需要创建其他数据项的集合。Jython 支持两种主要的集合类型。最基本的 是序列类型,它是项的有序集合。序列支持几种子类型,如字符串、列表和元组(tuple)。其他集合是映射类型。映射支持通过键值进行联合查找。您将在本节了解这两种类型。
序列类型
序列是项的有序集合。所有序列都是从零开始索引的,这意味着第一个元素是元素零 (0)。索引是连续的(即 0, 1, 2, 3, ...),一直到该序列的长度(小于 1)。因此,序列类似于 C 和 Java 中的数组。
所有序列都支持用索引(或下标)来选择子元素。如果 x 是一个序列,则表达式 x[n]
选择该序列的第 n 个值。可变的序列(如列表)支持索引赋值,这种操作会替换元素。对于这些序列,表达式 x[n] = y
用 y 取代了 x 的第 n 个元素。
序列支持对索引的扩展,称为切片(slicing),切片会选择元素的范围。例如,x[1:3]
选择 x 的第二个到第三个元素(最后的索引是传递所选值的索引)。与索引一样,赋值时可以使用切片来取代多个元素。
在 Jython 中,序列是一个抽象的概念,因为您不能直接创建序列,只能从序列派生出子类型。任何序列子类型都具有序列的所有函数。
切片的形式
下面总结一些有效的切片形式。假定 x 是一个包含 10 个元素(索引从 0 到 9)的序列。
表达式示例 | 产生的操作 | 注释 |
x[1] |
选择索引 1 | 与求索引相同 |
x[1:2] |
选择索引 1 | 最后的值是传递所选值的索引 |
x[1:] |
选择索引 1 到 9 | 缺少的值隐含为序列的长度 |
x[:7] |
选择索引 0 到 6 | 缺少的值隐含为零 |
x[:-1] |
选择索引 0 到 8 | 负索引通过序列长度进行调整 |
x[-6:-3] |
选择索引 3 到 6 | 支持相反的范围 |
x[:] |
选择索引 0 到 9 | 整个序列;这种方式创建序列的一个副本 |
x[:1000] |
选择索引 0 到 9 | 对超过序列结束索引的引用就是这个结束索引 |
x[-100:] |
选择索引 0 到 9 | 小于序列开始索引的引用是开始索引 |
x[::2] |
选择索引 0, 2, 4, 6, 8 | 第三个值忽略,不作选择 |
序列运算符
Jython 支持在序列(x 和 y)之间进行几种运算,总结如下:
运算符 | 用法 | 例子 |
x + y |
联结(或连接)序列 |
[1,2,3] + [4,5,6] --> [1,2,3,4,5,6] |
i * x x * i
|
重复序列 |
[1,2,3] * 3 --> [1,2,3,1,2,3,1,2,3] |
o in x o not in x
|
包含测试 |
2 in (1,2,3) --> 1 (true) 7 not in (1,2,3) --> 1 (true) |
序列函数
另外,任何序列 (x) 都可以采用下列几个函数,总结如下:
函数 | 用法 | 例子 |
len(x) |
序列的长度(元素个数) | len(1,2,3) --> 3 |
min(x) |
序列中的最小值 | min(1,2,3) --> 1 |
max(x) |
序列中的最大值 | max(1,2,3) --> 3 |
有关序列的最后说明
如上所述,序列在 Jython 中是一种抽象概念,因为您不能直接创建序列,只创建从序列派生而来的子类型。任何序列子类型都具有序列的全部函数。序列子类型有几个,如下所示:
字符串
A 字符串是字符的不变序列,可以被视为一个值。同样,字符串支持产生新字符串的所有不变序列的函数和运算符。例如,"abcdef"[1:4]
的值是新字符串 "bcd"
。有关字符串函数的更多信息,请参见 附录 B:字符串方法。
Jython 没有字符类型。字符是由长度为 1(即一个字符)的字符串表示的。
可以通过使用单个或三个引号来定义字符串常量。使用单引号定义的字符串不能跨行,而使用三个引号定义的字符串可以跨行。字符串可以由双引号 (") 和单引号 (') 括起来。引用字符可以包含其他未转义的引用字符或转义(前面放反斜杠 (\))的引用字符。有关信息,请参见 附录 A:转义字符。
字符串例子
下面是一些字符串例子:
- "This is a string"
- 'This is also a string'
- "This is Barry's string"
- 'Barry wrote "Introduction to Jython"!'
- "This is an escaped quote (\") in a quoted string"
- r"\s*xyx\s*" - equivalent to"\\s*xyx\\s"
- u"the number one is \u0031" (vs. "the number one is \x31")
注意,倒数第二个例子展示了原始字符串(raw string)。在原始字符串中,采用了反斜杠字符串的字面值(即不需要加两个反斜杠来获得反斜杠字符)。这种原始形式对大量采用转义字符的字符串特别有用,如正则表达式。本教程的第 2 部分将详细讨论正则表达式。
最后一个例子展示了一个 Unicode 字符串和如何创建转义的 Unicode 值。注意,所有字符串都使用 Unicode 字符值进行存储(JVM 提供该功能);这种格式将允许您输入 Unicode 字符值。
混合字符串和长字符串
为方便起见,Jython 解析器自动连接只由空格分隔的多个字符串(就像使用了 +
运算符)。这就很容易输入长字符串并在单个字符串中混合引用类型。例如,下面的序列常量:
"This string uses ' and " 'that string uses ".'
变为下面的字符串:
This string uses ' and that string uses ".
三重引用用于输入包含换行的长字符串。使用单引号定义的字符串不能跨行,而使用三个引号的字符串可以跨行。三重引用还可用于输入混合引号类型的短(单行)字符串。例如,下面是一个长的多行字符串:
r"""Strings literals are defined by the use |
而下面是一个短的混合引号字符串:'''This string uses ' and that string uses ".'''
格式化字符串和值
Jython 字符串支持类似于 C 的 printf
的特殊格式的运算,但使用模 (%) 运算符。在字符串中匹配 %x
的位置,右侧的项集合被替换成左侧的字符串。集合值通常是单值、值的元组和值字典。
格式规范的一般格式为:
%{(key)}{width}{.precision}x |
下面是对项进行格式化的指南:
- key:在提供目录中进行查找的可选关键字。
- width:字段的最小宽度(对于大型值,该字段将会更长)。
- precision:任何小数点后的数字个数。
- x :在 附录 H:格式代码 中描述的格式代码。
例如
print "%s is %i %s %s than %s!" % ("John", 5, "years", "older", "Mark") print "Name: %(last)s, %(first)s" % {'first':"Barry", 'last':"Feigenbaum", 'age':18} |
输出结果
John is 5 years older than Mark! |
元组
元组是任何类型的不变列表。一旦创建就不能更改。元组可以具有任何长度且可以包含任何类型的对象。下面展示了一些例子:
例子 | 注释 |
() |
空元组 |
(1,) |
有一个整数元素的元组;需要用逗号将元组与表达式如 (1) 区分开(1) |
(1, 'abc', 2, "def") |
有四个元素的元组,两个整数,两个字符串 |
((), (1,), (1,2), (1,2,3)) |
有多个元组的元组;每个子列表都包含整数 |
(1, "hello", ['a','b','c'], "goodbye") |
整数、字符串和字符串子列表的混合元组 |
v1 = 1; v2 = 10 (1, v1, v2, v1 + v2)
|
整数元组;支持变量引用和表达式 |
注意,尽管元组是不可变的,但元组中的元素可能会改变。具体来说是,嵌套列表(请参见 列表 )和映射(请参见 映射和字典)都可以被改变。
范围
要实现迭代(请参见 for 语句),Jython 使用整数递增的不可变序列。这些序列称为范围。采用两个内置函数很容易创建范围:
- range({start,} end {,inc}) 创建一个小范围。 该范围的所有元素都存在。
- xrange({start,} end {,inc}) 创建一个大范围。 仅在需要时创建元素。
范围从 start
(默认为 0)向上增加,但不包括 end
,步进的值为 inc
(默认为 1)。例如:
print range(10) # prints [0,1,2,3,4,5,6,7,8,9] |
列表
列表是任意类型的可变序列。列表的长度可以增加,也可以缩小,而列表中的元素可以替换,也可以删除。列表可以是任何长度,也可以包含任何类型的对象。有关列表函数的更多信息,请参见 附录 C:列表方法。下面展示了一些例子。
例子 | 注释 |
[] |
空列表 |
[1] |
有一个整数元素的列表 |
[1, 'abc', 2, "def"] |
有四个元素的列表,两个整数和两个字符串 |
[[],[1],[1,2],[1,2,3]] |
列表的列表;每个子列表都包含整数 |
[1, "hello", ['a','b','c'], "goodbye"] |
整数、字符串和字符串子列表的混合列表 |
v1 = 1; v2 = 10 [1, v1, v2, v1 + v2]
|
整数列表;支持变量引用和表达式 |
堆栈和队列
列表支持后进先出 (Last-In/First-Out,LIFO) 堆栈和先进先出 (First-in/First-out,FIFO) 队列概念。 使用列表 x 创建堆栈时,用x.pop()
(和等同的 x.pop(-1)
)删除项。使用列表 x 创建队列时,用 x.pop(0)
删除项。要向列表中添加元素,请使用x.append(item)
。 例如:
l = [1,2,3,4,5] # define a list l.append(6) # l is [1,2,3,4,5,6] w = l.pop() # w is 6, l is [1,2,3,4,5] |
列表内涵
列表也可以通过称为列表内涵(list comprehensions)的高级表示法进行创建。列表内涵 是结合了 for
和 if
语句来创建列表元素的列表。有关更多信息,请参见 for 语句 和 if 语句。下面是一些列表内涵的例子:
例子 | 产生的列表 |
[x for x in range(10)] |
[0,1,2,3,4,5,6,7,8,9] 与 range(10) 相同 |
[x for x in xrange(1000)] |
[0,1,2,..., 997, 998, 999] 与range(1000) 相同 |
[(x < y) for x in range(3) for y in range(3)] |
[0,1,1,0,0,1,0,0,0] |
[x for x in range(10) if x > 5] |
[6,7,8,9] |
[x ** 2 + 1 for x in range(5)] |
[1,2,5,10,17] |
[x for x in range(10) if x % 2 == 0] |
[0,2,4,6,8] |
映射和字典
映射类型支持可变的键-值对(称为项)的集合。尽管映射和序列都支持许多相似的运算,但映射和序列是截然不同的。两者的相似之处是它们都是一种抽象的概念;您只能使用映射子类型,而最常见的映射子类型是字典 。有关映射函数的更多信息,请参见 附录 D:映射方法。
映射支持通过键值进行联合查找。键可以是任何不变类型。键在进行散列处理时必须是不变的(请参见 附录 E:内置函数),而且散列值必须保持稳定。常见的键类型有数字、字符串和具有不变元素的元组。值可以是任何类型(包括 None
)。如果 m 是一个映射,则函数 len(m)
返回映射中项的数量。
映射与序列一样,都支持下标,但是通过键而非索引来支持的。例如,如果 m 是一个映射,而 x = m["x"]
从该映射中获得一个值,且 m["x"] = x
将一个新值添加到该映射中并取代该映射中的值。
字典示例
下面是一些字典常量的例子:
例子 | 注释 |
{} |
空字典 |
{1:"one", 2:"two", 3:"three"} |
有三个将整数映射到名称的元素的字典 |
{"one":1, "two":2, "three":3} |
有三个将名称映射到整数的元素的字典 |
{"first':'Barry", "mi":"A", "last":"Feigenbaum"} |
映射名称的字典 |
{"init":(1,2,3), "term":['x','y','z'], "data":{1:10,2:100.5}} |
包含元组、列表和另一个字典的字典 |
t = (1,2,3); l = ['x','y','z']; d = {1:10,2:100.5} {"init":t, "term":l, "data":d}
|
包含元组、列表和另一个字典的字典; 支持变量引用和表达式 |
如 格式化字符串和值 中所示,使用字典便于进行格式映射。
Jython 程序结构
文件结构
正如已经介绍的那样,Jython 程序是简单的文本文件。这些文件包含在输入时进行解释的语句(在快速分析语法错误后)。通过使用import
(请参见 模块和包) 和 exec
语句(请参见 动态代码求值),其他文件可以被有效包括进 Jython 程序中。
注释
Jython 包含两种形式的注释:
- 备注(remarks) 是用 sharp (#) 字符引入的注释。# 之后的同一行所有文本都被忽略。备注可以从任何列开始。
-
文档注释(documentation comments)是紧接在外部块(如模块、类和函数)之后的字符串常量。字符串不改变外部块的行为,而注释可以通过特殊属性
__doc__
访问以创建块的描述。
注释例子
下例展示了一个函数(fac
),它有一个文档注释和两个备注。该例还演示了如何通过编程方式访问文档注释。
代码序列
def fac(x): |
产生的输出
The fac function computes the value x! (x factorial) |
语句语法
从以上各节可以知道,Jython 的语法很简单。它与英语非常类似,而不像 C 和 Java 语言。具体来说,每个源代码行(通常)是单个语句。除了 expression
和 assignment
语句外,每个语句都由关键字名称(如 if
或 for
)引入。在任意两个语句之间都可以加空行或备注。
不需要在每行的结尾加分号,但如果愿意,也可以加。如果希望每行包含多条语句,则需要用分号来分隔语句。
如有必要,语句可以延续到超过一行。将一个反斜杠字符放在一行的末尾可以延续到任意行,如下所示:
x = "A looooooooooooooooooooooooooooooooong string " + \ |
如果是在用圆括号(())、方括号 ([]) 或花括号 ({}) 括住的结构中间,则可以在该结构的任何逗号后继续该行,而无须使用反斜杠。下面是一个例子:
x = (1, 2, 3, "hello", |
标识符和保留字
Jython 支持与 C++ 和 Java 名称相似的标识符。标识符用于给变量、函数和类命名,还可以用作关键字。标识符可以是任何长度,必须以字母(大写或小写)或下划线字符开头,可以是字母、十进制数字和下划线的任意组合。如 abc、abc123、_x、x_、myName和 ONE是一些有效的标识符,123abc、$xyz 和 abc pqr是一些无效的标识符。
注意,以下划线开头的名称通常保留用作内部名称或专有名称。
Jython 还有几个保留字(或关键字),它们不能用作变量、函数或类的名称。这些关键字分为下列几类:
- 引入语句的关键字:assert、break、class、continue、def、del、elif、else、except、exec、finally、for、from、global、if、import、pass、print、raise、return、try和 while。
- 引入参数的关键关键字:as、import 和 in。
- 运算符:and、in、is、lambda、not 和 or。
注意,关键字可以用于特殊环境中,如方法的名称。例如,您可以使用关键字调用与 Jython 关键字具有相同名称的 Java 方法。不正确的关键字通常会导致 SyntaxError
。
块
块(或套件)是语句组,用在希望使用单个语句的地方。所有可以将语句块作为目标的语句都通过冒号字符引入块。下列语句(或语句子句)将块作为目标:if、elif、else、for、while、try、except、def 和 class。不管是由逗号分隔的单条语句,还是小语句组,都可以跟在同一行冒号的后面,块可以跟在后续行缩进的语句后。
我强烈建议使用空格进行缩进。在具有不同制表符停止位(tab stop)的系统(或编辑器)之间移动时,使用制表符可能出现问题。请不要在同一源文件中混用制表符和空格。按照约定,每一层使用四个空格。
注意: 模块最外面的块中的所有行都必须从第一列开始,否则会产生 SyntaxError
。
示例块
与 C 和 Java 语言不同,在 Jython 中,不是使用花括号,而是使用缩进来划分块。例如:
# the following prints 0 through 10 on one line |
输出为:0 1 2 3 4 5 6 7 8 9.
作为 for 循环主体的块由缩进代码指出。主体中的所有行(除注释外)都必须缩进到相同的位置。同一个循环可以编写为:
# the following prints 0 through 10 on one line |
可见性和作用域
Jython 支持下列作用域:
- 内置 符号,由 Jython 运行时定义,它总是可用的,除非在另一个作用域中重新进行了定义。
- 全局 变量对整个模块都可见,包括在该模块中声明的函数和类。当前全局作用域中的变量的字典可以通过 globals 函数访问。
- 局部函数参数和变量,它在函数体中声明,对该块可用。当前局部作用域中的变量名的字典可以通过 locals 函数访问。在模块中和任何函数之外,局部作用域和全局作用域都是相同的。
一般而言,变量在声明它们的块的作用域中和在该作用域中定义的任何函数中都是可见的(请参见 Jython 函数 )。变量在每个作用域中只能声明一次;后续使用会重新绑定该变量。与在 C++ 和 Java 语言中不同,函数中的嵌套块不会开始一个新作用域。
动态代码求值
Jython 与一般的语言不同,它有能力动态创建代码,然后执行。例如,在计算器应用程序中,用户可以用文本形式输入表达式,Jython 可以直接执行该表达式(假设它符合 Jython 源代码规则)。
要较好地了解 Jython 如何对动态代码解释/求值,请考虑下列代码:
v1 = 100; v2 = 200 |
下面是使用上述代码进行求值的示例表达式和求值的结果:
输入表达式(作为字符串输入) | 结果 |
'1234.56' |
1234.56 |
'v1+v2' |
300 |
'd1["simple"]' |
123 |
'v1**2 + len(l1)' |
10004 |
Eval、exec 和 execfile
eval
函数用于执行返回值的表达式。exec
语句用于对不返回值的代码块(一条或多条语句)进行求值,它将文件、字符串(常从文件中读取)或函数作为自己的源操作数。execfile
函数执行来自文件的代码块,它实际上是运行一个子程序。
exec
语句采用下列形式:
exec source {in globals {, locals}} |
execfile
和 eval
函数采用下列形式:
execfile(filename, {globals {, locals}}) eval(expression, {globals {, locals}}) |
所有三种形式都有选择地采用定义全局名称空间和局部名称空间的两个字典。有关名称空间的详细信息,请参见 可见性和作用域。如果省略了这些字典,则使用当前的局部名称空间(由 locals
函数提供)和当前的全局名称空间(由 globals
函数提供)。
例如,如果字典 gd = {"one":1, "two":2}
和 ld = {"x":100, "y":-1}
用作名称空间,则: print eval("one + two * 2 + x + y", gd, ld)
输入结果为:104
。
有关使用 eval
函数和 exec
语句的更详细的信息,可以在 Python Library Reference(请参见 参考资料)中获得。
模块和导入
关于模块和导入
Jython 将程序分成不同的文件,称为模块。通过将模块导入代码中,模块就能被重用。Jython 提供了许多可以重用的模块(请参见附录 F:Jython 库汇总)。Jython 还允许重用任何 Java 类和 API。
模块和包
模块是可执行的 Jython 文件,其中包含变量、函数和类等的定义。模块被导入(执行和绑定)到其他程序/脚本或模块中。当导入程序或模块需要使用导入模块中的一些或所有定义时,就有必要导入模块。
Jython 包是概念上有层次结构的模块的集合。它们以目录的方式实现的,这些目录包含一个或多个模块和特殊文件 __init__.py
,该文件在包中第一个模块执行之前执行。
模块和包允许重用扩展标准 Jython 和 Java 库。您还可以创建在自己的 Jython 应用程序中重用的模块和包。有关可用的 Jython 模块的更多信息,请参见 附录 F:Jython 库汇总 。有关可用的 Java 库的更多信息,请访问 Sun Microsystems 的 Java 技术主页(在 参考资料 中)。
import 语句
import
语句执行另一个文件,并将绑定在它中的某些或所有名称都添加到当前名称空间中(请参见 可见性和作用域)。在导入文件中,当前名称空间一般是全局名称空间。该模块中的所有语句(包括赋值语句)都被执行。import
语句有几种形式:
import module {as alias} -- or -- from module import name {as alias} -- or -- from module import * |
module
值将 Jython (.py) 文件或加点的路径命名为 Jython 包。name
值从模块中选择特定的名称。模块名称是区分大小写的。这些参数可以重复。可选择的 alias
值允许对导入的对象重新命名。
导入的例子
下面是一些 import
语句的例子:
例子 | 注释 |
import sys |
导入 sys 模块。sys 中的所有名称都可以通过前缀 sys 来引用。 |
from sys import exc_info |
从 sys 模块导入 exc_info 函数。不需要前缀。 |
from sys import * |
导入 sys 模块中的所有名称和函数。不需要前缀。 |
from sys import exc_info as einfo |
从 sys 模块中导入 exc_info 函数并将其命名为 einfo 。不需要前缀。 |
from string import uppercase as uc, lowercase as lc |
从模块 string 中导入 uppercase 和 lowercase 函数。不需要前缀。 |
import sys, string |
导入模块 sys and string
|
import com.ibm.tools.compiler as compiler |
从 com.ibm.tools 包中导入 compiler ,并取一个短名称 compiler 。 |
导入模块和包
要导入模块或包,Jython 必须能找到相关的源文件 (.py)。Jython 使用 Jython 注册表中的 python.path
(与 Java 语言的 CLASSPATH
非常类似)和 python.prepath
变量来搜索这些文件。您可以使用任何文本编辑器来添加或更新 Jython 主目录(通常为 c:\jython-2.1
)中的 registry
文件。有关更多信息,请参见 Jython 注册表(在 参考资料 中)或 registry
文件本身。
默认情况下,Jython 将搜索包含执行源文件的目录;因此,可以找到与正在导入的 Jython 程序位于同一个目录中的模块。当前目录通常也在该路径中。只要输入下例命令就可查出当前搜索路径:
import sys |
在我的机器上,当在 C:\Articles
目录中运行时,上述命令生成下列输出:
['', 'C:\\Articles\\.', 'C:\\jython-2.1\\Lib', 'C:\\jython-2.1'] |
要找到 Java 类文件,Jython 既搜索 Java CLASSPATH
,也搜索 sys.path
值。
import 是可执行的
与 Java 语言不同,import
语句在 Jython 中是可执行的,但它不是编译器指令。因此,不需要在模块开始就执行导入;而仅在使用已导入符号(imported symbols)之前执行。实际上,导入可以有条件地完成,如下例所示:
: |
导入也可以被撤销,如下所示:
import sys |
子集导入
当导入模块时,已赋值的所有值或在模块中创建的函数通常都可以由模块导入程序(importer)引用。您可以通过改变模块中的代码来防止出现此类情况。以下划线 (_) 作为名称的开头或在模块的开始定义一个特殊的变量 __all__
,这样可以只列出要导入的变量或函数的名称。例如,下列 __all__
定义:
__all__ = ["getline","clearcache","checkcache"] |
只导入名称 getline
、clearcache
和 checkcache
。
在模块目录级别可以采用类似的策略。在名为 __init__.py
的文件中定义变量 __all__
,指示解释器要从模块中导入哪些模块(如果在导入语句中使用了通配符 (*))。例如,如果 __all__ = ['mod1', 'mod3', 'globals']
行位于名为 modules 目录下叫做__init__.py
的文件中,它将导致语句 from modules import *
从 modules 目录导入模块 mod1
、mod3
和 globals
。
运行本机应用程序
通过 os.system
函数,Jython 还可以运行任何在当前主机 PATH
中找到的外部程序,如主机操作系统应用程序。例如,要编译 Java 程序,可以使用
import os |
Jython 异常
关于异常
不论程序员是如何仔细设计和测试其代码,都可能发生意外错误,即异常。Jython 为恢复这些错误提供了优异的支持。
异常通常是 Jython 类型 exceptions.Exception
或 Java 类 java.lang.Exception
的子类。大多数 Jython 异常名称都以 "Error"(例如IOError
或 IndexError
)或 "Warning"结尾。而 Java 异常以 "Error"(适用于关键异常)或 "Exception"(适用于一般可恢复异常)结尾。有关更多信息,请参见 Jython 异常层次结构 或 Python Library Reference(请参见 参考资料 获得一个链接)。
Jython 异常层次结构
下面是 Jython 的主要异常层次结构的子集。
- 1 Exception
- 1.1 SystemExit
- 1.2 StopIteration
- 1.3 StandardError
- 1.3.1 KeyboardInterrupt
- 1.3.2 ImportError
- 1.3.3 EnvironmentError
- 1.3.3.1 IOError
- 1.3.3.2 OSError
- 1.3.4 EOFError
- 1.3.5 RuntimeError
- 1.3.5.1 NotImplementedError
- 1.3.6 NameError
- 1.3.6.1 UnboundLocalError
- 1.3.7 AttributeError
- 1.3.8 SyntaxError
- 1.3.8.1 IndentationError
- 1.3.8.2 TabError
- 1.3.9 TypeError
- 1.3.10 AssertionError
- 1.3.11 LookupError
- 1.3.11.1 IndexError
- 1.3.11.2 KeyError
- 1.3.12 ArithmeticError
- 1.3.12.1 OverflowError
- 1.3.12.2 ZeroDivisionError
- 1.3.12.3 FloatingPointError
- 1.3.13 ValueError
- 1.3.14 ReferenceError
- 1.3.15 SystemError
- 1.3.16 MemoryError
- 2 Warning
- 2.1 UserWarning
- 2.2 DeprecationWarning
- 2.3 PendingDeprecationWarning
- 2.4 SyntaxWarning
- 2.5 OverflowWarning
- 2.6 RuntimeWarning
- 2.7 FutureWarning
该层次结构是 Python Library Reference(请参见 参考资料)的子集。这些异常可以被进一步分类。
try-except-else 语句
与 C++ 和 Java 语言类似,Jython 支持异常处理程序。这些处理程序由 try-except-else
语句定义,该语句具有如下所示的形式:
try: statement |
可以用不同的 type
值重复 except
子句。如果这样,异常就不能有重叠的层次结构(即成为“兄弟”),或者必须按子异常到根异常的顺序进行排序。可选的 type
值是一个异常类型(或者是 exceptions.Exception
的子类,或者是 java.lang.Throwable
的子类)。如果缺少 type
,则 except
子句捕获所有 Jython 和 Java 异常。可选的 var
值接收实际的异常对象。如果缺少 var
,则异常对象是不能直接访问的。else
子句是可选的。只有在没有发生异常时才执行该语句。
如果在 try
子句中发生了异常,则该子句退出,进入第一个匹配的 except
子句(如果有)。如果匹配不到异常,则包含 try-except-else
的块退出且重新引发异常。
如果异常在 except
或 else
子句中引发,则该子句将退出,而新异常将在包含块中得到处理。
访问异常信息
要访问有关异常的信息,可以使用上面描述的 except
子句中的值或 sys.exc_info
函数。例如,您可以使用下列函数,其中,type
是异常的类,value
是异常对象(使用 str(value)
来获得该消息),traceback
是执行跟踪,它是执行跟踪框架的链接表。
import sys |
有关异常和跟踪的更详细信息可以在 Python Reference Manual (请参见 参考资料)中获得。
try-finally 语句
与 C++ 和 Java 语言一样,Jython 还支持结构 try-finally
,采用该结构可以轻松地执行必需的清除活动,如关闭打开的文件、释放资源等。一旦进入 try
子句,finally
子句中的任何代码都要保证执行一次,即使通过返回语句(请参见 return 语句)或异常退出也是如此。try-finally
语句具有下列形式:
try: statement |
注意,try-except-else
语句可以嵌套在 try-finally
语句中,反之亦然。
try 语句的例子
下面是一起使用 try-except
和 try-finally
语句的例子。本教程的第 2 部分将详细讨论 Jython 的文件 I/O。
def readfile (name): |
raise 语句
异常由被调用函数或内置服务生成。还可以使用 raise
语句生成异常。raise
语句具有下列形式:
raise exception -- or -- raise exception_class {, message} -- or -- raise |
下面是 raise
语句的一些例子。
例子 | 注释 |
raise |
重新引发当前的异常;在异常块中用于重新生成异常 |
raise IOError |
创建和引发 IOError ,没有消息 |
raise anIOError |
重新引发现有的 IOError 对象 |
raise IOError, "End of File" |
创建和引发 IOError ,有解释性消息 |
from java import io raise io.IOException, "End of File"
|
创建和引发 Java 异常,有解释性消息 |
Jython 过程语句
每个过程的语句
Jython 有一些执行计算或控制程序流的语句,包括 expression
、assignment
、pass
、if
、while
、for
、break
、continues
和 del
语句。您将在下一屏中了解这些过程语句。
pass 语句
pass
语句在下列情形下使用:在语法上要求必须有一个 Jython 语句,但此时程序没有要求执行任何操作。pass
在创建空循环语句或提供块的临时实现时很有用。该语句具有下列形式:
pass |
表达式语句
在 Jython 中,任何表达式都可以充当语句;而最终的值被简单地丢弃即可。任何此类 expression
语句都常常调用函数或方法(在第 2 部分进一步讨论)。例如,下列代码依次调用三个函数:
performAction(1) |
运算符和优先级
Jython 表达式由 运算符优先级总结 中描述的运算符的任何有效组合组成。它们与大多数语言的表达式类似,特别类似于 C/C++ 和 Java 语言。
1 + 1 # add 1 and 1 yielding 2 (1 + 2) ** 3 # add 1 and 2 and raise the result by 3 yielding 27 1 + 2 ** 3 # raise 2 by 3 and add 1 yielding 9 x % y == 0 # tests to see if x is divisible by y x & 1 # extracts the low-order bit of x # below is the same as: "(0 <= x) and (x < 100)" but is more concise |
运算符优先级总结
下表概括了 Jython 运算符的优先级。使用圆括号可以改变运算符的顺序,也可以提高可读性。除非另行说明,否则同一优先级运算是从左到右进行求值的。较高优先级的运算位于列表的顶部。
运算 | 注释 |
( expression ) ( expr1, ..., exprN ) [ expr1, ...,exprN ] { key1:value1, ..., keyN:valueN } `expression`
|
嵌套表达式或分组 元组构造函数 列表构造函数 字典构造函数 repr (表示) 表达式 |
x.name x[i], x[i:j], x[i:j:k] x(...)
|
成员(属性或方法)选择 下标或切片 函数调用 |
** |
作为幂(右结合) |
+ - ~
|
正 负 按位取反 |
* / %
|
乘 除 取模 |
+ -
|
加 减 |
<<, >> |
按位移动 |
& |
按位与 |
^ |
按位异或 |
| |
按位或 |
is , is not in , not in < , <= , > , >= , == , != , <>
|
同一性测试 包含测试 关系测试 |
not |
逻辑非 |
and |
逻辑与 |
or |
逻辑或 |
lambda |
声明一个 lambda 函数 |
赋值语句
assignment
语句用于将值绑定(或重新绑定)到变量。如果没有定义变量,则绑定创建变量并对其赋值。在 Jython 中,所有数据都是对象,变量实际上存储的是对象的引用而非值。变量是没有类型的,因此赋值可以更改变量引用的值的类型。
多个变量可以具有对同一个对象的引用;这种情况就称为取别名。为此,Jython 支持 is
和 is not
运算符,用于测试两个变量是否引用同一个对象。
变量只能在块中声明一次。这意味着,即使块中的流不执行创建变量的assignment
语句,也会由解析器声明变量。直到实际执行第一个赋值操作之前,变量都具有未定义的值。
注意,与assignment
语句类似,其他语句也可以绑定变量。class
、def
、for
和 except
语句是一些例子。
并行赋值
assignment
语句支持序列解开(unpacking)。这种功能支持并行赋值。例如,下列语句将 a 设置为 1,将 b 设置为 2 ,并将 c 设置为 3:
(a, b, c) = (1, 2, 3) -- or -- x = (1, 2, 3) |
左侧和右侧必须有相同的变量数。如果提供了一个序列变量(称为函数的参数),而且要访问其中的值,则这种解开方法会很有用。为方便起见,结束圆括号不是必需的,因此上述赋值还可以写成:a, b, c = 1, 2, 3
。
多重赋值
Jython 支持多重赋值。例如,下列语句将 c 设置为 1,将 b 设置为 c(或 1),并将 a 设置为 b(或 1)。
a = b = c = 1 |
因此,assignment
的不平常之处就在于它是右结合的。
增量赋值
Jython 支持增量赋值,它将运算符与assignment
结合在一起。一般的形式为 v <op>= expression
,等同于 v = v <op> expression
,但是只对 v
求值一次(这在下标变量中非常重要)。
可用的增量运算符有:
+= |
if 语句
if
, elif
和 else
语句提供基本的判断能力。测试表达式求值为 false(None、0 或空)或 true(非 0 或非空)。
采用下列形式有条件地执行语句或块:
if expression: statement -- or -- if expression: |
下面是一个例子:
if x < 0: x = -x # ensure x is positive |
if-else 语句
采用下列形式在两个备选语句和/或块之间进行选择:
if expression: statement |
下面是一个例子:
if x >= 0: |
if-elif-else 语句
采用下列形式选择一组备选语句和/或块:
if expression: statement |
elif
子句可以重复。else
子句是可选的。下面是一个例子:
if x == 0: |
条件表达式
基于 C 的大多数语言(包括 C++ 和 Java 语言)都支持条件表达式。这些表达式返回子表达式的选择,在避免使用重复的目标时非常有用。如果目标包含复杂表达式(如下标),则这种功能很重要。条件表达式具有下列形式:
|
Jython 不直接支持条件表达式;而使用下面的形式:
if expression: target = true_expression; else: target = false_expression -- or -- if expression: target = true_expression |
在 Jython 中,可以使用 and
和 or
运算符来实现类似于 Java 条件表达式的形式,如下所示:
target = (expression) and (true_expression) or (false_expression) |
注意,这种形式只有在 true_expression
和 false_expression
求出的值不为 false 值(如 None
、0 或空序列或空映射)时才有效。如果求出的值为 false,则请使用 if-else
形式。
实现开关语句
Jython 不支持许多语言都支持的 switch
或 case
语句。if-elif-else
形式可以用于对有限数量的情况进行相似性测试。对于数量更多的情况,可以使用序列或映射来完成(请参见 Jython 函数 ),如下所示:
: |
while 语句
while
语句用于执行条件循环。只要表达式求出的值为 true,则执行循环。while
语句具有下列形式:
while expression: statement |
else
子句是可选的,只有在 while
子句正常结束(即没有使用 break
语句)时才执行。通常不使用该语句。
例子:
x = 10 |
下面是一个无限循环:
while 1: print "Hello!" |
for 语句
for
语句用于执行迭代循环。它处理从提供的expression
中返回的序列,依次获取每个元素。只要元素保留在该序列中,就执行循环。for
语句具有下列形式:
for vars in expression: statement |
else
子句是可选的,只有在 for
子句正常结束(即不使用 break
语句)时执行。
例子:
for c in "String": |
在上述代码中,使用 for i in range(limit)
提供了大多数语言都具有的 for-loop 或 do-loop 迭代。还要注意,keys
没必须要以提供的顺序输出。
break 和 continue 语句
有时需要在中间退出 while
或 for
。这通常是循环机制本身检测不到一些异常条件而产生的结果。break
语句提供该行为。该语句具有下列形式:
break |
下面是一个例子:
for i in range(100): |
同样,有时可能需要跳过循环体的其余部分,较早地开始下一个迭代。continue
语句提供该行为。该语句具有下列形式:
continue |
下面是一个例子:
for i in range(100): |
一般而言,break
和 continue
语句都作为 if
语句的目标出现的。只有紧密包含的循环才可被控制。
更新序列
在迭代的同时还更新(即插入和删除条目)序列的话,一定要特别小心,因为这可能会导致迭代索引不可预期地进行更改。建议您创建要迭代的序列的副本,如下所示:
for i in x[:]: # iterate over a copy |
del 语句
可变的序列(请参见 序列类型 )、映射(请参见 映射和字典)和类都支持 del
语句,该语句分别从集合或类中删除元素或属性。对序列而言,删除是按索引进行的;而对映射是按键值;对类是按属性名称。我们将在本教程的第 2 部分详细讨论 del
语句的类支持。
局部或全局变量可以被删除;这将从名称空间中删除变量(它不删除变量所引用的对象)。del
语句还支持切片表示法(slice notation)。
假设 "l" 是列表 [1,2,3,4,5],d 是字典 {1:"one", 2:"two", 3:"three"},而 x 某个类实例,下面是一些 del
语句的例子:
例子 | 注释 |
del l[0] |
删除第一个元素 |
del l[1:3] |
删除第二个到第三个元素 |
del l[::2] |
删除偶数元素 |
del l[:] |
删除所有元素 |
del d[1] |
删除带有键的元素1 |
del x.attr1 |
删除属性attr1
|
var = [1,2,3] : del var
|
从名称空间中删除变量var
|
Jython 函数
什么是函数?
任何编程语言的一个最重要的特性是代码重用。代码重用有两种主要方法:返回值的代码块(称为函数)和不返回值的代码块(称为子例程)。Jython 完全支持通过函数进行代码重用。
Jython 提供了许多可供您使用的内置函数和库函数(请参见 附录 E:内置函数 和 附录 F:Jython 库汇总)。内置函数无须导入就可使用;而库函数首先必须导入。
Jython 超越了许多语言(包括 Java 语言),它将函数作为一类对象,就像操纵其他对象一样操纵该对象(最为特别的是,对象可以存储在集合中,并作为参数传递给其他函数)。
def 语句
在 Jython 中,函数通过 def
语句声明,该语句具有以下形式:
def name ( args ): statement -- or -- def name ( args ): |
在给定的作用域(模块、函数或类)内,每个函数名都应是惟一的。函数名事实上是绑定到函数体的变量(类似于任何其他赋值)。实际上,可以定义多个变量来引用同一个函数。函数体可以是单个语句(通常是一个返回语句),也可以是语句块(这种情形更为常见)。
指定函数参数
def
语句中可选的 args 是逗号分隔的参数定义列表。下面是一些例子:
例子 | 注释 |
def x(a, b, c) |
定义有三个必需位置参数的函数。 |
def x(a, b, c=1) |
定义有三个参数的函数,最后一个参数是可选的,其默认值为 1。 |
def x(a=3, b=2, c=1) |
定义有三个参数的函数,这三个参数都是可选的,都有默认值。 |
def x(p1, p2, kw1=1, kw2=2) |
定义一个有两个位置参数和两个关键字(可选)参数的函数。声明该函数时,所有可选参数(=值)参数必须在所有非可选参数之后。调用该函数时,关键字参数(如提供)可以在位置参数之后按名称以任何顺序指定。 |
def x(p1, p2, *v) |
定义一个具有两个必需位置参数和数量不确定的变量参数的函数。v 变量将是一个元组。 |
def x(p1, p2, **kw) |
定义一个具有两个必需位置参数和数量不确定的变量参数的函数。kw 变量是字典。 |
def x(p1, p2, *v, **kw) |
定义一个具有两个必需位置参数和数量不确定的位置和关键字参数的函数。v 变量是元组。kw 变量是字典。 |
处理可变参数
如果参数接受可变对象(如列表和字典)的默认值,则最好采用下列形式:
def x(p1, p2, p3=None) |
而非下面简单的形式:
def x(p1, p2, p3=[]) |
由于等号后的值仅在定义函数时求值(并非每次调用时都求值),所以上面第二个例子中的列表将被对该函数的所有调用所共享。这种行为通常不是我们期望的。在第一个例子中,每个调用都获得了一个不同的列表。
匿名函数
您可以定义匿名函数,也叫做 lambda
函数。匿名函数通常是一行(one-line)的函数,通常用作其他函数的参数。这些函数采用下列形式声明:
lambda args: expression |
参数列表与在 指定函数参数 中描述的相同。每个 lambda
函数至少要有一个参数。表达式的值由函数返回。
return 语句
函数通过 return
语句返回值,该语句还有退出函数的功能。return
语句可以返回也可以不返回一个明确的值;如果没有指定任何值,则使用 None
。如果函数体的最后一个语句不是 return
语句,则假定执行无值返回。return
语句具有下列形式:
return expression -- or -- return |
另外,下面的形式使您可以作为元组返回多个值:
return expression1, expression2, ..., expressionN |
函数调用
函数是通过使用 call
运算符调用的,该运算符是函数引用后加括号的列表。例如,如果 f 是函数,则 f(...)
调用函数。如果函数定义支持参数,则调用可以包含参数,如下例所示:
函数定义 | 调用示例 | 注释 |
def x(a, b, c) |
x(1,2,3) x("1", "2", "3")
|
实参可以是任何类型。 |
def x(a, b, c=1) |
x(1,2,3) x(1,2)
|
参数c 可以省略 |
def x(a=3, b=2, c=1) |
x() x(1,2,3) x(c=10, a="d") x(1,c=5)
|
命名参数可以被视作位置参数、关键字参数或混合参数。如果是关键字参数,则顺序就不重要了。 |
def x(p1, p2, kw1=1, kw2=2) |
x(1,2) x(1,3,kw2=5)
|
既可以使用位置参数,又可以使用关键字参数。 |
def x(p1, p2, *v) |
x(1,2) x(1,2,3) x(1,2,3,4)
|
v 元组获得第三个参数或后续参数。 |
def x(p1,p2,**kw) |
x(1,2, aaa=1, mmm=2, zzz=3) |
关键字可以有任何名称。 |
def x(p1,p2,*v, **kw) |
x(1,2,3,4, aaa=1, xxx="yyy") |
v 元组获得第三个参数和后续位置参数,而字典 kw 获得具有值的 aaa 和xxx 关键字。 |
注意,在形参(parameter)声明和实参(argument)之间的空格是可选的。建议在两个参数之间添加空格以增加可读性。
函数定义和调用的例子
下面是一些函数定义和调用的例子。
def k(): return 1 # return the constant 1 |
global 语句
有时,您可能希望在局部上下文中声明变量(即赋值),但在全局作用域中引用变量。为此,请在第一次使用变量前使用 global
语句。下面是一个例子:
x = 10; y = 20; z = 30 # three global variables def f1(p, q, r): |
注意,只要全局变量没有被局部地重新绑定,那么在没有将其声明为全局的情况下,就可读取该变量。因此,只有在对全局变量赋值时才需要 global
语句。
泛型函数
与 Smalltalk 的函数类似,Jython 函数是泛型的,因为对每个参数而言,可以传递任何类型。这就使得函数极端灵活。只要对函数的参数执行的任何运算对参数的实际类型而言都是有效的,那么泛型函数就能工作正常。例如,对于下列函数定义
def sum (x, y): |
下列函数调用是有效的:
print sum(1, 2) # prints 3 print sum('123', '456') # prints 123456 print sum([1,2,3], [4,5,6]) # prints [1,2,3,4,5,6] print prod(2, 3) # prints 6 print prod('123', 2) # prints 123123 |
动态类型测试
您可以使用动态类型测试(即使用 isinstance
函数或比较 type
函数的结果)来获得更大的灵活性。有关更多信息,请参见 附录 G:Jython 类型汇总。下面是一个例子:
# See Part 2 of this tutorial for the definition of the UserList class |
嵌套函数
与许多其他语言(包括 Java 语言)不同,Jython 允许在其他函数内部定义函数。嵌套(或局部)函数有助于缩减函数的作用域。下面是一个例子:
def x(a, b, c): |
包含函数中的变量对嵌套函数是不可见的。如果嵌套函数必须使用这些值,则将这些值作为参数传递给嵌套函数。例如,下列函数
def calc(a, b, c): |
输出
{'data': {'x': 6000, 'c': 30, 'b': 20, 'sum': \ |
使用嵌套函数还能方便地创建(预先配置)要作为结果返回的函数,如下所示:
def makeSq(n): |
上述函数可以像下面这样使用:
sq2 = makeSq(2) |
函数式程序设计
与 Lisp 和 Smalltalk 一样,Jython 支持有限形式的函数式程序设计。函数式程序设计使用 Jython 函数的最优秀的特性并对函数和数据结构执行运算。下面展示了内置的函数式程序设计服务:
语法 | 用法/注释 | 例子 |
apply(func, pargs {, kargs}) func(*pargs {, **kargs})
|
执行具有提供了位置参数和可选关键字参数的函数。 | apply(lambda x, y: x*y, (10, 20)) --> 200 |
map(func, list, ...) |
根据将 func 应用于每个列表的每个元素所得的结果,创建一个新的列表。该函数的每个参数必须有一个列表。 |
map(lambda x, y: x+y, [1,2],[3,4]) --> [4,6] map(None, [1,2],[3,4]) --> [[1,3],[2,4]]
|
reduce(func, list {,init}) |
将func 依次应用于每对项,然后累加结果。 |
reduce(lambda x, y: x+y, [1,2,3,4],5) --> 15 reduce(lambda x, y: x&y, [1,0,1]) --> 0 reduce(None, [], 1) --> 1
|
filter(func, seq) |
根据 seq 选择的 func 为其返回 true 的项,创建一个新的列表。func 是一个参数(one-argument )的函数。 |
filter(lambda x: x>0, [1,-1,2,0,3]) --> [1,2,3] |
使用诸如 map
、reduce
和 filter
这样的函数,使得处理序列(即字符串、列表和元组)非常容易。这些函数是高阶(higher-order)函数,因为它们可以将函数作为参数或者作为结果返回。
函数式程序设计的例子
我们给出一些函数式程序设计的例子来结束这一节对 Jython 函数的讨论以及“介绍 Jython”教程的前半部分。
阶乘计算器可以通过 reduce
来实现:
def fac(x): |
可以使用 map
来修改列表:
l = [1, -2, 7, -3, 0, -11] |
在序列中可以使用 map
来执行一组函数:
def f1(x): return ... |
可以使用 map
来获得循环:
def body1(count): |
可以使用 filter
进行选择:
# Assume a class Employee exists with attributes |
下面是如何使用上述 filter
选择一些员工的例子:
# returns: [Jose] |
结束语和参考资料
结束语
在两部分“介绍 Jython”教程的前半部分,您了解了有关使用 Jython 的概念和编程基础知识,包括访问选项和文件编译、语法和数据类型、程序结构、过程语句和使用 Jython 进行函数式程序设计。
本教程的第 2 部分将研究该语言的一些更高级的特性,对用 Jython 进行面向对象的程序设计进行概念上和实际介绍。您还学习在 Jython 中进行调试、字符串处理、文件 I/O 和 Java 支持。本教程结束时,将对如何用 Jython 构建一个可以工作的 GUI 应用程序进行令人兴奋的、实际的演示。
最好是趁您对第 1 部分的内容还有很深印象的时候,就来学习第 2 部分的内容。如果您中断一段时间,那么可以花时间来研究第 1 部分附带的附录(附录 ),或购买一些 参考资料 一节中包含的参考资料。
参考资料
- 下载本教程的代码jython1-source.zip。
- 访问 Jython 主页下载 Jython。
- 获得本教程“Introduction to Jython, Part 2: Programming essentials”的第 2 部分(developerWorks,2004 年 2 月)。
- 了解添加或更新 Jython registry 文件的更多信息。
- Jython 模块和包使得可以重用扩展的标准 Java 库。在 Java technology 主页了解 Java 库的更多信息(并下载当前版本的 JDK)。
- 您可以在 Python 主页找到 Python Library Reference、Python 文档和 Python 教程。
- 在“Charming Jython”一文中(developerWorks,2003 年 5 月),developerWorks 的定期投稿人员 Uche Ogbuji 对 Jython 进行了简短的介绍。
- 阅读 Eric Allen 的“Repls provide interactive evaluation”(developerWorks,2002 年 3 月)后,试着使用 Jython 构建一个“读等于输出循环(read-eval-print-loop)”。
- 可爱的 Python 是一个定期的 developerWorks 栏目,致力于使用 Python 进行程序设计。
- 要获得对 Jython 的全面介绍,请参见 Samuele Pedroni 和 Noel Rappin 所著的 Jython Essentials(O'Reilly,2002 年 3 月)。
- Jython for Java Programmers 主要介绍使用 Jython 进行应用程序开发、部署和优化(Robert W. Bill 和 New Riders,2001 年 12 月)。
- Python Programming with the Java Class Libraries (Richard Hightower 和 Addison Wesley, 2003 年)很好地介绍了使用 Jython 构建 Web 和企业应用。
- 您可以在 developerWorks Java 技术专区 找到有关 Java 编程各方面的文章。
- 访问 Developer Bookstore 获得技术书籍的全面列表,其中包括数百本与 Java 有关的书籍。
- 另请参见 Java 技术专区教程页面,在此可以获得来自 developerWorks 的免费 Java 教程的完整列表。
-
附录
附录 A:转义字符
有几种特殊字符需要加反斜杠:
反斜杠表示 字符 \t
制表符 \v
垂直制表符 \n
换行 \r
回车 \f
换页 \"
引号 \'
撇号 \\
反斜杠 \b
退格 \a
铃声 \000
八进制值(3 个基数为 8 的数字,范围为 0-3778) \xXX...
十六进制值(2 个基数为 16 的数字,范围为 0-FF16),在字符串中使用(即 "\x31" --> '1') \uXXXX...
十六进制值(4 个技术为 16 的数字,范围为 0-FFFF16);在 unicode 字符串中使用(即 u"\u0031" --> '1') 附录 B:字符串方法
字符串支持几种有用的方法:
方法 用法 例子 s.capitalize()
对 s 执行首字母大写 "abc".capitalize() --> "Abc" s.count(ss {,start {,end}})
计算 ss 在 s[start:end] 的出现次数 "aaabbccc".count("ab") --> 1 s.startswith(str {, start {, end}})
s.endswith(str {, start {, end}})测试 s 是否以 str 开头/结尾 "xxxyyyzzz".startswith("xx") --> 1 s.expandtabs({size})
用空格替换制表符(tab),默认大小为 8 "x\ty".expandtabs(4) --> "x y" s.find(str {, start {, end}})
s.rfind(str {, start {, end}})
在 s 中查找 str 的第一个索引;如果找不到,则返回 -1,rfind 从右到左进行搜索 "12345".find('23') --> 1 s.index(str {, start {, end}})
s.rindex(str {, start {, end}})
在 s 查找 str 的第一个索引;如果找不到,则引发 ValueError。rindex 从右到左搜索 "12345".index('23') --> 1 s.isalnum
测试字符串是否是字母数字型的 "12345abc".isalnum() --> 1 s.isalpha
测试字符串是否是按字母顺序排列的 "12345abc".isalpha() --> 0 s.isnum
测试字符串是否是数值型的 "12345abc".isnum() --> 0 s.isupper
测试字符串是否是全大写的 "abc".isupper() --> 0 s.islower
测试字符串是否是全小写的 "abc".islower() --> 1 s.isspace
测试字符串是否全是空格 "12345 abc".isspace() --> 0 s.istitle
测试字符串是否是首字母大写的字母数字字符串 "Abc Pqr".istitle() --> 1 s.lower()
s.upper()
s.swapcase()
s.title()
转换为全小写、大写、大小写颠倒或标题形式 "abcXYZ".lower() --> "abcxyz" "abc def ghi".title() --> "Abc Def Ghi" s.join(seq)
将 seq 中的字符串连接起来,以 s 作为分隔符 " ".join(("hello", "goodbye") --> "hello goodbye" s.splitlines({keep})
将 s 分割为多行,如果 keep 为 true,则使用换行 "one\ntwo\nthree".splitlines() --> ["one", "two", "three"] s.split({sep {, max}})
用 sep(默认为空格)将 s 分割为“字”,直到最大次数 "one two three".split() --> ["one", "two", "three"] s.ljust(width)
s.rjust(width)
s.center(width)
s.zfill(width)
在字段宽度中,向左、右或中心调整字符串。用 0 进行填充。 "xxx".rjust(8) --> " xxx" "xxx".center(8) --> " xxx " str(10).zfill(10) --> "0000000010" s.lstrip()
s.rstrip()
s.strip()
删除前导(和/或尾部)空格 " xxx ".strip() --> "xxx" s.translate(str {,delc})
删除 delc 中的任何字符后,使用表转换 s。str 应为长度为 256 的字符串 "ab12c".translate(reversealpha, "0123456789") --> "cba" s.replace(old, new {, max})
用字符串 new 全部替换或按照 max 出现次数替换旧字符串 old "11111".replace('1', 'a', 2) --> "aa111" 注意: 其他方法也得到支持,要获得完整列表,请参见 Python Library Reference(参考资料)。还要注意,通过包含字符串模块,许多(但非全部)方法还可以作为函数进行调用,即-
string.center(s, 10)
与s.center(10)
相同。字符串模块有一些重要的变量:
变量 注释 digits octdigits hexdigits 十进制、八进制和十六进制数字 lowercase uppercase letters 小写字母表、大写字母表和两者的混合 whitespace 合法的空格字符 附录 C:列表方法
列表支持几种有用的方法。
函数 注释 例子 x in l x not in l 测试包含性 1 in [1,2,3,4] --> 1 l.count(x) 计算 x 的出现次数。使用 "==" 进行测试。 [1,2,3,3].count(3) --> 2 l.append(x) -- 或者 -- l = l + [x] 将 x 附加到列表 [1,2].append([3,4]) --> [1,2,[3,4]] [1,2] + [3] --> [1,2,3] l.extend(list) 附加列表的元素 [1,2].extend([3,4]) --> [1,2,3,4] l.index(item) 查找列表中项的索引;如果不存在,则引发 ValueError [1,2,3,4].index(3) --> 2 l.insert(index, x) -- 或者 -- l[i:i] = [x] 将 x 插入到列表中索引之前 [1,2,3].insert(1, 4) --> [1,4,2,3] l.pop({index}) 删除第 n 个(默认为最后一个)项 [1,2,3,4].pop(0) --> [2,3,4], 1 [1,2,3,4].pop() --> [1,2,3], 4 l.remove(x) 从列表中删除项 [1,2,3,4].remove(3) --> [1,2,4] l.reverse() 翻转列表(在适当位置) [1,2,3].reverse() --> [3,2,1] l.sort({cmp}) 对列表排序(在适当位置);cmp 函数用于对项排序。cmp 函数带有两个参数并返回 <0, 0, >0 [1,4,3,2].sort() --> [1,2,3,4] 附录 D:映射方法
映射支持几种有用的方法。
方法 注释 m.clear() 清空映射 m.copy() 创建映射的浅副本 m.has_key(k) -- 或者 -- k in m 测试键是否存在 m.items() 获得键/值元组的列表 m.keys() 获得键的列表 m.values() 获得值的列表(可能有重复) m1.update(m2) 将 m2 中的所有项添加到 m1 中 m.get(k{, default}) m.setdefault(k, default) 获得 k 的值,如果缺少值,则返回默认值/KeyError;与 get 相同,但 set(设置)一个持久的默认值 m.popitem() 获得和删除某些项,在对映射的迭代期间使用。例如: m = {1:1, 2:2, 3:3}
while len(m) > 0:
i = m.popitem()
print i附录 E:内置函数
Jython 提供了非常有用的内置函数,不导入就可使用这些函数。下面汇总了最常使用的内置函数:
语法 用法/注释 例子 abs(x) 绝对值 abs(-1) --> 1 apply(func, pargs {, kargs}) -- 或者 -- func(*pargs {, **kargs}) 执行具有提供的位置参数和可选关键字参数的函数 apply(lambda x, y: x * y, (10, 20)) --> 200 callable(x) 测试对象是否可调用(即是否是函数、类或实现 __call__) callable(MyClass) --> 1 chr(x) 将整数 (0 - 65535) 转换为 1 个字符的字符串 chr(9) --> "\t" cmp(x, y) 将 x 与 y 进行比较, 如果 x < y,返回 negative(负),如果 x == y,返回 0, 如果 x > y,返回 positive(正)。 cmp("Hello", "Goodbye") --> > 0 coerce(x, y) 返回已强制为常见类型的 x 和 y 的元组 coerce(-1, 10.2) --> (-1.0, 10.2) compile(text, name, kind) 编译来自源文件名的文本字符串。Kind 是:"exec"、"eval" 或 "single" x = 2
c = compile("x * 2",
"<string>", "eval")
eval(c) --> 4complex(r, i) 创建复数 complex(1, 2) --> 1.0+2.0j complex("1.0-0.1j") --> 1.0-0.1j dir({namespace}) 返回名称空间中键的列表(如果省略,则名称空间是局部的) dir() --> [n1, ..., nN] vars({namespace}) 返回名称空间(如果省略,则名称空间是局部的);请不要对它进行更改 vars() --> {n1:v1, ..., nN:vN} divmod(x, y) 返回元组 (x /y, x % y) divmod(100, 33) --> (3, 1) eval(expr {, globals {, locals}}) 求出提供的名称空间中表达式的值 myvalues = {'x':1, 'y':2}
eval("x + y", myvalues) --> 3execfile(name {,globals {, locals}}) 读取和执行提供的名称空间中的指定文件 execfile("myfile.py") filter(func, list) 对 func 返回 true 的那些项创建项的列表 filter(lambda x: x > 0, [-1, 0, 1, -5, 10]) --> [1, 10] float(x) 将 x 转换为浮点数 float(10) --> 10.0 float("10.3") --> 10.3 getattr(object, name {, default}) 获得对象属性的值;如果未定义,则返回默认值(或如果没有默认值,则返回异常) getattr(myObj, "size", 0) --> 0 setattr(object, name, value) 创建/设置对象属性的值 setattr(myObj, "size", 10) hasattr(object, name) 测试对象是否有属性 hasattr(myObj, "size") --> 0 globals() 返回当前全局名称空间字典 {n1:v1, ..., nN:vN} locals() 返回当前局部名称空间字典 {n1:v1, ..., nN:vN} hash(object) 返回对象的散列值。与 java.lang.Object.hashCode()
类似hash(x) --> 10030939 hex(x) 返回 x 的十六进制字符串 hex(-2) --> "FFFFFFFE" id(object) 返回对象的惟一稳定的整数 id id(myObj) --> 39839888 input(prompt) 提示输入并对提供的输入表达式求值;等同于 eval(raw_input(prompt))
input("Enter expression:") with "1 + 2" --> 3 raw_input(prompt) 提示并输入字符串 raw_input("Enter value:") with "1 + 2" --> "1 + 2" int(x{, radix}) 转换为整数;radix:0, 2..36; 0 意味着猜测 int(10.2) --> 10 int("10") --> 10 int("1ff", 16) --> 511 isinstance(object, class) 测试对象是否是类的实例或类的子类的实例;类可以是要测试多个类型的类的元组 isinstance(myObj, MyObject) --> 0 isinstance(x, (Class1, Class2)) --> 1 issubclass(xclass, clsss) 测试 xclass 是否是类的子类或同一类;类可以是要测试多个类型的类的元组 issubclass(MyObject, (Class1, Class2)) --> 0 len(x) 返回序列或映射的长度(项的数量) len("Hello") --> 5 list(seq) 将序列转换为列表 list((1, 2, 3)) --> [1,2,3] list("Hello") --> ['H','e','l','l','o'] tuple(seq) 将序列转换为元组 tuple((1, 2, 3)) --> (1,2,3) tuple("Hello")--> ('H','e','l','l','o') long(x {, radix}) 转换为长整数;radix:0, 2..36; 0 意味着猜测 long(10) --> 10L long("10000000000") --> 10000000000L map(func, list, ...) 根据将 func 应用于每个列表的每个元素所得的结果,创建一个新的列表 map(lambda x,y: x+y, [1,2],[3,4]) --> [4,6] map(None, [1,2],[3,4]) --> [[1,3],[2,4]] max(x) 返回最大值 max(1,2,3) --> 3 max([1,2,3]) --> 3 min(x) 返回最小值 min(1,2,3) --> 1 min([1,2,3]) --> 1 oct(x) 转换为八进制字符串 oct(10) --> "012 oct(-1) --> "037777777777" open(name, mode {, bufsize}) 返回一个打开的文件。Mode 是:(r|w|a){+}{b} open("useful.dat", "wb", 2048) ord(x) 返回字符的整数值 ord('\t') --> 9 pow(x,y) pow(x,y,z) 计算 x ** y 计算 x ** y % z pow(2,3) --> 8 range({start,} stop {, inc}) xrange({start,} stop {, inc}) 返回范围从 start 到 stop 步进为 inc 的序列;start 默认值为 0;inc 默认值为 1。将 xrange 用于大型序列(指大于 20 个项) range(10) --> [0,1,2,3,4,5,6,7,8,9] range(9,-1,-1) --> [9,8,7,6,5,4,3,2,1,0] reduce(func, list {, init}) 将 func 依次应用到每对项,并累加结果 reduce(lambda x,y:x+y, [1,2,3,4],5) --> 15 reduce(lambda x,y:x&y, [1,0,1]) --> 0 reduce(None, [], 1) --> 1 repr(object) -- 或者 -- `object` 转换为可以从中重新创建对象的字符串(如有可能) repr(10 * 2) --> "20" repr('xxx') --> "'xxx'" x = 10; `x` --> "10'" round(x {, digits}) 对数字四舍五入 round(10.009, 2) --> 10.01 round(1.5) --> 2 str(object) 转换为对人友好的字符串 str(10 * 2) --> "20" str('xxx') --> 'xxx' type(object) 返回对象的类型(与类不同)。要获得类,请使用 object.__class__
。模块类型包含所有 Jython 类型的符号名称x = "1"; type(x) is type('') --> 1 zip(seq, ...) 将序列压缩(zip)在一起;只要是最短输入序列,则结果是惟一的 zip([1,2,3],"abc") --> [(1,'a'),(2,'b'),(3,'c')] 有关更多信息,请参见 Python Library Reference(参考资料)。
附录 F:Jython 库汇总
Jython 支持大量的 Python 库。只使用这些库,就可编写在任何 Python 环境中运行的 Jython 程序。许多库提供的功能都与 Java API 提供的相同。Jython 还可以访问所有的 Java 库。这意味着它可以胜任 Java 程序的所有工作,但不再可以在 Python 环境中运行程序。
用 Python 编写的且不依赖操作系统特定服务的大多数库都得到支持,无须进行更改。许多库都随 Jtyhon 提供。而用 C 编写的库必须进行转换;许多核心 C 库都已转换且随 Jython 一起提供。
Jython 自己还有一些独一无二的库。这些库补充了 Java 本身提供的扩展 API 库。有关这些库的更多信息,请阅读源文件(在<jython_install_dir>/Lib/<lib_name>.py)或参见 Python Library Reference(参考资料)。
随 Jython 提供的更有趣的外部库包括:
库 注释(大多来自库 prolog) atexit 允许程序员定义多个要在正常程序终止时执行的退出函数 base64 根据 RFC-1521 转换为 base64 的传输编码/从 base64 的传输编码转换回来 BaseHTTPServer HTTP 服务器基类(抽象) bdb 普通 Python 调试器基类 bisect 某些 Bisection 算法 calendar 日历输出函数(英语) cgi 支持 CGI(公共网关接口)脚本的模块 CGIHTTPServer 支持 CGI 的 SimpleHTTPServer cmd 构建面向行的命令解释器的泛型类 code 模仿 Python 的交互解释器所需的工具 codecs Python Codec Registry、API 和 helper(抽象) colorsys RGB 和其他颜色系统之间的转换函数 ConfigParser 配置文件解析器 Cookie cookie 是一个模块,用于处理作为字典的 HTTP cookie copy 普通(浅和深)复制操作 difflib 计算对象之间增量的工具 dircache 读取和缓存目录列表 doctest 在文档字符串中运行例子的框架(与 JUnit 有些像);下面我推荐单元测试 dumbdbm 哑而慢但却简单的 dbm 克隆 fileinput 通过所有标准输入文件快速编写循环的类 fnmatch shell 模式的文件名匹配 formatter 普通输出格式化框架(抽象) fpformat 普通的浮点格式函数 ftplib FTP 客户机和一些 helper 函数 getopt 命令行选项的解析器(UNIX 风格) glob 文件名匹配(globbing)(匹配路径名模式的路径列表)工具 gopherlib Gopher 协议客户机接口 gzip 读写 gzipped 文件的函数 htmlentitydefs HTML 字符实体参考 httplib HTTP/1.1 客户机库 imaplib IMAP4 客户机 imghdr 根据前几个字节识别所选的图像文件格式 isql 为使用数据库提供一个交互式环境 linecache 从文件缓存行 mailcap Mailcap 文件处理。请参见 RFC 1524 mimetools 由 MIME 读取程序或 MIME 写入程序使用的各种工具 mimetypes 猜想文件的 MIME 类型 MimeWriter 普通 MIME 写入器 mimify 邮件消息的 MIME 化和反 MIME 化 multifile 多部分消息中部分消息的 readline() 风格的接口 nntplib 基于 RFC 977:网络新闻传输协议的 NNTP 客户机类 nturl2path 将 NT 路径名转换为文件 URL,反之亦然 pdb Python 调试器 pickle 创建 Jython(非 Java)对象的可移植序列化表示 pipes 转换管道模板 poplib POP3 客户机类 posixfile 在 POSIX 中可获得的扩展文件操作 pprint 递归支持美化输出列表、元组和字典 profile 对 python 代码进行概要分析的类 pstats 在已进行概要分析的 python 代码上打印报告的类 pyclbr 解析 Python 文件并检索类和方法 Queue 多个生产者、多个消费者队列 quopri 根据 RFC-1521 转换成 quoted-printable 传输编码/从 quoted-printable 传输编码转换回来 random 随机变量生成器 re 正则表达式引擎(克隆 sre) repr 重做 '...'(表示)但对大多数大小有限制 rfc822 RFC-822 消息操纵类 sched 普通而有用的事件调度程序类 sgmllib 与 SAX 类似的 SGML(用作 HTML 的子集)解析器,使用派生的类作为静态 DTD(抽象) shelve 管理 pickled 对象的存储方式(持久性方式,字典方式) shutil 复制文件和字典树的工具函数 SimpleHTTPServer 简单的 HTTP 服务器(仅为文本 HEAD 和 GET) smtplib 符合 RFC-821 (SMTP) 和 RFC-1869 (ESMTP) 的 SMTP/ESMTP 客户机类 sndhdr 帮助识别选择声音文件的例程 socket 基本的套接字支持 SocketServer 普通的套接字服务器类 sre 正则表达式引擎 stat 用于解释 os.stat() 和 os.lstat() 结果的常数/函数 string 公共字符串操纵;一个非常有用的字符串运算集合。字符串类型还支持将大多数函数作为方法。 StringIO 类似于文件的对象,它从字符串缓冲中读取或写入到字符串缓冲中 telnetlib 基于 RFC-854 的 TELNET 客户机类 tempfile 临时文件和文件名 threading 新线程模型,模仿 Java 平台的线程模型的子集 tokenize 对 Python 程序进行标记(tokenization)支持 traceback 提取、格式化和打印有关 Python 堆栈跟踪的信息 unittest Python 单元测试框架,基于 Erich Gamma 的 JUnit 和 Kent Beck 的 Smalltalk 测试框架 urllib 打开任意的 URL urlparse 解析(绝对和相对)URL user 允许用户指定的定制代码在启动时运行的钩子(hook) UserDict 将字典对象包装起来的几乎完整的用户定义的包装器 UserList 将列表对象包装起来的几乎完整的用户定义的包装器 UserString 将字符串对象包装起来的几乎完整的用户定义的包装器 whrandom Wichman-Hill 随机数生成器 xmllib 类似于 SA 的 XML 解析器,将派生的类用作静态 DTD(抽象) zipfile 读和写 ZIP 文件 __future__ 用于访问可在今天获得的将来版本的功能(可能不如最终的功能) 注意:我并没说上述库模块在 Jython 中使用时没有错误,特别是您运行的不是 UNIX 系统时。在决定使用它们进行编码之前,请尝试采用交互方式使用它们。
附录 G:Jython 类型汇总
Jython 支持许多对象类型。模块类型定义这些类型的符号。函数类型 获得任何对象的类型。类型值可以被测试(请参见 动态类型测试)。下表总结了最常用的类型。
类型符号 Jython 运行时类型 注释 ArrayType PyArray 任何数组对象 BuiltinFunctionType PyReflectedFunction 任何内置的函数对象 BuiltinMethodType PyMethod 任何内置的方法对象 ClassType PyClass 任何 Jython 类对象 ComplexType PyComplex 任何复杂对象 DictType -- 或者 -- DictionaryType PyDictionary 任何字典对象 FileType PyFile 任何文件对象 FloatType PyFloat 任何浮点对象 FunctionType PyFunction 任何函数对象 InstanceType PyInstance 任何类实例对象 -- 无 -- PyJavaInstance 任何 Java 类实例对象 IntType PyInteger 任何整数对象 LambdaType PyFunction 任何 lambda 函数表达式对象 ListType PyList 任何列表对象 LongType PyLong 任何长整型对象 MethodType PyMethod 任何非内置的方法对象 ModuleType PyModule 任何模块对象 NoneType PyNone 任何 None
(只有一个)对象StringType PyString 任何 ASCII 字符串对象 TracebackType PyTraceback 任何异常跟踪对象 TupleType PyTuple 任何元组对象 TypeType PyJavaClass 任何类型对象 UnboundMethodType PyMethod 任何方法(无绑定实例)对象 UnicodeType PyString 任何 Unicode 字符串对象 XRangeType PyXRange 任何扩展的范围对象 注意:几个类型映射到相同的 Java 运行时类型。
有关类型的详细信息,请参见 Python Library Reference(参考资料)。
附录 H:格式代码
格式运算符(请参见格式化字符串和值)支持下列格式字符:
字符 结果格式 注释 %s, %r 字符串 %s 执行 str(x)
, %r 执行repr(x)
%i, %d 整数 十进制数 格式基本上相同 %o, %u, %x, %X 无符号值 八进制、无符号十进制和十六进制 %f, %F 浮点十进制数 显示小数点后面的部分 %e, %E, %g, %G 指数 %g 是 %f,除非值很小;否则是 %e %c 字符 必须为单个字符或整数 %% 字符 % 字符 注意: 有关格式项的结构和选项的更详细信息可以在 Python Library Reference(参考资料)中找到。格式字符串是区分大小写的(例如,X vs x 使符号以匹配的大小写显示出来)。
-
关于作者
Barry Feigenbaum 博士是 IBM Worldwide Accessibility Center 的成员,他参加了一个致力于解决让伤残人员能访问 IBM 产品的团队。Feigenbaum 博士已出版了一些书籍和文章,拥有若干项专利,在行业大会如 JavaOne 上发表过演讲。他在奥斯汀的得克萨斯大学兼任助理教授。
Feigenbaum 博士有 10 年以上使用面向对象语言(如 C++、Smalltalk、Java 编程语言和 Jython)的经验。工作中经常使用 Java 语言和 Jython。Feigenbaum 博士是一个 Sun 认证的 Java 程序员、开发人员和架构师。可以通过 feigenba@us.ibm.com 与他联系。
致谢
我要感谢 Mike Squillace 和 Roy Feigel,感谢他们对本教程进行了杰出的技术评审。