本文轉自:http://www.ibm.com/developerworks/cn/education/java/j-jython1/index.htmlhtml
關於本教程java
這個兩部分的教程將介紹 Jython 腳本語言,並提供開始開發基於 Jython 的應用程序所需的足夠知識。Jython 是 Python 的一種實現,已無縫集成到 Java 平臺中。Python 主要在 UNIX 環境中使用,是一種強大的面向對象的腳本語言。linux
Jython 很是有用,由於它運行於 JVM 上,且具備成熟腳本語言所具備的高生產率。與 Python 程序不一樣,Jython 程序能夠運行在任何支持 JVM 的環境中。如今這意味着可在大多數計算系統上使用,包括 Microsoft Windows、Mac OS、大多數 UNIX 變體(包括全部 Linux 系統)和全部的 IBM 系統。git
本教程採用漸進步驟介紹 Jython。本文(即本教程的前半部分)將介紹使用 Jython 的概念和編程基礎知識,包括訪問選項和文件編譯、語法和數據類型、程序結構、過程語句和函數。 本教程的第 2 部分將開始對採用 Jython 的面向對象編程進行概念性介紹。以後,咱們將進行更具體的討論,包括類語句、屬性和方法、抽象類和運算符重載。這個高級討論還包括調試、字符串處理、文件 I/O 和 Jython 中的 Java 支持。本教程結束時,將一步步演示如何用 Jython 構建一個能夠工做的 GUI 應用程序。程序員
在本教程的開始部分,示例代碼很是簡單,但在第 2 部分結束時,您將會徹底掌握函數、類和程序。本教程還包括一組附錄,詳細介紹了 Jython 的內部工做原理。web
回頁首正則表達式
本教程面向各個層次的軟件開發人員,從偶爾的涉足者到專業人員。但它特別適合那些但願利用腳本語言所具備的高生產率優點的 Java 開發人員。那些但願輕鬆進入 Java 開發世界的 Visual Basic 和 C++/C# 程序員,也能夠學習本教程。sql
總之,咱們將討論 Jython 腳本編程的如下方面:
第 1 部分
第 2 部分
要從本討論中獲益,應該至少熟悉一門過程編程語言和計算機編程的基本概念,包括命令行處理。要徹底利用 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 2.1。您會發現下載頁面上的下載說明很是容易。
正如前面所提到的,本教程基於當前穩定的 Jython 級別,即版本 2.1。能夠從 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 是用 Java 語言編寫的 Python 實現,並與 Java 平臺集成在一塊兒。Python 是一種腳本語言,常常在基於 UNIX 的系統(包括 Linux)中使用。Python 由 Guido van Rossum 發明並在 1991 年被引入到開發人員社區中。Jython 當前支持級別 2.1 的 Python 語法。
與 Java 編程語言不一樣,Jython 是一種腳本語言。腳本語言一般具備以下特色:
通常而言,能夠說腳本語言對程序員效率的貢獻是創建在機器效率和性能之上的。與編程語言(如 Java 語言)相比,Jython 易於學習且編碼效率很高。
Jython 還能夠被描述爲輕巧靈活的語言。這種語言一般被認爲是能執行各類各樣的任務,在解決許多不一樣類型的問題時頗有用,易於使用且功能強大、意圖明確。它們也是理想的快速原型開發語言。
與基於 C 的兄弟 Python 同樣,Jython 大多數是在小場合中用來開發小型程序和腳本;它有許多特性,容許在幾分鐘內建立簡單而實用的程序。但這並不意味着 Jython 不能用於大規模的程序設計。實際上,Jython 支持複雜的打包方案,相似於 Java 語言。依賴其面向對象的特色,Jython 具備高度的可擴展性,併爲有效的軟件工程提供了最新結構。
Jython 與 Java 語言類似,但不像其餘一些腳本編程語言,如 Perl 和 Rexx,它從一開始就設計成一種面向對象的語言。所以,它提供易於理解的強大的面向對象編程 (OOP) 特性。
Jython 最大的優勢之一是運行於任何 JVM 上,所以採用 Jython 編碼的應用程序幾乎能夠在任何計算系統上運行。
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 交互會話開始。在 ">>>" 或 "..." 提示符後輸入下列命令:
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 源文件以擴展名 .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 expression {, expression}... {,} -- or -- print |
上述 print
語句還能夠包含由逗號分隔的表達式的列表。表達式輸出時,會自動在兩個表達式之間添加一個空格。所以, print "Hello", "Goodbye"
輸出 Hello Goodbye
。
若是 print
語句以逗號結束,則不輸出換行。print
行自己輸出一個換行。
在 Jython 中,典型的示例程序――Hello World――是一個單行文件(名稱爲 hello.py),以下所示:
print "Hello World!" |
要運行該程序,應輸入命令:C:\>c:\jython-2.1\jython hello.py
注意必需要有 .py 擴展名,不然將出現 "file not found" 錯誤。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 源文件能夠被編譯成 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 支持三種數值類型,以下所示:
int
)。 BigInteger
)。 double
類型相同的值。 x.real
是實部,而 x.imag
是虛部。任一部分均可以是 0.0。方法 x.conjugate
生成一個新複數,該值有 +x.real
和 -x.imag
。 數值類型還支持下列運算和函數:
運算/函數 | 用法 |
-x |
負 x(即 0 - x) |
+x |
正 ―― 沒有改變(即 0 + x) |
x + y |
將 y 添加到 x |
x - y |
從 x 中減去 y |
x * y |
x 乘以 y |
x / y |
x 除以 y |
x % y divmod(x, y) |
取 x 除以 y 所得的模數 Return (x / y, x % y) |
x ** y pow(x, y) |
將 y 做爲 x 的冪 將 y 做爲 x 的冪 |
abs(x) |
If x < 0, then -x; else x |
int(x) |
將 x 轉換爲整數 |
long(x) |
將 x 轉換爲長整數 |
float(x) |
將 x 轉換爲浮點數 |
complex(r, i) complex(x) |
將 r 和 i 轉換爲複數 將 x 轉換爲複數 |
注意:對於數值類型,操做數被提高到下個較高的類型。對於整數操做數, /、% 和 ** 都產生整數結果。對於 int
、long
、float
和complex
轉換函數,x 能夠是字符串,也能夠是任何數字。
整型還支持下列運算:
運算 | 用法 | 註釋 |
x << y |
將 x 左移 y 位 | 相似於 x * pow(2, y) |
x >> y |
將 x 右移 y 位 | 相似於 x / pow(2, y) |
x & y |
x 和 y 按位與 | 對 x 中與 y 中的 0 位對應的位清零。 |
x | y |
x 和 y 按位或 | 將 x 中與 y 中的 1 位對應的位置 1。 |
x ^ y |
x 和 y 按位異或 | 將 x 中與 y 中的 1 位對應的位取反 |
~x |
將 x 位取反 | 將全部位都取反 |
浮點類型另外支持下列函數(在 math
模塊中):
函數 | 註釋 |
ceil(v) floor(v) |
計算 v 的最大值和最小值。 |
sin(v) cos(v) tan(v) |
計算 v 的正弦、餘弦和正切。 |
acos(v) asin(v) atan(v) atan2(v, w) |
計算 v(或 v / w)的反正弦、反餘弦和反正切。 |
sinh(v) cosh(v) tanh(v) |
計算 v 的雙曲正弦、雙曲餘弦和雙曲正切。 |
exp(v) pow(v, w) sqrt(v) log(v) log10(v) |
計算 v 的冪和對數。 |
fabs(v) |
計算 v 的絕對值。 |
fmod(v, w) |
計算 v 和 w 的模。可能與 v % w 不一樣。 |
modf(v) |
返回(做爲 tuple (i, f))v 的整數部分和小數部分(二者都爲浮點數)。 |
frexp(v) |
返回(做爲 tuple (m, e))v 的浮點尾數和整型指數。結果類 似於 v == m * 2 ** e 。 |
ldexp(v, w) |
計算 v * 2 ** w (w 必須爲整數)。 |
hypot(v, w) |
計算 v 和 w 斜邊(即sqrt(v * v + w * w) )。 |
咱們運行一個例子來演示上一屏中的 math
模塊中的函數。有關更多信息,請參見 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:轉義字符。
下面是一些字符串例子:
注意,倒數第二個例子展現了原始字符串(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 |
下面是對項進行格式化的指南:
例如
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 使用整數遞增的不可變序列。這些序列稱爲範圍。採用兩個內置函數很容易建立範圍:
範圍從 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 包含兩種形式的註釋:
__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 名稱類似的標識符。標識符用於給變量、函數和類命名,還能夠用做關鍵字。標識符能夠是任何長度,必須以字母(大寫或小寫)或下劃線字符開頭,能夠是字母、十進制數字和下劃線的任意組合。如 abc、abc123、_x、x_、myName和 ONE是一些有效的標識符,123abc、$xyz 和 abc pqr是一些無效的標識符。
注意,如下劃線開頭的名稱一般保留用做內部名稱或專有名稱。
Jython 還有幾個保留字(或關鍵字),它們不能用做變量、函數或類的名稱。這些關鍵字分爲下列幾類:
注意,關鍵字能夠用於特殊環境中,如方法的名稱。例如,您可使用關鍵字調用與 Jython 關鍵字具備相同名稱的 Java 方法。不正確的關鍵字一般會致使 SyntaxError
。
塊(或套件)是語句組,用在但願使用單個語句的地方。全部能夠將語句塊做爲目標的語句都經過冒號字符引入塊。下列語句(或語句子句)將塊做爲目標:if、elif、else、for、while、try、except、def 和 class。無論是由逗號分隔的單條語句,仍是小語句組,均可以跟在同一行冒號的後面,塊能夠跟在後續行縮進的語句後。
我強烈建議使用空格進行縮進。在具備不一樣製表符中止位(tab stop)的系統(或編輯器)之間移動時,使用製表符可能出現問題。請不要在同一源文件中混用製表符和空格。按照約定,每一層使用四個空格。
注意: 模塊最外面的塊中的全部行都必須從第一列開始,不然會產生 SyntaxError
。
與 C 和 Java 語言不一樣,在 Jython 中,不是使用花括號,而是使用縮進來劃分塊。例如:
# the following prints 0 through 10 on one line 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 函數 )。變量在每一個做用域中只能聲明一次;後續使用會從新綁定該變量。與在 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
函數執行來自文件的代碼塊,它其實是運行一個子程序。
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 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
值。
與 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"] |
只導入名稱 getline
、clearcache
和 checkcache
。
在模塊目錄級別能夠採用相似的策略。在名爲 __init__.py
的文件中定義變量 __all__
,指示解釋器要從模塊中導入哪些模塊(若是在導入語句中使用了通配符 (*))。例如,若是 __all__ = ['mod1', 'mod3', 'globals']
行位於名爲 modules 目錄下叫作__init__.py
的文件中,它將致使語句 from modules import *
從 modules 目錄導入模塊 mod1
、mod3
和 globals
。
經過 os.system
函數,Jython 還能夠運行任何在當前主機 PATH
中找到的外部程序,如主機操做系統應用程序。例如,要編譯 Java 程序,可使用
import os 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 的主要異常層次結構的子集。
該層次結構是 Python Library Reference(請參見 參考資料)的子集。這些異常能夠被進一步分類。
與 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 (請參見 參考資料)中得到。
與 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-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 exception -- or -- raise exception_class {, message} -- or -- raise |
下面是 raise
語句的一些例子。
例子 | 註釋 |
raise |
從新引起當前的異常;在異常塊中用於從新生成異常 |
raise IOError |
建立和引起 IOError ,沒有消息 |
raise anIOError |
從新引起現有的 IOError 對象 |
raise IOError, "End of File" |
建立和引起 IOError ,有解釋性消息 |
from java import io raise io.IOException, "End of File" |
建立和引起 Java 異常,有解釋性消息 |
Jython 過程語句
Jython 有一些執行計算或控制程序流的語句,包括 expression
、assignment
、pass
、if
、while
、for
、break
、continues
和 del
語句。您將在下一屏中瞭解這些過程語句。
pass
語句在下列情形下使用:在語法上要求必須有一個 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
語句相似,其餘語句也能夠綁定變量。class
、def
、for
和 except
語句是一些例子。
assignment
語句支持序列解開(unpacking)。這種功能支持並行賦值。例如,下列語句將 a 設置爲 1,將 b 設置爲 2 ,並將 c 設置爲 3:
(a, b, c) = (1, 2, 3) -- or -- x = (1, 2, 3) (a, b, c) = 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
, elif
和 else
語句提供基本的判斷能力。測試表達式求值爲 false(None、0 或空)或 true(非 0 或非空)。
採用下列形式有條件地執行語句或塊:
if expression: statement -- or -- if expression: block |
下面是一個例子:
if x < 0: x = -x # ensure x is positive |
採用下列形式在兩個備選語句和/或塊之間進行選擇:
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 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
語句用於執行條件循環。只要表達式求出的值爲 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
語句用於執行迭代循環。它處理從提供的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
沒必需要以提供的順序輸出。
有時須要在中間退出 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
語句,該語句分別從集合或類中刪除元素或屬性。對序列而言,刪除是按索引進行的;而對映射是按鍵值;對類是按屬性名稱。咱們將在本教程的第 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 語言),它將函數做爲一類對象,就像操縱其餘對象同樣操縱該對象(最爲特別的是,對象能夠存儲在集合中,並做爲參數傳遞給其餘函數)。
在 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
語句能夠返回也能夠不返回一個明確的值;若是沒有指定任何值,則使用 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
語句。下面是一個例子:
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] |
使用諸如 map
、reduce
和 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 部分附帶的附錄(附錄 ),或購買一些 參考資料 一節中包含的參考資料。
附錄
有幾種特殊字符須要加反斜槓:
反斜槓表示 | 字符 |
\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') |
字符串支持幾種有用的方法:
方法 | 用法 | 例子 |
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 | 合法的空格字符 |
列表支持幾種有用的方法。
函數 | 註釋 | 例子 |
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] |
映射支持幾種有用的方法。
方法 | 註釋 | |
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() | 得到和刪除某些項,在對映射的迭代期間使用。例如:
|
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" |
|
|
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}}) | 求出提供的名稱空間中表達式的值 |
|
|
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(參考資料)。
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 系統時。在決定使用它們進行編碼以前,請嘗試採用交互方式使用它們。
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(參考資料)。
格式運算符(請參見格式化字符串和值)支持下列格式字符:
字符 | 結果格式 | 註釋 |
%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,感謝他們對本教程進行了傑出的技術評審。