Python 3.0 的新特性

作者:

Guido van Rossum

本文解釋了 Python 3.0 相較於 2.6 的新特性。Python 3.0,也被稱為“Python 3000”或“Py3K”,是第一個有意向後不相容的 Python 版本。Python 3.0 於 2008 年 12 月 3 日釋出。與典型的版本相比,它有更多的更改,並且對所有 Python 使用者來說都更重要。然而,在消化了這些更改之後,你會發現 Python 實際上並沒有改變太多——總的來說,我們主要是在修復眾所周知的煩惱和缺陷,並刪除大量舊的無用程式碼。

本文不試圖提供所有新功能的完整規範,而是試圖給出一個方便的概述。有關完整詳細資訊,您應該參考 Python 3.0 的文件和/或文字中引用的許多 PEP。如果您想了解特定功能的完整實現和設計原理,PEP 通常比常規文件有更多的細節;但請注意,一旦某個功能完全實現,PEP 通常不會保持更新。

由於時間限制,本文件並不像它應該的那樣完整。與新版本一樣,原始碼發行版中的 Misc/NEWS 檔案包含有關所做的每一件小事的豐富詳細資訊。

常見的絆腳石

本節列出瞭如果您習慣了 Python 2.5 最容易讓您絆倒的一些更改。

檢視和迭代器代替列表

一些眾所周知的 API 不再返回列表

  • dict 方法 dict.keys()dict.items()dict.values() 返回“檢視”而不是列表。例如,這不再有效:k = d.keys(); k.sort()。請使用 k = sorted(d) 代替(這在 Python 2.5 中也有效,並且同樣高效)。

  • 此外,不再支援 dict.iterkeys()dict.iteritems()dict.itervalues() 方法。

  • map()filter() 返回迭代器。如果您真的需要列表,並且輸入序列的長度都相等,則一個快速的解決方法是將 map() 包裝在 list() 中,例如 list(map(...)),但更好的解決方法通常是使用列表推導式(特別是當原始程式碼使用 lambda 時),或者重寫程式碼使其根本不需要列表。特別棘手的是 map() 為了函式副作用而呼叫;正確的轉換是使用常規的 for 迴圈(因為建立列表只會浪費)。

    如果輸入序列的長度不相等,則 map() 將在最短序列終止時停止。為了與 Python 2.x 中的 map() 完全相容,還要將序列包裝在 itertools.zip_longest() 中,例如 map(func, *sequences) 變為 list(map(func, itertools.zip_longest(*sequences)))

  • range() 現在的行為類似於 xrange() 過去的行為,只是它可以處理任意大小的值。後者不再存在。

  • zip() 現在返回一個迭代器。

排序比較

Python 3.0 簡化了排序比較的規則

  • 當運算元沒有有意義的自然排序時,排序比較運算子(<<=>=>)會引發 TypeError 異常。因此,像 1 < ''0 > Nonelen <= len 這樣的表示式不再有效,例如,None < None 會引發 TypeError 而不是返回 False。一個推論是,對異構列表進行排序不再有意義——所有元素都必須彼此可比較。請注意,這不適用於 ==!= 運算子:不同且不可比較型別的物件始終彼此比較不相等。

  • sorted()list.sort() 不再接受提供比較函式的 *cmp* 引數。請改用 *key* 引數。注意,*key* 和 *reverse* 引數現在是“僅關鍵字”的引數。

  • cmp() 函式應被視為已刪除,並且不再支援 __cmp__() 特殊方法。請將 __lt__() 用於排序,將 __eq__()__hash__() 結合使用,並根據需要使用其他豐富的比較。(如果您真的需要 cmp() 功能,則可以使用表示式 (a > b) - (a < b) 作為 cmp(a, b) 的等效項。)

整數

  • PEP 237:本質上,long 被重新命名為 int。也就是說,只有一個內建的整數型別,名為 int;但它的行為方式大多與舊的 long 型別相同。

  • PEP 238:像 1/2 這樣的表示式返回一個浮點數。使用 1//2 來獲得截斷行為。(後一種語法已經存在多年,至少從 Python 2.2 開始就有了。)

  • sys.maxint 常量被移除,因為整數的值不再有限制。然而,sys.maxsize 可以用作大於任何實際列表或字串索引的整數。它符合實現的“自然”整數大小,並且通常與同一平臺上先前版本中的 sys.maxint 相同(假設使用相同的構建選項)。

  • 長整數的 repr() 不再包含尾部的 L,因此無條件剝離該字元的程式碼將改為截斷最後一位數字。(請改用 str()。)

  • 八進位制字面量不再採用 0720 的形式;請改用 0o720

文字與資料,而非 Unicode 與 8 位

你所認為的關於二進位制資料和 Unicode 的一切都已改變。

  • Python 3.0 使用 _文字_ 和(二進位制)_資料_ 的概念,而不是 Unicode 字串和 8 位字串。所有文字都是 Unicode;然而,_編碼_ 的 Unicode 表示為二進位制資料。用於儲存文字的型別是 str,用於儲存資料的型別是 bytes。與 2.x 情況的最大區別在於,任何在 Python 3.0 中混合文字和資料的嘗試都會引發 TypeError,而在 Python 2.x 中混合 Unicode 和 8 位字串,如果 8 位字串恰好只包含 7 位 (ASCII) 位元組,則會起作用,但如果它包含非 ASCII 值,則會得到 UnicodeDecodeError。多年來,這種特定於值的行為導致了許多不愉快的局面。

  • 由於這種理念的改變,幾乎所有使用 Unicode、編碼或二進位制資料的程式碼都可能需要更改。這種改變是積極的,因為在 2.x 版本中,存在許多與混合編碼和未編碼文字有關的錯誤。為了在 Python 2.x 中做好準備,請開始對所有未編碼文字使用 unicode,並僅對二進位制或編碼資料使用 str。然後 2to3 工具將為你完成大部分工作。

  • 你不能再使用 u"..." 字面量表示 Unicode 文字。但是,你必須使用 b"..." 字面量表示二進位制資料。

  • 由於 strbytes 型別不能混合使用,你必須始終在它們之間進行顯式轉換。使用 str.encode()str 轉到 bytes,使用 bytes.decode()bytes 轉到 str。你還可以分別使用 bytes(s, encoding=...)str(b, encoding=...)

  • str 一樣,bytes 型別是不可變的。有一個單獨的 _可變_ 型別用於儲存緩衝的二進位制資料,bytearray。幾乎所有接受 bytes 的 API 也接受 bytearray。可變 API 基於 collections.MutableSequence

  • 原始字串字面量中的所有反斜槓都按字面意思解釋。這意味著原始字串中的 '\U''\u' 轉義不會被特殊處理。例如,r'\u20ac' 在 Python 3.0 中是一個包含 6 個字元的字串,而在 2.6 中,ur'\u20ac' 是單個“歐元”字元。(當然,此更改僅影響原始字串字面量;歐元字元在 Python 3.0 中是 '\u20ac'。)

  • 內建的 basestring 抽象型別已被移除。請改用 strstrbytes 型別沒有足夠多的共同功能來保證使用共享的基類。2to3 工具(見下文)將每個 basestring 的出現替換為 str

  • 作為文字檔案開啟的檔案(仍然是 open() 的預設模式)始終使用編碼在字串(在記憶體中)和位元組(在磁碟上)之間進行對映。二進位制檔案(在模式引數中使用 b 開啟)始終在記憶體中使用位元組。這意味著,如果使用不正確的模式或編碼開啟檔案,I/O 很可能會大聲失敗,而不是默默地產生不正確的資料。這也意味著,即使是 Unix 使用者也必須在開啟檔案時指定正確的模式(文字或二進位制)。存在一個平臺相關的預設編碼,在 Unix 平臺上可以使用 LANG 環境變數進行設定(有時也可以使用其他一些平臺特定的區域設定相關的環境變數)。在許多情況下,但並非所有情況下,系統預設值都是 UTF-8;你不應依賴此預設值。任何讀取或寫入純 ASCII 文字之外的內容的應用程式都應該有一種覆蓋編碼的方法。不再需要在 codecs 模組中使用編碼感知流。

  • sys.stdinsys.stdoutsys.stderr 的初始值現在都是僅限 Unicode 的文字檔案(即,它們是 io.TextIOBase 的例項)。要使用這些流讀取和寫入位元組資料,你需要使用它們的 io.TextIOBase.buffer 屬性。

  • 檔名以(Unicode)字串的形式傳遞給 API 並從 API 返回。這可能會帶來平臺特定的問題,因為在某些平臺上,檔名是任意的位元組字串。(另一方面,在 Windows 上,檔名以 Unicode 的形式原生儲存。)作為一種變通方法,大多數接受檔名的 API(例如 open()os 模組中的許多函式)也接受 bytes 物件以及字串,並且一些 API 有方法請求返回 bytes 值。因此,如果引數是 bytes 例項,則 os.listdir() 返回一個 bytes 例項列表,而 os.getcwdb() 返回當前工作目錄作為 bytes 例項。請注意,當 os.listdir() 返回字串列表時,無法正確解碼的檔名會被省略,而不是引發 UnicodeError

  • 當系統提供的位元組無法使用預設編碼解釋時,某些系統 API(如 os.environsys.argv)也可能會出現問題。設定 LANG 變數並重新執行程式可能是最好的方法。

  • PEP 3138: 字串的 repr() 不再轉義非 ASCII 字元。但是,它仍然會轉義控制字元和 Unicode 標準中具有不可列印狀態的程式碼點。

  • PEP 3120: 預設的原始碼編碼現在是 UTF-8。

  • PEP 3131: 現在識別符號中允許使用非 ASCII 字母。(但是,標準庫仍然僅限 ASCII,註釋中的貢獻者姓名除外。)

  • StringIOcStringIO 模組已刪除。請改為匯入 io 模組,並分別使用 io.StringIOio.BytesIO 來處理文字和資料。

  • 另請參閱為 Python 3.0 更新的 Unicode HOWTO

語法更改概述

本節簡要概述 Python 3.0 中的每個語法更改。

新語法

  • PEP 3107: 函式引數和返回值註解。這提供了一種標準化方法來註解函式的引數和返回值。這些註解沒有附加的語義,只是可以使用 __annotations__ 屬性在執行時進行內省。目的是鼓勵透過元類、裝飾器或框架進行實驗。

  • PEP 3102: 僅限關鍵字的引數。引數列表中出現在 *args 之後的命名引數必須在呼叫時使用關鍵字語法指定。你也可以在引數列表中使用裸 * 來表示你不接受可變長度的引數列表,但你有僅限關鍵字的引數。

  • 在類定義中,基本類列表之後允許使用關鍵字引數。這被用於指定元類的新約定(請參閱下一節),但只要元類支援,它也可以用於其他目的。

  • PEP 3104: nonlocal 語句。使用 nonlocal x,你現在可以直接賦值給外部(但非全域性)作用域中的變數。nonlocal 是一個新的保留字。

  • PEP 3132: 擴充套件的可迭代解包。你現在可以編寫諸如 a, b, *rest = some_sequence 之類的程式碼。甚至 *rest, a = stuffrest 物件始終是一個(可能為空)列表;右側可以是任何可迭代物件。示例

    (a, *rest, b) = range(5)
    

    這將 a 設定為 0b 設定為 4rest 設定為 [1, 2, 3]

  • 字典推導式:{k: v for k, v in stuff}dict(stuff) 的含義相同,但更靈活。(這是 PEP 274 證明是正確的。 :-))

  • 集合字面量,例如 {1, 2}。請注意,{} 是一個空字典;對於空集合,請使用 set()。也支援集合推導式;例如,{x for x in stuff}set(stuff) 的含義相同,但更靈活。

  • 新的八進位制字面量,例如 0o720(在 2.6 中已經存在)。舊的八進位制字面量 (0720) 已刪除。

  • 新的二進位制字面量,例如 0b1010(在 2.6 中已經存在),並且有一個新的對應的內建函式 bin()

  • 位元組字面量以引導 bB 引入,並且有一個新的對應的內建函式 bytes()

更改的語法

  • PEP 3109PEP 3134: 新的 raise 語句語法:raise [expr [from expr]]。請參閱下文。

  • aswith 現在是保留字。(實際上是從 2.6 開始。)

  • TrueFalseNone 是保留字。(2.6 已經部分強制執行了對 None 的限制。)

  • except exc, var 更改為 except exc as var。請參閱 PEP 3110

  • PEP 3115: 新的元類語法。而不是

    class C:
        __metaclass__ = M
        ...
    

    你現在必須使用

    class C(metaclass=M):
        ...
    

    不再支援模組全域性 __metaclass__ 變數。(它是一個柺杖,用於使在不從 object 派生每個類的情況下,更容易預設使用新式類。)

  • 列表推導式不再支援 [... for var in item1, item2, ...] 這種語法形式。請改用 [... for var in (item1, item2, ...)]。 另外請注意,列表推導式具有不同的語義:它們更接近於 list() 建構函式內部生成器表示式的語法糖,特別是迴圈控制變數不再洩露到周圍的作用域中。

  • 省略號 (...) 可以用作任何位置的原子表示式。(以前只允許在切片中使用。)此外,它現在必須拼寫為 ...。(以前也可以拼寫為 . . .,這只是語法上的一個偶然情況。)

已移除的語法

  • PEP 3113:元組引數解包已移除。您不能再編寫 def foo(a, (b, c)): ...。請改用 def foo(a, b_c): b, c = b_c

  • 移除了反引號(請改用 repr())。

  • 移除了 <> (請改用 !=)。

  • 移除了關鍵字:exec() 不再是關鍵字;它仍然是一個函式。(幸運的是,在 2.x 中也接受函式語法。)另請注意,exec() 不再接受流引數;您可以使用 exec(f.read()) 來代替 exec(f)

  • 整數文字不再支援尾隨的 lL

  • 字串文字不再支援前導的 uU

  • from 模組 import * 語法只允許在模組級別使用,不再允許在函式內部使用。

  • 相對匯入唯一可接受的語法是 from .[模組] import 名稱。所有不以 . 開頭的 import 形式都被解釋為絕對匯入。(PEP 328

  • 經典類已移除。

Python 2.6 中已存在的更改

由於許多使用者可能直接從 Python 2.5 跳轉到 Python 3.0,因此本節提醒讀者注意最初為 Python 3.0 設計但已向後移植到 Python 2.6 的新功能。有關更詳細的描述,請查閱 Python 2.6 中的新增功能 中的相應章節。

庫的更改

由於時間限制,本文件並未詳盡涵蓋標準庫的非常廣泛的更改。PEP 3108 是庫的主要更改的參考。以下是簡要回顧

  • 許多舊模組已被刪除。 一些模組,例如 gopherlib (不再使用)和 md5 (已由 hashlib 替換),已被 PEP 4 棄用。 其他模組由於取消了對各種平臺(例如 Irix,BeOS 和 Mac OS 9)的支援而被刪除(請參閱 PEP 11)。 一些模組也由於缺乏使用或存在更好的替代方案而在 Python 3.0 中被選中刪除。 有關詳盡列表,請參閱 PEP 3108

  • bsddb3 包已被刪除,因為它在核心標準庫中的存在已被證明是核心開發人員的特殊負擔,原因是測試不穩定以及 Berkeley DB 的釋出計劃。 但是,該軟體包在 https://www.jcea.es/programacion/pybsddb.htm 上得到了活躍且良好的維護。

  • 一些模組由於其舊名稱違反了 PEP 8,或者出於各種其他原因而被重新命名。 這是列表

    舊名稱

    新名稱

    _winreg

    winreg

    ConfigParser

    configparser

    copy_reg

    copyreg

    Queue

    queue

    SocketServer

    socketserver

    markupbase

    _markupbase

    repr

    reprlib

    test.test_support

    test.support

  • Python 2.x 中的一種常見模式是使用純 Python 實現模組的一個版本,並使用 C 擴充套件來實現可選的加速版本; 例如,picklecPickle。 這將匯入加速版本並回退到這些模組的每個使用者的純 Python 版本的負擔。 在 Python 3.0 中,加速版本被認為是純 Python 版本的實現細節。 使用者應始終匯入標準版本,該版本嘗試匯入加速版本並回退到純 Python 版本。pickle / cPickle 對已受到這種處理。profile 模組在 3.1 的列表中。 StringIO 模組已轉換為 io 模組中的一個類。

  • 一些相關的模組已分組到包中,並且通常簡化了子模組名稱。 產生的新包是

    • dbm (anydbm, dbhash, dbm, dumbdbm, gdbm, whichdb)。

    • html (HTMLParser, htmlentitydefs)。

    • http (httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib)。

    • tkinter (所有與 Tkinter 相關的模組,除了 turtle)。 turtle 的目標受眾實際上並不關心 tkinter。 另請注意,自 Python 2.6 起,turtle 的功能已大大增強。

    • urllib (urllib, urllib2, urlparse, robotparse)。

    • xmlrpc (xmlrpclib, DocXMLRPCServer, SimpleXMLRPCServer)。

對標準庫模組的其他一些更改,未在 PEP 3108 中涵蓋

  • 已刪除 sets。 請使用內建的 set() 類。

  • 清理 sys 模組:刪除了 sys.exitfunc(), sys.exc_clear(), sys.exc_type, sys.exc_value, sys.exc_traceback。 (請注意,sys.last_type 等仍然存在。)

  • 清理 array.array 型別:read()write() 方法已移除;請改用 fromfile()tofile()。此外,array 的 'c' 型別程式碼也已移除 – 請使用 'b' 表示位元組,或使用 'u' 表示 Unicode 字元。

  • 清理 operator 模組:移除了 sequenceIncludes()isCallable()

  • 清理 thread 模組:acquire_lock()release_lock() 已移除;請改用 acquire()release()

  • 清理 random 模組:移除了 jumpahead() API。

  • new 模組已移除。

  • 函式 os.tmpnam()os.tempnam()os.tmpfile() 已移除,請改用 tempfile 模組。

  • tokenize 模組已更改為使用位元組工作。現在的主要入口點是 tokenize.tokenize(),而不是 generate_tokens。

  • string.letters 及其朋友(string.lowercasestring.uppercase)已移除。請改用 string.ascii_letters 等。(移除的原因是 string.letters 及其朋友具有特定於語言環境的行為,對於這種具有吸引力的全域性“常量”來說,這不是一個好主意。)

  • 將模組 __builtin__ 重新命名為 builtins(刪除了下劃線,添加了 ‘s’)。在大多數全域性名稱空間中找到的 __builtins__ 變數保持不變。要修改內建物件,您應該使用 builtins,而不是 __builtins__

PEP 3101:一種新的字串格式化方法

  • 一個新的內建字串格式化作業系統取代了 % 字串格式化運算子。(但是,仍然支援 % 運算子;它將在 Python 3.1 中被棄用,並在以後的某個時間從語言中刪除。)請閱讀 PEP 3101 以獲取完整資訊。

異常的更改

引發和捕獲異常的 API 已被清理,並添加了新的強大功能

  • PEP 352:所有異常都必須(直接或間接)派生自 BaseException。這是異常層次結構的根。這並非新的建議,但繼承自 BaseException要求是新的。(Python 2.6 仍然允許引發經典類,並且對您可以捕獲的內容沒有任何限制。)因此,字串異常最終真正徹底地消亡了。

  • 幾乎所有異常實際上都應該派生自 ExceptionBaseException 應該僅用作應該僅在頂層處理的異常的基類,例如 SystemExitKeyboardInterrupt。處理除後一類之外的所有異常的推薦用法是使用 except Exception

  • StandardError 已移除。

  • 異常不再表現為序列。請改用 args 屬性。

  • PEP 3109:引發異常。現在您必須使用 raise Exception(args),而不是 raise Exception, args。此外,您不能再顯式指定回溯;相反,如果您必須這樣做,您可以直接分配給 __traceback__ 屬性(見下文)。

  • PEP 3110:捕獲異常。現在您必須使用 except SomeException as variable,而不是 except SomeException, variable。此外,當 except 塊離開時,variable 會被顯式刪除。

  • PEP 3134:異常連結。有兩種情況:隱式連結和顯式連結。當在 exceptfinally 處理程式塊中引發異常時,會發生隱式連結。這通常是由於處理程式塊中的錯誤導致的;我們稱之為次級異常。在這種情況下,原始異常(正在處理的異常)將作為次級異常的 __context__ 屬性儲存。使用以下語法呼叫顯式連結

    raise SecondaryException() from primary_exception
    

    (其中 *primary_exception* 是產生異常物件的任何表示式,可能是之前捕獲的異常)。在這種情況下,主異常儲存在次級異常的 __cause__ 屬性上。當發生未處理的異常時列印的回溯會遍歷 __cause____context__ 屬性的鏈,併為鏈的每個元件列印單獨的回溯,主異常位於頂部。(Java 使用者可能會認識到此行為。)

  • PEP 3134:異常物件現在將其回溯儲存為 __traceback__ 屬性。這意味著異常物件現在包含與異常相關的所有資訊,並且使用 sys.exc_info() 的理由更少了(儘管後者並未被移除)。

  • 當 Windows 無法載入擴充套件模組時,改進了一些異常訊息。例如,錯誤程式碼 193 現在是 %1 不是有效的 Win32 應用程式。字串現在處理非英語語言環境。

其他雜項更改

運算子和特殊方法

  • != 現在返回 == 的相反結果,除非 == 返回 NotImplemented

  • “未繫結方法”的概念已從語言中刪除。當將方法作為類屬性引用時,現在會得到一個普通的函式物件。

  • __getslice__()__setslice__()__delslice__() 已被移除。語法 a[i:j] 現在轉換為 a.__getitem__(slice(i, j)) (或者,當用作賦值或刪除目標時,分別轉換為 __setitem__()__delitem__())。

  • PEP 3114:標準的 next() 方法已重新命名為 __next__()

  • 移除了 __oct__()__hex__() 特殊方法 —— oct()hex() 現在使用 __index__() 將引數轉換為整數。

  • 移除了對 __members____methods__ 的支援。

  • 名為 func_X 的函式屬性已重新命名為使用 __X__ 形式,從而在函式屬性名稱空間中為使用者定義的屬性釋放這些名稱。也就是說,func_closurefunc_codefunc_defaultsfunc_dictfunc_docfunc_globalsfunc_name 分別重新命名為 __closure____code____defaults____dict____doc____globals____name__

  • __nonzero__() 現在是 __bool__()

內建函式

  • PEP 3135:新的 super()。現在可以不帶引數呼叫 super(),並且(假設這是在 class 語句中定義的常規例項方法)會自動選擇正確的類和例項。帶引數時,super() 的行為不變。

  • PEP 3111raw_input() 已重新命名為 input()。也就是說,新的 input() 函式從 sys.stdin 讀取一行,並刪除末尾的換行符後返回。如果輸入過早終止,則會引發 EOFError。要獲得舊的 input() 行為,請使用 eval(input())

  • 添加了一個新的內建函式 next(),用於呼叫物件上的 __next__() 方法。

  • round() 函式的舍入策略和返回型別已更改。精確的中間情況現在舍入到最接近的偶數結果,而不是遠離零。(例如,round(2.5) 現在返回 2 而不是 3。)round(x[, n]) 現在委託給 x.__round__([n]) 而不是總是返回浮點數。當使用單個引數呼叫時,它通常返回一個整數;當使用兩個引數呼叫時,它返回與 x 相同型別的值。

  • intern() 移到 sys.intern()

  • 已移除:apply()。使用 f(*args) 代替 apply(f, args)

  • 移除了 callable()。可以使用 isinstance(f, collections.Callable) 代替 callable(f)operator.isCallable() 函式也已消失。

  • 移除了 coerce()。既然經典類已經消失,此函式不再有作用。

  • 移除了 execfile()。使用 exec(open(fn).read()) 代替 execfile(fn)

  • 移除了 file 型別。請使用 open()。現在,io 模組中,open 可以返回幾種不同型別的流。

  • 移除了 reduce()。如果確實需要,請使用 functools.reduce();但是,99% 的時間裡,顯式的 for 迴圈更具可讀性。

  • 移除了 reload()。請使用 imp.reload()

  • 已移除。dict.has_key() – 請改用 in 運算子。

構建和 C API 更改

由於時間限制,這裡僅列出 C API 更改的非常不完整的列表。

  • 刪除了對多個平臺的支援,包括但不限於 Mac OS 9、BeOS、RISCOS、Irix 和 Tru64。

  • PEP 3118:新的緩衝區 API。

  • PEP 3121:擴充套件模組初始化和最終化。

  • PEP 3123:使 PyObject_HEAD 符合標準 C 規範。

  • 不再支援 C API 的受限執行。

  • PyNumber_Coerce()PyNumber_CoerceEx()PyMember_Get()PyMember_Set() C API 已被移除。

  • 新的 C API PyImport_ImportModuleNoBlock(),其功能類似於 PyImport_ImportModule(),但不會阻塞匯入鎖(而是返回錯誤)。

  • 重新命名了布林轉換的 C 級槽和方法:nb_nonzero 現在是 nb_bool

  • 從 C API 中移除了 METH_OLDARGSWITH_CYCLE_GC

效能

3.0 版本通用化的最終結果是,Python 3.0 執行 pystone 基準測試比 Python 2.5 慢約 10%。最大的原因很可能是移除了對小整數的特殊處理。仍然有改進的空間,但這將在 3.0 釋出後進行!

移植到 Python 3.0

對於將現有的 Python 2.5 或 2.6 原始碼移植到 Python 3.0,最佳策略如下:

  1. (前提條件:)從出色的測試覆蓋率開始。

  2. 移植到 Python 2.6。這應該不會比從 Python 2.x 到 Python 2.(x+1) 的平均移植工作量更多。確保所有測試都透過。

  3. (仍然使用 2.6:)開啟 -3 命令列開關。這將啟用有關 3.0 中將刪除(或更改)的功能的警告。再次執行您的測試套件,並修復您收到警告的程式碼,直到沒有剩餘警告,並且所有測試仍然透過。

  4. 在您的原始碼樹上執行 2to3 原始碼到原始碼轉換器。在 Python 3.0 下執行轉換後的結果。手動修復任何剩餘的問題,直到所有測試再次透過。

不建議嘗試編寫在 Python 2.6 和 3.0 下都能不變地執行的原始碼;您必須使用非常扭曲的編碼風格,例如避免使用 print 語句、元類等等。如果您正在維護一個需要同時支援 Python 2.6 和 Python 3.0 的庫,最好的方法是透過編輯 2.6 版本的原始碼並再次執行 2to3 轉換器來修改上面的步驟 3,而不是編輯 3.0 版本的原始碼。

有關將 C 擴充套件移植到 Python 3.0 的資訊,請參閱 將擴充套件模組移植到 Python 3