【轉】介紹Jython,第一部分:輕輕松松寫JAVA程序


本文轉自: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 中是一種抽象概念,因為您不能直接創建序列,只創建從序列派生而來的子類型。任何序列子類型都具有序列的全部函數。序列子類型有幾個,如下所示:

  • 字符串 是字符的不變序列(請參見 字符串)。
  • 元組 是任何數據類型的不變序列(請參見 元組)。
  • 范圍 是整數的不變序列(請參見 范圍)。
  • 列表 是任何數據類型的可變序列(請參見 列表)。
 

字符串

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
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(...) 成員(屬性或方法)選擇  下標或切片  函數調用
** 作為冪(右結合)
+  -  ~ 正 負 按位取反
*  /  % 乘 除 取模
+  - 加 減
<<, >> 按位移動
& 按位與
^ 按位異或
| 按位或
is, is not  in, not 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 語句

if, elif  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,感謝他們對本教程進行了傑出的技術評審。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM