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 最容易遇到的更改。
Print 成為函式¶
print
語句已被 print()
函式取代,並使用關鍵字引數取代了舊 print
語句的大部分特殊語法 (PEP 3105)。示例:
Old: print "The answer is", 2*2
New: print("The answer is", 2*2)
Old: print x, # Trailing comma suppresses newline
New: print(x, end=" ") # Appends a space instead of a newline
Old: print # Prints a newline
New: print() # You must call the function!
Old: print >>sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)
Old: print (x, y) # prints repr((x, y))
New: print((x, y)) # Not the same as print(x, y)!
你還可以自定義專案之間的分隔符,例如:
print("There are <", 2**32, "> possibilities!", sep="")
它將產生
There are <4294967296> possibilities!
備註
檢視和迭代器取代列表¶
一些知名的 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 > None
或len <= 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 世界中,存在大量與混合編碼和未編碼文字有關的 bug。為了在 Python 2.x 中做好準備,開始對所有未編碼文字使用
unicode
,並且只對二進位制或編碼資料使用str
。然後2to3
工具將為你完成大部分工作。你不再可以使用
u"..."
字面量表示 Unicode 文字。但是,你必須使用b"..."
字面量表示二進位制資料。由於
str
和bytes
型別不能混合使用,你必須始終在它們之間顯式轉換。使用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
已被移除。請改用str
。str
和bytes
型別的功能沒有足夠的共同點來保證共享基類。2to3
工具(見下文)將所有出現的basestring
替換為str
。以文字檔案模式開啟的檔案(
open()
仍預設為此模式)始終使用編碼在字串(記憶體中)和位元組(磁碟上)之間進行對映。二進位制檔案(以模式引數中的b
開啟)始終在記憶體中使用位元組。這意味著如果檔案以不正確的模式或編碼開啟,I/O 很可能會大聲失敗,而不是靜默地產生不正確的資料。這也意味著即使是 Unix 使用者在開啟檔案時也必須指定正確的模式(文字或二進位制)。存在一個平臺相關的預設編碼,在 Unix 平臺下可以透過LANG
環境變數(有時也透過其他平臺特定的區域設定相關環境變數)進行設定。在許多情況下,但並非所有情況下,系統預設編碼是 UTF-8;你不應該依賴此預設值。任何讀寫純 ASCII 文字之外的應用程式都應該有辦法覆蓋編碼。不再需要使用codecs
模組中支援編碼的流。sys.stdin
、sys.stdout
和sys.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.environ
和sys.argv
,當系統提供的位元組無法使用預設編碼解釋時,也可能出現問題。設定LANG
變數並重新執行程式可能是最好的方法。PEP 3138:字串的
repr()
不再轉義非 ASCII 字元。但它仍然轉義 Unicode 標準中具有不可列印狀態的控制字元和碼點。PEP 3120:預設原始碼編碼現在是 UTF-8。
PEP 3131:識別符號中現在允許使用非 ASCII 字母。(但是,標準庫仍然只包含 ASCII 字元,註釋中的貢獻者姓名除外。)
StringIO
和cStringIO
模組已刪除。相反,請匯入io
模組,並分別使用io.StringIO
或io.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 = stuff
。rest
物件始終是(可能為空的)列表;右側可以是任何可迭代物件。示例:(a, *rest, b) = range(5)
這將 a 設定為
0
,b 設定為4
,rest 設定為[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()
。位元組字面量以
b
或B
開頭,並且有一個新的相應內建函式bytes()
。
改變的語法¶
PEP 3109 和 PEP 3134:新的
raise
語句語法:raise [expr [from expr]]
。見下文。as
和with
現在是保留字。(實際上自 2.6 以來就是。)True
,False
, 和None
是保留字。(2.6 已經部分強制執行了對None
的限制。)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)
。整數字面量不再支援末尾的
l
或L
。字串字面量不再支援前導的
u
或U
。從 module
import
*
語法只允許在模組級別使用,不再允許在函式內部使用。相對匯入唯一可接受的語法是
from .[module] import name
。所有不以.
開頭的import
形式都被解釋為絕對匯入。(PEP 328)經典類已移除。
Python 2.6 中已存在的更改¶
由於許多使用者可能直接從 Python 2.5 跳到 Python 3.0,本節提醒讀者注意最初為 Python 3.0 設計但已反向移植到 Python 2.6 的新功能。有關更長的描述,應查閱 Python 2.6 的新功能 中的相應章節。
PEP 343:'with' 語句。
with
語句現在是標準功能,不再需要從__future__
匯入。另請檢視 編寫上下文管理器 和 contextlib 模組。PEP 366:從主模組進行顯式相對匯入。這增強了當引用模組位於包中時
-m
選項的實用性。PEP 3101:高階字串格式化。注意:2.6 的描述提到了 8 位和 Unicode 字串的
format()
方法。在 3.0 中,只有str
型別(支援 Unicode 的文字字串)支援此方法;bytes
型別不支援。計劃是最終將此作為字串格式化的唯一 API,並在 Python 3.1 中開始棄用%
運算子,之後在某個時間從語言中移除。PEP 3105:print 作為函式。這現在是一個標準功能,不再需要從
__future__
匯入。上面給出了更多詳細資訊。PEP 3110:異常處理更改。現在
except
excas
var 語法是標準語法,except
exc, var 不再受支援。(當然,as
var 部分仍然是可選的。)PEP 3112:位元組字面量。
b"..."
字串字面量表示法(及其變體,如b'...'
、b"""..."""
和br"..."
)現在生成bytes
型別的字面量。PEP 3116:新 I/O 庫。
io
模組現在是進行檔案 I/O 的標準方式。內建的open()
函式現在是io.open()
的別名,並具有額外的關鍵字引數 encoding、errors、newline 和 closefd。另請注意,無效的 mode 引數現在會引發ValueError
,而不是IOError
。文字檔案物件底層的基礎二進位制檔案物件可以透過f.buffer
訪問(但請注意,文字物件會維護自身的緩衝區以加速編碼和解碼操作)。PEP 3118:修訂的緩衝區協議。舊的內建
buffer()
現已完全移除;新的內建memoryview()
提供了(大部分)相似的功能。PEP 3119:抽象基類。
abc
模組和collections
模組中定義的抽象基類(ABCs)現在在語言中扮演著更為突出的角色,並且內建集合型別如dict
和list
分別符合collections.MutableMapping
和collections.MutableSequence
ABC。PEP 3127:整數字面量支援和語法。如上所述,新的八進位制字面量表示法是唯一受支援的,並且已新增二進位制字面量。
PEP 3141:數字的型別層次結構。
numbers
模組是 ABC 的另一個新用法,它定義了 Python 的“數字塔”。另請注意新的fractions
模組,它實現了numbers.Rational
。
庫更改¶
由於時間限制,本文件未能詳盡涵蓋標準庫中非常廣泛的更改。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
SocketServer
socketserver
markupbase
_markupbase
repr
reprlib
test.test_support
test.support
Python 2.x 中常見的模式是有一個純 Python 實現的模組版本,以及一個可選的 C 擴充套件實現的加速版本;例如,
pickle
和cPickle
。這使得每個使用這些模組的使用者都必須承擔匯入加速版本並回退到純 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
(除了turtle
之外的所有Tkinter
相關模組)。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()
。此外,陣列的'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.lowercase
和string.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 仍然允許引發經典類,並且對你可以捕獲的內容沒有限制。)因此,字串異常終於真正徹底地消失了。幾乎所有異常實際上都應該派生自
Exception
;BaseException
應該只用作僅在頂層處理的異常的基類,例如SystemExit
或KeyboardInterrupt
。處理除後者以外所有異常的推薦慣例是使用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:異常鏈。有兩種情況:隱式鏈和顯式鏈。隱式鏈發生在
except
或finally
處理程式塊中引發異常時。這通常是由於處理程式塊中的錯誤造成的;我們稱之為 次要 異常。在這種情況下,原始異常(正在處理的異常)將作為次要異常的__context__
屬性儲存。顯式鏈使用此語法呼叫:raise SecondaryException() from primary_exception
(其中 primary_exception 是任何產生異常物件的表示式,可能是之前捕獲的異常)。在這種情況下,主異常儲存在次要異常的
__cause__
屬性上。當發生未處理的異常時列印的回溯會遍歷__cause__
和__context__
屬性鏈,併為鏈的每個元件列印單獨的回溯,主異常位於頂部。(Java 使用者可能會識別此行為。)PEP 3134:異常物件現在將其回溯儲存為
__traceback__
屬性。這意味著異常物件現在包含與異常相關的所有資訊,使用sys.exc_info()
的原因更少(儘管後者並未移除)。當 Windows 無法載入擴充套件模組時,一些異常訊息得到了改進。例如,
error code 193
現在是%1 is not a valid Win32 application
。字串現在處理非英語語言環境。
其他雜項更改¶
運算子和特殊方法¶
!=
現在返回==
的相反值,除非==
返回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_closure
、func_code
、func_defaults
、func_dict
、func_doc
、func_globals
、func_name
分別重新命名為__closure__
、__code__
、__defaults__
、__dict__
、__doc__
、__globals__
、__name__
。__nonzero__()
現在是__bool__()
。
內建函式¶
PEP 3135:新的
super()
。現在,您可以在不帶引數的情況下呼叫super()
,並且(假設它是在class
語句中定義的常規例項方法中)將自動選擇正確的類和例項。帶引數時,super()
的行為保持不變。PEP 3111:
raw_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)
。已移除
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_OLDARGS
和WITH_CYCLE_GC
。
效能¶
Python 3.0 泛化的最終結果是,Python 3.0 執行 pystone 基準測試比 Python 2.5 慢約 10%。最大的原因很可能是取消了對小整數的特殊處理。仍有改進的空間,但這將在 3.0 釋出後進行!
移植到 Python 3.0¶
要將現有 Python 2.5 或 2.6 原始碼移植到 Python 3.0,最佳策略如下:
(先決條件:) 從出色的測試覆蓋率開始。
移植到 Python 2.6。這應該不比從 Python 2.x 移植到 Python 2.(x+1) 的平均工作量大。確保所有測試都透過。
(仍使用 2.6:) 啟用
-3
命令列開關。這將啟用有關 3.0 中將移除(或更改)的功能的警告。再次執行您的測試套件,並修復您收到警告的程式碼,直到沒有警告,並且所有測試仍然透過。在您的原始碼樹上執行
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。