【转】介绍Jython,第一部分:轻轻松松写JAVA程序

2023-03-14,,

本文转自: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
Volume Serial Number is ????-???? Directory of C:\Jython-2.1 --/--/---- --:--- <DIR> .
--/--/---- --:--- <DIR> ..
--/--/---- --:--- 1,873 ACKNOWLEDGMENTS
--/--/---- --:--- <DIR> cachedir
--/--/---- --:--- <DIR> com
--/--/---- --:--- <DIR> Demo
--/--/---- --:--- <DIR> Doc
--/--/---- --:--- <DIR> installer
--/--/---- --:--- 428 jython.bat
--/--/---- --:--- 719,950 jython.jar
--/--/---- --:--- 272 jythonc.bat
--/--/---- --:--- <DIR> Lib
--/--/---- --:--- 7,184 LICENSE.txt
--/--/---- --:--- 18,178 NEWS
--/--/---- --:--- <DIR> org
--/--/---- --:--- 651 README.txt
--/--/---- --:--- 4,958 registry
--/--/---- --:--- <DIR> Tools
--/--/---- --:--- 224,493 Uninstall.class
9 File(s) 977,987 bytes
? Dir(s) ??? bytes free

 

回页首

测试运行

最后的步骤是确保配置了 Jython。要运行 Jython,请输入下列命令启动 Jython:

C:\>c:\jython-2.1\jython

执行该命令后应该产生一个与下面类似的介绍:

Jython 2.1 on java1.4.1_01 (JIT: null)
Type "copyright", "credits" or "license" for more information.

最后退出 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
rem This file generated by Jython installer
rem
JAVA_HOME=<java_home>
rem
rem collect all arguments into %ARGS%
set ARGS=
:loop
if [%1] == [] goto end
set ARGS=%ARGS% %1
shift
goto loop
:end %JAVA_HOME%\bin\java.exe
-Dpython.home=C:\jython-2.1
-cp "C:\jython-2.1\jython.jar;%CLASSPATH%"
org.python.util.jython %ARGS%

 

回页首

一切都是解释型的

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)
Type "copyright", "credits" or "license" for more information.
>>> 1 + 2
3
>>> "Hello" + "Goodbye"
'HelloGoodbye'
>>> def fac(x):
... if x <= 1: return 1
... return long(x) * fac(x-1)
...
>>> fac(3)
6L
>>> fac(100)
93326215443944152681699238856266700490715968264381621468592963895217599
99322991560894146397615651828625369792082722375825118521091686400000000
0000000000000000L
>>> import sys; sys.exit(0)
C:\>

通过这个例子,可以看到输入会很快得到执行。而输入包括简单表达式和更复杂的操作,如函数定义(即 fac 函数)。已定义的值和函数可以立即使用。还应注意,Jython 通过 long 类型支持非常大的整数。

注意上例中 fac 函数的缩进非常重要。在本教程的后面,您将了解有关该要求的更多信息(请参见 块)。

 

回页首

通过源文件使用 Jython

如果 Jython 只接受命令行输入,那它的用处就不太大;因此,它还允许接受源文件。Jython 源文件以扩展名 .py 结束。Jython 文件必须包含一系列 Jython 语句。表达式,如 1 + 2,并不是有效的语句(虽然执行,但不生成显示的输出)。

要显示表达式,必须将其放在 print 语句中。因此,上一节的序列可以编码在源文件中,如下所示:

print 1 + 2
print "Hello" + "Goodbye"
def fac(x):
if x <= 1: return 1
return long(x) * fac(x-1)
print fac(3)
print fac(100)

上述代码产生的输出与 将 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):
if x <= 1: return 1
return long(x) * fac(x-1) if __name__ == "__main__":
print 1 + 2
print "Hello" + "Goodbye"
print fac(3)
print fac(100)

同样,运行该文件会产生与以前相同的结果。但如果文件被导入到另一个只希望重用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...
For -1 result = Exception - only positive integers supported: -1
For 0 result = 1
For 1 result = 1
For 10 result = 3628800
For 100 result =
93326215443944152681699238856266700490715968264381621468592963895217599
99322991560894146397615651828625369792082722375825118521091686400000000
0000000000000000
For 1000 result = 4023872600770937735437024
... many digits removed ...
00000000000000000000

注意,这个输出与直接使用 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
浮点值可以有小数部分。浮点数支持与 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 转换为复数

注意:对于数值类型,操作数被提升到下个较高的类型。对于整数操作数, /、% 和 ** 都产生整数结果。对于 intlong 、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))
print "Cosine of %f = %f" % (0.5, cos(0.5))
print "Tangent of %f = %f" % (0.5, tan(0.5))

示例代码产生下列输出:

PI = 3.141593, e = 2.718282
Sine of 0.500000 = 0.479426
Cosine of 0.500000 = 0.877583
Tangent of 0.500000 = 0.546302

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 中是一种抽象概念,因为您不能直接创建序列,只创建从序列派生而来的子类型。任何序列子类型都具有序列的全部函数。序列子类型有几个,如下所示:

字符串 是字符的不变序列(请参见 字符串)。
元组 是任何数据类型的不变序列(请参见 元组)。
范围 是整数的不变序列(请参见 范围)。
列表 是任何数据类型的可变序列(请参见 列表)。
 

回页首

字符串

字符串是字符的不变序列,可以被视为一个值。同样,字符串支持产生新字符串的所有不变序列的函数和运算符。例如,"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
single or triple quoting.
Strings defined using single quotes cannot span
lines while strings using triple quotes can.
A string may be enclosed in quotes (") or apostrophes (').
They may contain the other character un-escaped
or the quoting character escaped
(proceeded by the backslash (\) character."""

而下面是一个短的混合引号字符串:'''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!
Name: Feigenbaum, Barry

 

回页首

元组

元组是任何类型的不变列表。一旦创建就不能更改。元组可以具有任何长度且可以包含任何类型的对象。下面展示了一些例子:

例子 注释
() 空元组
(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]
print range(2,20,2) # prints [2,4,6,8,10,12,14,16,18]
print range(10,0,-1) # prints [10,9,8,7,6,5,4,3,2,1]

 

回页首

列表

列表是任意类型的可变序列。列表的长度可以增加,也可以缩小,而列表中的元素可以替换,也可以删除。列表可以是任何长度,也可以包含任何类型的对象。有关列表函数的更多信息,请参见 附录 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]
x = l.pop(-1) # x is 5, l is [1,2,3,4]
y = l.pop(0) # y is 1, l is [2,3,4]
z = l.pop(0) # z is 2, l is [3,4]

 

回页首

列表内涵

列表也可以通过称为列表内涵(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)"
if x <= 1: return 1 # base case
return long(x) * fac(x-1) # use recursion on reduced case
:
print fac.__doc__

产生的输出

The fac function computes the value x! (x factorial)

 

回页首

语句语法

从以上各节可以知道,Jython 的语法很简单。它与英语非常类似,而不像 C 和 Java 语言。具体来说,每个源代码行(通常)是单个语句。除了 expression 和 assignment 语句外,每个语句都由关键字名称(如 if 或 for)引入。在任意两个语句之间都可以加空行或备注。

不需要在每行的结尾加分号,但如果愿意,也可以加。如果希望每行包含多条语句,则需要用分号来分隔语句。

如有必要,语句可以延续到超过一行。将一个反斜杠字符放在一行的末尾可以延续到任意行,如下所示:

x = "A looooooooooooooooooooooooooooooooong string " + \
"another looooooooooooooooooooooooooooooooong string"

如果是在用圆括号(())、方括号 ([]) 或花括号 ({}) 括住的结构中间,则可以在该结构的任何逗号后继续该行,而无须使用反斜杠。下面是一个例子:

x = (1, 2, 3, "hello",
"goodbye", 4, 5, 6)

 

回页首

标识符和保留字

Jython 支持与 C++ 和 Java 名称相似的标识符。标识符用于给变量、函数和类命名,还可以用作关键字。标识符可以是任何长度,必须以字母(大写或小写)或下划线字符开头,可以是字母、十进制数字和下划线的任意组合。如 abcabc123_xx_myName和 ONE是一些有效的标识符,123abc$xyz 和 abc pqr是一些无效的标识符。

注意,以下划线开头的名称通常保留用作内部名称或专有名称。

Jython 还有几个保留字(或关键字),它们不能用作变量、函数或类的名称。这些关键字分为下列几类:

引入语句的关键字assertbreakclasscontinuedefdelelifelseexceptexecfinallyforfromglobalifimportpassprintraisereturntry和 while
引入参数的关键关键字asimport 和 in
运算符andinislambdanot 和 or

注意,关键字可以用于特殊环境中,如方法的名称。例如,您可以使用关键字调用与 Jython 关键字具有相同名称的 Java 方法。不正确的关键字通常会导致 SyntaxError

 

回页首

(或套件)是语句组,用在希望使用单个语句的地方。所有可以将语句块作为目标的语句都通过冒号字符引入块。下列语句(或语句子句)将块作为目标:ifelifelseforwhiletryexceptdef 和 class。不管是由逗号分隔的单条语句,还是小语句组,都可以跟在同一行冒号的后面,块可以跟在后续行缩进的语句后。

我强烈建议使用空格进行缩进。在具有不同制表符停止位(tab stop)的系统(或编辑器)之间移动时,使用制表符可能出现问题。请不要在同一源文件中混用制表符和空格。按照约定,每一层使用四个空格。

注意: 模块最外面的块中的所有行都必须从第一列开始,否则会产生 SyntaxError

 

回页首

示例块

与 C 和 Java 语言不同,在 Jython 中,不是使用花括号,而是使用缩进来划分块。例如:

# the following prints 0 through 10 on one line
for i in range(10):
# print next value
print i,
print # new line

输出为:0 1 2 3 4 5 6 7 8 9.

作为 for 循环主体的块由缩进代码指出。主体中的所有行(除注释外)都必须缩进到相同的位置。同一个循环可以编写为:

# the following prints 0 through 10 on one line
for i in range(10): print i, # print next value
print # new line

 

回页首

可见性和作用域

Jython 支持下列作用域:

内置 符号,由 Jython 运行时定义,它总是可用的,除非在另一个作用域中重新进行了定义。
全局 变量对整个模块都可见,包括在该模块中声明的函数和类。当前全局作用域中的变量的字典可以通过 globals 函数访问。
局部函数参数和变量,它在函数体中声明,对该块可用。当前局部作用域中的变量名的字典可以通过 locals 函数访问。在模块中和任何函数之外,局部作用域和全局作用域都是相同的。

一般而言,变量在声明它们的块的作用域中和在该作用域中定义的任何函数中都是可见的(请参见 Jython 函数 )。变量在每个作用域中只能声明一次;后续使用会重新绑定该变量。与在 C++ 和 Java 语言中不同,函数中的嵌套块不会开始一个新作用域。

 

回页首

动态代码求值

Jython 与一般的语言不同,它有能力动态创建代码,然后执行。例如,在计算器应用程序中,用户可以用文本形式输入表达式,Jython 可以直接执行该表达式(假设它符合 Jython 源代码规则)。

要较好地了解 Jython 如何对动态代码解释/求值,请考虑下列代码:

v1 = 100; v2 = 200
l1 = [1, 2, v1, v2]
d1 = {"simple":123, "complex":(v1, v2, l1)}
expr = raw_input("Enter an expression:")
print eval(expr) # evaluate and print the expression

下面是使用上述代码进行求值的示例表达式和求值的结果:

输入表达式(作为字符串输入) 结果
'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
print sys.path

在我的机器上,当在 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)之前执行。实际上,导入可以有条件地完成,如下例所示:

   :
# lots of other stuff
:
if __name__ == "__main__":
:
from sys import exit
exit(0)

导入也可以被撤销,如下所示:

import sys
:
# lots of other stuff
:
del sys

 

回页首

子集导入

当导入模块时,已赋值的所有值或在模块中创建的函数通常都可以由模块导入程序(importer)引用。您可以通过改变模块中的代码来防止出现此类情况。以下划线 (_) 作为名称的开头或在模块的开始定义一个特殊的变量 __all__,这样可以只列出要导入的变量或函数的名称。例如,下列 __all__ 定义:

__all__ = ["getline","clearcache","checkcache"]

只导入名称 getlineclearcache 和 checkcache

在模块目录级别可以采用类似的策略。在名为 __init__.py 的文件中定义变量 __all__,指示解释器要从模块中导入哪些模块(如果在导入语句中使用了通配符 (*))。例如,如果 __all__ = ['mod1', 'mod3', 'globals'] 行位于名为 modules 目录下叫做__init__.py 的文件中,它将导致语句 from modules import * 从 modules 目录导入模块 mod1mod3 和 globals

 

回页首

运行本机应用程序

通过 os.system 函数,Jython 还可以运行任何在当前主机 PATH 中找到的外部程序,如主机操作系统应用程序。例如,要编译 Java 程序,可以使用

import os
import sys cmd = "javac %(name)s.java 1>%(name)s.out 2>%(name)s.err" % \
{'name': sys.argv[1]})
rc = os.system(cmd)
if rc == 0:
print "Successful"
else:
print "Failed: return code=%i..." % rc
# read and process the .err file...

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
except type, var: statement
:
else: statement -- or -- try:
block
except type, var:
block
:
else:
block

可以用不同的 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
:
try:
:
except:
type, value, traceback = sys.exc_info()

有关异常和跟踪的更详细信息可以在 Python Reference Manual (请参见 参考资料)中获得。

 

回页首

try-finally 语句

与 C++ 和 Java 语言一样,Jython 还支持结构 try-finally,采用该结构可以轻松地执行必需的清除活动,如关闭打开的文件、释放资源等。一旦进入 try 子句,finally 子句中的任何代码都要保证执行一次,即使通过返回语句(请参见 return 语句)或异常退出也是如此。try-finally 语句具有下列形式:

try: statement
finally: statement -- or -- try:
block
finally:
block

注意,try-except-else 语句可以嵌套在 try-finally 语句中,反之亦然。

 

回页首

try 语句的例子

下面是一起使用 try-except 和 try-finally 语句的例子。本教程的第 2 部分将详细讨论 Jython 的文件 I/O。

def readfile (name):
"return the lines in a file or None if the file cannot be read"
try:
file = open(name, 'r') # access the file
try:
return file.readlines()
finally:
file.close() # ensure file is closed
except IOError, ioe: # report the error
print "Exception -", ioe : # prints Exception - File not found - nofile (...)
# then None
print readfile("nofile") # prints a list of the lines in the file
print readfile("realfile")

 

回页首

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 有一些执行计算或控制程序流的语句,包括 expressionassignmentpassifwhileforbreakcontinues 和 del 语句。您将在下一屏中了解这些过程语句。

 

回页首

pass 语句

pass 语句在下列情形下使用:在语法上要求必须有一个 Jython 语句,但此时程序没有要求执行任何操作。pass 在创建空循环语句或提供块的临时实现时很有用。该语句具有下列形式:

pass

 

回页首

表达式语句

在 Jython 中,任何表达式都可以充当语句;而最终的值被简单地丢弃即可。任何此类 expression 语句都常常调用函数或方法(在第 2 部分进一步讨论)。例如,下列代码依次调用三个函数:

performAction(1)
performAction(2)
performAction(3)

 

回页首

运算符和优先级

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
0 <= x < 100 # tests a range # the use of (...) below is not required but it improves readability
(x > 0) and (y < 0) # tests the relation of 2 values 1 + 2 * 3 ** 4 << 2 # complex expression yielding 652
(1 + (2 * (3 ** 4))) << 2 # Equivalent fully parenthesized expression

 

回页首

运算符优先级总结

下表概括了 Jython 运算符的优先级。使用圆括号可以改变运算符的顺序,也可以提高可读性。除非另行说明,否则同一优先级运算是从左到右进行求值的。较高优先级的运算位于列表的顶部。

运算 注释
( expression )  ( expr1, ..., exprN )  [ expr1, ...,exprN ]  { key1:value1, ..., keyN:valueN }  `expression` 嵌套表达式或分组  元组构造函数  列表构造函数  字典构造函数  repr (表示) 表达式
x.name  x[i], x[i:j], x[i:j:k]  x(...) 成员(属性或方法)选择  下标或切片  函数调用
** 作为幂(右结合)
+  -  ~ 正 负 按位取反
*  /  % 乘 除 取模
+  - 加 减
<<, >> 按位移动
& 按位与
^ 按位异或
| 按位或
isis not  innot in  <<=>>===!=<> 同一性测试  包含测试  关系测试
not 逻辑非
and 逻辑与
or 逻辑或
lambda 声明一个 lambda 函数

 

回页首

赋值语句

assignment语句用于将值绑定(或重新绑定)到变量。如果没有定义变量,则绑定创建变量并对其赋值。在 Jython 中,所有数据都是对象,变量实际上存储的是对象的引用而非值。变量是没有类型的,因此赋值可以更改变量引用的值的类型。

多个变量可以具有对同一个对象的引用;这种情况就称为取别名。为此,Jython 支持 is 和 is not 运算符,用于测试两个变量是否引用同一个对象。

变量只能在块中声明一次。这意味着,即使块中的流不执行创建变量的assignment语句,也会由解析器声明变量。直到实际执行第一个赋值操作之前,变量都具有未定义的值。

注意,与assignment语句类似,其他语句也可以绑定变量。classdeffor 和 except 语句是一些例子。

 

回页首

并行赋值

assignment语句支持序列解开(unpacking)。这种功能支持并行赋值。例如,下列语句将 a 设置为 1,将 b 设置为 2 ,并将 c 设置为 3

(a, b, c) = (1, 2, 3)

-- or --

x = (1, 2, 3)
(a, b, c) = x

左侧和右侧必须有相同的变量数。如果提供了一个序列变量(称为函数的参数),而且要访问其中的值,则这种解开方法会很有用。为方便起见,结束圆括号不是必需的,因此上述赋值还可以写成: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 语句

ifelif 和 else 语句提供基本的判断能力。测试表达式求值为 false(None、0 或空)或 true(非 0 或非空)。

采用下列形式有条件地执行语句或块:

if expression: statement

  -- or --

if expression:
block

下面是一个例子:

if x < 0: x = -x  # ensure x is positive

 

回页首

if-else 语句

采用下列形式在两个备选语句和/或块之间进行选择:

if expression: statement
else: statement -- or -- if expression:
block
else:
block

下面是一个例子:

if x >= 0:
result = fac(x)
else:
print x, "is invalid for a factorial"

 

回页首

if-elif-else 语句

采用下列形式选择一组备选语句和/或块:

if   expression: statement
elif expression: statement
:
else: statement -- or -- if expression:
block
elif expression:
block
:
else:
block

elif 子句可以重复。else 子句是可选的。下面是一个例子:

if   x == 0:
doThis()
elif x == 1:
doThat()
elif x == 2:
doTheOtherThing()
else:
print x, "is invalid"

 

回页首

条件表达式

基于 C 的大多数语言(包括 C++ 和 Java 语言)都支持条件表达式。这些表达式返回子表达式的选择,在避免使用重复的目标时非常有用。如果目标包含复杂表达式(如下标),则这种功能很重要。条件表达式具有下列形式:

                    
target = expression ? true_expression : false_expression

Jython 不直接支持条件表达式;而使用下面的形式:

if expression: target = true_expression; else: target = false_expression

-- or --

if expression: target = true_expression
else: target = false_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 函数 ),如下所示:

:
# define the function to handle each unique case
def case1(...): return ...
def case2(...): return ...
:
def caseN(...): return ... # defines cases in a dictionary; access by key
cases = {key1:case1, key2:case2, ..., keyN:caseN}
:
result = cases[key](...) # get the selected case result -- or -- # defines cases in a list or tuple; access by index
cases = (case1, case2, ..., caseN)
:
result = cases[x](...) # get the xth case result

 

回页首

while 语句

while 语句用于执行条件循环。只要表达式求出的值为 true,则执行循环。while 语句具有下列形式:

while expression: statement
else: statement -- or -- while expression:
block
else:
block

else 子句是可选的,只有在 while 子句正常结束(即没有使用 break 语句)时才执行。通常不使用该语句。

例子:

x = 10
while x > 0:
process(x)
x -= 1

下面是一个无限循环:

while 1: print "Hello!"

 

回页首

for 语句

for 语句用于执行迭代循环。它处理从提供的expression中返回的序列,依次获取每个元素。只要元素保留在该序列中,就执行循环。for 语句具有下列形式:

for vars in expression: statement
else: statement -- or -- for vars in expression:
block
else:
block

else 子句是可选的,只有在 for 子句正常结束(即不使用 break 语句)时执行。

例子:

for c in "String":
processCharacter(c) # process the chars in turn -- or -- values = (1,2,5,7,9,-1)
for v in values:
process(v) # process the values supplied -- or -- for i in range(10):
print i # print the values 0 to 9 on separate lines -- or -- for k, v in {"one":1, "two":2, "three":3}.items():
print k, '=', v # print the keys and values of a dictionary

在上述代码中,使用 for i in range(limit) 提供了大多数语言都具有的 for-loop 或 do-loop 迭代。还要注意,keys 没必须要以提供的顺序输出。

 

回页首

break 和 continue 语句

有时需要在中间退出 while 或 for。这通常是循环机制本身检测不到一些异常条件而产生的结果。break 语句提供该行为。该语句具有下列形式:

break

下面是一个例子:

for i in range(100):
d = getData(i)
if not valid(d): break # can't continue
processData(d)

同样,有时可能需要跳过循环体的其余部分,较早地开始下一个迭代。continue 语句提供该行为。该语句具有下列形式:

continue

下面是一个例子:

for i in range(100):
: # *** some preliminary work ***
if not valid(i): continue # can't process this one
: # *** some other stuff ***

一般而言,break 和 continue 语句都作为 if 语句的目标出现的。只有紧密包含的循环才可被控制。

 

回页首

更新序列

在迭代的同时还更新(即插入和删除条目)序列的话,一定要特别小心,因为这可能会导致迭代索引不可预期地进行更改。建议您创建要迭代的序列的副本,如下所示:

for i in x[:]:    # iterate over a copy
if i > 0: # remove all positive values
x.remove(i)

 

回页首

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 ):
block

在给定的作用域(模块、函数或类)内,每个函数名都应是惟一的。函数名事实上是绑定到函数体的变量(类似于任何其他赋值)。实际上,可以定义多个变量来引用同一个函数。函数体可以是单个语句(通常是一个返回语句),也可以是语句块(这种情形更为常见)。

 

回页首

指定函数参数

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)
if p3 is None: p3 = []
:

而非下面简单的形式:

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
print k() # prints 1 # below replaces the built-in abs definition
def abs(x): # calc the absolute value
if x < 0: return -x
return x
print abs(-10) # prints 10 sum = lambda x, y: x + y # define sum function
print sum(1,2) # prints 3 prod = lambda x, y: x * y # define prod function
print prod(1,2) # prints 2 # fully equivalent to the above,
# but the above binding of prod is replaced
def prod(x, y): return x * y # define the prod function
print prod(1,2) # prints 2 # make an alias of prod
xy = prod
print xy(1,2) # prints 2 # a function that takes a function
# similar to the built-in function apply
def applyer (func, args):
return func(*args) print applyer(xy, (1,2)) # prints 2
print applyer(lambda x,y: x ** y, (2,16)) # prints 65536 def factorial(x):
"calculate the factorial of a number"
if x < 0:
raise ValueError, "negative factorial not supported"
if x < 2:
return 1
return long(x) * factorial(x-1) print factorial(3) # prints 6

 

回页首

global 语句

有时,您可能希望在局部上下文中声明变量(即赋值),但在全局作用域中引用变量。为此,请在第一次使用变量前使用 global 语句。下面是一个例子:

x = 10; y = 20; z = 30  # three global variables

def f1(p, q, r):
x = p # local x, y & z variables
y = q
z = r def f2(a, b, c):
global x, y
x = a # global x & y variables
y = b
z = c # local z variable print x, y, z # prints: 10, 20, 30 f1(1, 2, 3)
print x, y, z # prints: 10, 20, 30 f2(-1, -2, -3)
print x, y, z # prints: -1, -2, 30

注意,只要全局变量没有被局部地重新绑定,那么在没有将其声明为全局的情况下,就可读取该变量。因此,只有在对全局变量赋值时才需要 global 语句。

 

回页首

泛型函数

与 Smalltalk 的函数类似,Jython 函数是泛型的,因为对每个参数而言,可以传递任何类型。这就使得函数极端灵活。只要对函数的参数执行的任何运算对参数的实际类型而言都是有效的,那么泛型函数就能工作正常。例如,对于下列函数定义

def sum (x, y):
return x + y def prod (x, y):
return 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
from UserList import *
:
data = None # undefined until setData called
prevdata = [] def setData (values=None):
""" Set global data. """
global data, prevdata # use the global data
if not data is None: # save any prior versions
prevdata.append(data)
data = [] # create default empty data space
if not values is None: # some initial values supplied
if isinstance(values, UserList): # values is a UserList
data = values.data[:] # set to copy of UserList's values
else: # values is some other sequence
# this will fail if values is not some form of sequence
data = list(values) # convert to a list
:
print data # prints None
:
setData("123456")
print data # prints ['1',2','3','4','5','6']
:
setData((1,2,3,4,5,6))
print data # prints [1,2,3,4,5,6]
:
xdata = data[:]; xdata.reverse()
setData(xdata)
print data # prints [6,5,4,3,2,1]
:
print prevdata # prints [['1',2','3','4','5','6'],[1,2,3,4,5,6]]

 

回页首

嵌套函数

与许多其他语言(包括 Java 语言)不同,Jython 允许在其他函数内部定义函数。嵌套(或局部)函数有助于缩减函数的作用域。下面是一个例子:

def x(a, b, c):
y = a * b def square(x):
return x ** 2 # this x is different from function x y *= square(c)
return x

包含函数中的变量对嵌套函数是不可见的。如果嵌套函数必须使用这些值,则将这些值作为参数传递给嵌套函数。例如,下列函数

def calc(a, b, c):
x = a * b * c def sum(data):
# cannot access calc's namespace (x, a, b, c, or sum) here
print locals()
return data['a'] + data['b'] + data['c'] x += sum(locals())
return x print calc(10,20,30)

输出

{'data': {'x': 6000, 'c': 30, 'b': 20, 'sum': \
<function sum at 32308441>, 'a': 10}}
6060

使用嵌套函数还能方便地创建(预先配置)要作为结果返回的函数,如下所示:

def makeSq(n):
def sq(x=n): # n's value is saved as the parameter x value
return x ** 2
return sq

上述函数可以像下面这样使用:

sq2 = makeSq(2)
print "2*2=%i" % sq2() # prints: 2*2=4 sq10 = makeSq(10)
print "10*10=%i" % sq10() # prints: 10*10=100

 

回页首

函数式程序设计

与 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]

使用诸如 mapreduce 和 filter 这样的函数,使得处理序列(即字符串、列表和元组)非常容易。这些函数是高阶(higher-order)函数,因为它们可以将函数作为参数或者作为结果返回。

 

回页首

函数式程序设计的例子

我们给出一些函数式程序设计的例子来结束这一节对 Jython 函数的讨论以及“介绍 Jython”教程的前半部分。

阶乘计算器可以通过 reduce 来实现:

def fac(x):
return reduce(lambda m,n: long(m)*n, range(1,x)) print fac(10) # prints 362880L

可以使用 map 来修改列表:

l = [1, -2, 7, -3, 0, -11]
l = map(abs, l) print l # prints [1, 2, 7, 3, 0, 11]

在序列中可以使用 map 来执行一组函数:

def f1(x): return ...
def f2(x): return ...
def f3(x): return ...
:
def fM(x): return ...
:
def fN(x): return ... # x=(5) is an example of a parameter for each function,
# any expression is allowed, each function will get it
# the list determines the order of the functions
# the result of each function is returned in a list.
results = map(lambda f,x=(5): f(x), [fN,f3,f2,f3,...,fM,...,f1])

可以使用 map 来获得循环:

def body1(count):
# any body here
: # do body 10 times, passing the loop count
map(body1, range(10)) def body2(x,y,z):
# any body here
: # do body with multiple parameters
# calls body2(1, 'a', "xxx")
# then body2(2, 'b', "yyy")
# then body2(3, 'c', "zzz")
map(body2, [1,2,3], "abc", ["xxx", "yyy", "zzz"])

可以使用 filter 进行选择:

# Assume a class Employee exists with attributes
# name, age, sex, title, spouse and children (among others)
# and that instances such as John, Mary and Jose exist.
# See Part 2 of this tutorial for more information on using classes. John = Employee('John', 35, 'm', title='Sr. Engineer')
Mary = Employee('Mary', 22, 'f', title='Staff Programmer')
Jose = Employee('Jose', 50, 'm', title='Dept. Manager', children=[...])
employees = [John, Jose, Mary]

下面是如何使用上述 filter 选择一些员工的例子:

# returns: [Jose]
hasChildren = filter(lambda e: e.children, employees) # returns: []
over65 = filter(lambda e: e.age>65, employees) # returns: [Mary]
isProgrammer = filter(lambda e: \
e.title and e.title.lower().find('prog') >= 0, employees)

结束语和参考资料

结束语

在两部分“介绍 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) --> 4
complex(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) --> 3
execfile(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,感谢他们对本教程进行了杰出的技术评审。

【转】介绍Jython,第一部分轻轻松松写JAVA程序的相关教程结束。

《【转】介绍Jython,第一部分:轻轻松松写JAVA程序.doc》

下载本文的Word格式文档,以方便收藏与打印。