Python 2.4 新特性

作者:

A.M. Kuchling

本文介紹了 2005 年 3 月 30 日釋出的 Python 2.4.1 中的新功能。

Python 2.4 是一箇中等規模的版本。它不像激進的 Python 2.2 那樣引入了許多更改,但引入的功能比保守的 2.3 版本多。 最重要的新語言特性是函式裝飾器和生成器表示式; 大多數其他更改都針對標準庫。

根據 CVS 更改日誌,在 Python 2.3 和 2.4 之間應用了 481 個補丁,修復了 502 個錯誤。這兩個數字都可能被低估了。

本文不試圖提供每個新功能的完整規範,而是提供每個功能的簡要介紹。 有關完整詳細資訊,您應參考 Python 2.4 的文件,例如 Python 庫參考和 Python 參考手冊。 通常,您將被推薦使用特定新功能的 PEP,以瞭解實現和設計原理。

PEP 218:內建集合物件

Python 2.3 引入了 sets 模組。現在,集合資料型別的 C 實現已作為兩個新的內建型別 set(iterable)frozenset(iterable) 新增到 Python 核心中。它們為成員資格測試、從序列中消除重複項以及諸如並集、交集、差集和對稱差集之類的數學運算提供了高速操作。

>>> a = set('abracadabra')              # form a set from a string
>>> 'z' in a                            # fast membership testing
False
>>> a                                   # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a)                          # convert back into a string
'arbcd'

>>> b = set('alacazam')                 # form a second set
>>> a - b                               # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b                               # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b                               # letters in both a and b
set(['a', 'c'])
>>> a ^ b                               # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])

>>> a.add('z')                          # add a new element
>>> a.update('wxy')                     # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x')                       # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])

frozenset() 型別是 set() 的不可變版本。 由於它是不可變的並且可雜湊的,因此可以用作字典鍵或另一個集合的成員。

sets 模組保留在標準庫中,如果您希望子類化 SetImmutableSet 類,它可能會很有用。目前沒有計劃棄用該模組。

另請參閱

PEP 218 - 新增內建集合物件型別

最初由 Greg Wilson 提出,最終由 Raymond Hettinger 實現。

PEP 237:統一長整數和整數

此 PEP 的漫長過渡過程始於 Python 2.2,在 Python 2.4 中又向前邁進了一步。 在 2.3 中,某些在 int/long 統一後行為不同的整數運算會觸發 FutureWarning 警告,並返回限制為 32 位或 64 位(取決於您的平臺)的值。在 2.4 中,這些表示式不再產生警告,而是產生不同的結果,通常是長整數。

有問題的表示式主要是左移和冗長的十六進位制和八進位制常量。 例如,2 << 32 在 2.3 中會產生警告,在 32 位平臺上計算結果為 0。在 Python 2.4 中,此表示式現在返回正確答案 8589934592。

另請參閱

PEP 237 - 統一長整數和整數

原始 PEP 由 Moshe Zadka 和 GvR 編寫。 2.4 的更改由 Kalle Svensson 實現。

PEP 289:生成器表示式

Python 2.2 中引入的迭代器特性和 itertools 模組使編寫迴圈遍歷大型資料集的程式更容易,而無需一次將整個資料集儲存在記憶體中。 列表推導式不太適合這種情況,因為它們會生成一個包含所有項的 Python 列表物件。 這不可避免地會將所有物件拉入記憶體,如果您的資料集非常大,這可能會成為問題。 在嘗試編寫函式式風格的程式時,很自然地會寫成類似於

links = [link for link in get_all_links() if not link.followed]
for link in links:
    ...

而不是

for link in get_all_links():
    if link.followed:
        continue
    ...

第一種形式更簡潔,可能更具可讀性,但如果您正在處理大量連結物件,則必須編寫第二種形式,以避免同時將所有連結物件都儲存在記憶體中。

生成器表示式的工作方式與列表推導式類似,但不會物化整個列表; 相反,它們會建立一個生成器,該生成器將逐個返回元素。 上面的例子可以寫成

links = (link for link in get_all_links() if not link.followed)
for link in links:
    ...

生成器表示式始終必須寫在括號內,如上面的示例所示。 表示函式呼叫的括號也計算在內,因此如果要建立一個將立即傳遞給函式的迭代器,則可以寫成

print sum(obj.count for obj in list_all_objects())

生成器表示式在各種小方面與列表推導式不同。 最值得注意的是,迴圈變數(在上面的示例中為obj)在生成器表示式之外是不可訪問的。 列表推導式將變數賦值給其最後的值; Python 的未來版本將更改此設定,使列表推導式在這方面與生成器表示式匹配。

另請參閱

PEP 289 - 生成器表示式

由 Raymond Hettinger 提出,由 Jiwon Seo 實現,早期工作由 Hye-Shik Chang 指導。

PEP 292:更簡單的字串替換

標準庫中的一些新類為將變數替換到字串中提供了另一種機制; 這種替換樣式可能更適合未經培訓的使用者需要編輯模板的應用程式。

按名稱替換變數的常用方法是 % 運算子

>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'

在編寫模板字串時,很容易忘記右括號後面的 is。 如果模板在 Python 模組中,這不是一個大問題,因為您執行程式碼,會得到“不支援的格式字元” ValueError 並修復問題。 但是,考慮一下諸如 Mailman 之類的應用程式,其中模板字串或翻譯由不瞭解 Python 語言的使用者編輯。 格式字串的語法對於此類使用者來說很難解釋,如果他們犯了錯誤,則很難向他們提供有用的反饋。

PEP 292 將 Template 類新增到 string 模組,該模組使用 $ 來指示替換

>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'

如果字典中缺少鍵,則 substitute() 方法將引發 KeyError。 還有一個 safe_substitute() 方法會忽略缺少的鍵

>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'

另請參閱

PEP 292 - 更簡單的字串替換

由 Barry Warsaw 編寫和實現。

PEP 318:函式和方法的裝飾器

Python 2.2 透過新增靜態方法和類方法擴充套件了 Python 的物件模型,但它沒有擴充套件 Python 的語法來提供定義靜態方法或類方法的任何新方法。 相反,您必須以通常的方式編寫 def 語句,並將結果方法傳遞給 staticmethod()classmethod() 函式,該函式會將該函式包裝為新型別的方法。 您的程式碼如下所示

class C:
   def meth (cls):
       ...

   meth = classmethod(meth)   # Rebind name to wrapped-up class method

如果方法很長,就很容易錯過或忘記函式體後面的 classmethod() 呼叫。

最初的想法是新增一些語法來使此類定義更具可讀性,但在 2.2 版本釋出時,一個好的語法並不明顯。如今,一個好的語法仍然不明顯,但使用者要求更容易訪問該功能;因此添加了一個新的語法特性來滿足這一需求。

這個新特性被稱為“函式裝飾器”。這個名稱源於這樣一個想法:classmethod()staticmethod() 和類似的功能正在函式物件上儲存額外的資訊;它們正在用更多細節裝飾函式。

這個符號借鑑了 Java,並使用 '@' 字元作為指示符。使用新的語法,上面的示例將寫成

class C:

   @classmethod
   def meth (cls):
       ...

@classmethodmeth=classmethod(meth) 賦值的簡寫形式。更一般地說,如果您有以下程式碼

@A
@B
@C
def f ():
    ...

它等效於以下預裝飾器程式碼

def f(): ...
f = A(B(C(f)))

裝飾器必須在函式定義之前的行上出現,每行一個裝飾器,並且不能與 def 語句在同一行,這意味著 @A def f(): ... 是非法的。您只能裝飾函式定義,無論是在模組級別還是在類內部;您不能裝飾類定義。

裝飾器只是一個函式,它將要裝飾的函式作為引數,並返回相同的函式或一些新物件。除非將其他裝飾器應用於結果,否則裝飾器的返回值不必是可呼叫的(儘管通常是這樣)。編寫自己的裝飾器很容易。以下簡單示例僅在函式物件上設定一個屬性

>>> def deco(func):
...    func.attr = 'decorated'
...    return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>

作為一個稍微更實際的示例,以下裝飾器檢查提供的引數是否為整數

def require_int (func):
    def wrapper (arg):
        assert isinstance(arg, int)
        return func(arg)

    return wrapper

@require_int
def p1 (arg):
    print arg

@require_int
def p2(arg):
    print arg*2

PEP 318 中的一個示例包含了一個更花哨的這個想法的版本,它可以讓您指定所需的型別並檢查返回的型別。

裝飾器函式可以接受引數。如果提供了引數,則會使用這些引數呼叫您的裝飾器函式,並且必須返回一個新的裝飾器函式;此函式必須接受一個函式並返回一個函式,如前所述。換句話說,@A @B @C(args) 變為

def f(): ...
_deco = C(args)
f = A(B(_deco(f)))

正確理解這一點可能有點繞彎,但並不太難。

一個小的相關更改使得函式的 func_name 屬性可寫。此屬性用於在回溯中顯示函式名稱,因此裝飾器應更改任何已構造並返回的新函式的名稱。

另請參閱

PEP 318 - 函式、方法和類的裝飾器

由 Kevin D. Smith、Jim Jewett 和 Skip Montanaro 編寫。有幾個人編寫了實現函式裝飾器的補丁,但實際簽入的補丁是 Mark Russell 編寫的補丁 #979728。

https://wiki.python.org/moin/PythonDecoratorLibrary

此 Wiki 頁面包含幾個裝飾器的示例。

PEP 322:反向迭代

一個新的內建函式 reversed(seq) 接受一個序列,並返回一個以相反順序迴圈遍歷序列元素的迭代器。

>>> for i in reversed(xrange(1,4)):
...    print i
...
3
2
1

與擴充套件切片(例如 range(1,4)[::-1])相比,reversed() 更易於閱讀,執行速度更快,並且使用的記憶體少得多。

請注意,reversed() 僅接受序列,不接受任意迭代器。如果要反轉迭代器,請先使用 list() 將其轉換為列表。

>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
...   print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
  ...

另請參閱

PEP 322 - 反向迭代

由 Raymond Hettinger 編寫和實現。

PEP 324:新的子程序模組

標準庫提供了許多執行子程序的方法,它們提供了不同的功能和不同的複雜程度。os.system(command) 易於使用,但速度較慢(它執行一個執行命令的 shell 程序)且危險(您必須小心轉義 shell 的元字元)。popen2 模組提供了可以捕獲子程序的標準輸出和標準錯誤輸出的類,但命名令人困惑。subprocess 模組清理了這一點,提供了一個統一的介面,可以滿足您可能需要的所有功能。

popen2 的類集合不同,subprocess 包含一個名為 subprocess.Popen 的類,其建構函式支援許多不同的關鍵字引數。

class Popen(args, bufsize=0, executable=None,
            stdin=None, stdout=None, stderr=None,
            preexec_fn=None, close_fds=False, shell=False,
            cwd=None, env=None, universal_newlines=False,
            startupinfo=None, creationflags=0):

args 通常是一個字串序列,它將作為子程序執行的程式的引數。(如果 shell 引數為 true,則 args 可以是一個字串,然後將該字串傳遞給 shell 進行解釋,就像 os.system() 所做的那樣。)

stdinstdoutstderr 指定子程序的輸入、輸出和錯誤流將是什麼。您可以提供檔案物件或檔案描述符,也可以使用常量 subprocess.PIPE 在子程序和父程序之間建立管道。

建構函式有許多方便的選項

  • close_fds 請求在執行子程序之前關閉所有檔案描述符。

  • cwd 指定將在其中執行子程序的工作目錄(預設為父程序的工作目錄)。

  • env 是一個指定環境變數的字典。

  • preexec_fn 是一個在啟動子程序之前呼叫的函式。

  • universal_newlines 使用 Python 的 通用換行符 功能開啟子程序的輸入和輸出。

建立 Popen 例項後,您可以呼叫其 wait() 方法來暫停直到子程序退出,呼叫 poll() 來檢查它是否已退出而不會暫停,或者呼叫 communicate(data) 將字串 data 傳送到子程序的標準輸入。communicate(data) 然後讀取子程序傳送到其標準輸出或標準錯誤的任何資料,返回一個元組 (stdout_data, stderr_data)

call() 是一個快捷方式,它將其引數傳遞給 Popen 建構函式,等待命令完成,並返回子程序的狀態碼。它可以作為 os.system() 的更安全替代方案

sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
    # Success
    ...
else:
    # dpkg returned an error
    ...

該命令的呼叫不使用 shell。如果您確實想使用 shell,您可以新增 shell=True 作為關鍵字引數,並提供一個字串而不是一個序列

sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)

該 PEP 採用了 shell 和 Python 程式碼的各種示例,並展示瞭如何將它們轉換為使用 subprocess 的 Python 程式碼。強烈建議閱讀 PEP 的這一部分。

另請參閱

PEP 324 - subprocess - 新程序模組

由 Peter Åstrand 編寫和實現,並得到 Fredrik Lundh 和其他人的協助。

PEP 327:十進位制資料型別

Python 一直支援浮點 (FP) 數字,它基於底層的 C double 型別,作為一種資料型別。然而,儘管大多數程式語言都提供了浮點型別,但許多人(甚至程式設計師)都沒有意識到浮點數不能準確地表示某些十進位制小數。新的 Decimal 型別可以準確地表示這些小數,直到使用者指定的精度限制。

為什麼需要 Decimal?

侷限性源於用於浮點數的表示形式。FP 數字由三個分量組成

  • 符號,即正數或負數。

  • 尾數,這是一個由一位二進位制數後跟一個小數部分組成的數。例如,以 2 為底的表示法中的 1.01 在十進位制表示法中是 1 + 0/2 + 1/4,或 1.25。

  • 指數,它指示所表示的數字中小數點的位置。

例如,數字 1.25 具有正號、尾數值為 1.01(以二進位制表示)和指數 0(不需要移動小數點)。數字 5 具有相同的符號和尾數,但指數為 2,因為尾數乘以 4(2 的指數 2 次冪);1.25 * 4 等於 5。

現代系統通常提供符合 IEEE 754 標準的浮點支援。C 語言的 double 型別通常被實現為 64 位 IEEE 754 數字,它使用 52 位空間來表示尾數。這意味著數字只能精確到 52 位。如果要表示的數字展開後會無限重複,那麼這個展開會在 52 位後被截斷。不幸的是,大多數軟體需要以 10 為底輸出,而以 10 為底的常用分數在二進位制中通常是無限迴圈小數。例如,十進位制的 1.1 在二進位制中是 1.0001100110011 ...;.1 = 1/16 + 1/32 + 1/256 加上無限多的附加項。IEEE 754 必須在 52 位後截斷這個無限重複的小數,因此表示會略有不準確。

有時,當列印數字時,您可以看到這種不準確性。

>>> 1.1
1.1000000000000001

當您列印數字時,這種不準確性並不總是可見的,因為 FP 到十進位制字串的轉換是由 C 庫提供的,並且大多數 C 庫都試圖產生合理的輸出。然而,即使它沒有顯示出來,這種不準確性仍然存在,並且後續操作可能會放大錯誤。

對於許多應用程式來說,這並不重要。如果我正在繪製點並在我的顯示器上顯示它們,那麼 1.1 和 1.1000000000000001 之間的差異太小,無法被看到。報告通常將輸出限制為特定的小數位數,如果您將數字四捨五入到兩位、三位甚至八位小數,則永遠不會出現錯誤。但是,對於確實重要的應用程式來說,實現您自己的自定義算術例程需要做很多工作。

因此,建立了 Decimal 型別。

Decimal 型別

一個新的模組 decimal 被新增到 Python 的標準庫中。它包含兩個類,DecimalContextDecimal 例項表示數字,Context 例項用於封裝各種設定,例如精度和預設舍入模式。

Decimal 例項是不可變的,就像常規的 Python 整數和 FP 數字一樣;一旦建立,您就無法更改例項表示的值。Decimal 例項可以從整數或字串建立。

>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")

您還可以提供包含符號、以十進位制數字元組表示的尾數和指數的元組。

>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")

注意:符號位是一個布林值,因此 0 為正,1 為負。

從浮點數轉換會帶來一點問題:表示 1.1 的 FP 數字應該轉換為完全是 1.1 的十進位制數,還是轉換為 1.1 加上任何引入的不準確之處? 決定是迴避這個問題,並將這種轉換排除在 API 之外。相反,您應該使用所需的精度將浮點數轉換為字串,並將該字串傳遞給 Decimal 建構函式。

>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")

一旦您擁有 Decimal 例項,您就可以對它們執行通常的數學運算。一個限制:求冪需要整數指數。

>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
  ...
decimal.InvalidOperation: x ** (non-integer)

您可以將 Decimal 例項與整數組合,但不能與浮點數組合。

>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
  ...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>

Decimal 數字可以與 mathcmath 模組一起使用,但請注意,在執行操作之前,它們將立即轉換為浮點數,從而可能導致精度和準確性的損失。您還將得到一個常規的浮點數而不是 Decimal

>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j

Decimal 例項有一個 sqrt() 方法,該方法返回一個 Decimal,但如果您需要其他函式,例如三角函式,則必須自己實現它們。

>>> d.sqrt()
Decimal("351364.1828820134592177245001")

Context 型別

Context 類的例項封裝了十進位制運算的幾個設定。

  • prec 是精度,即小數位數。

  • rounding 指定舍入模式。decimal 模組具有各種可能性的常量:ROUND_DOWNROUND_CEILINGROUND_HALF_EVEN 以及其他各種常量。

  • traps 是一個字典,用於指定在遇到某些錯誤條件時會發生什麼:要麼引發異常,要麼返回一個值。錯誤條件的一些示例包括除以零、精度損失和溢位。

透過呼叫 getcontext() 可以獲得一個執行緒本地的預設上下文;您可以更改此上下文的屬性以更改預設精度、舍入或陷阱處理。以下示例顯示了更改預設上下文的精度的效果。

>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")

錯誤條件的預設操作是可選的;該模組可以返回一個特殊值,例如無窮大或非數字,或者可以引發異常。

>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
  ...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>

Context 例項還有各種格式化數字的方法,例如 to_eng_string()to_sci_string()

有關更多資訊,請參閱 decimal 模組的文件,其中包括一個快速入門教程和參考。

另請參閱

PEP 327 - 十進位制資料型別

由 Facundo Batista 編寫,並由 Facundo Batista、Eric Price、Raymond Hettinger、Aahz 和 Tim Peters 實現。

http://www.lahey.com/float.htm

本文使用 Fortran 程式碼來說明浮點數不準確可能導致的許多問題。

https://speleotrove.com/decimal/

基於十進位制的表示的描述。這種表示形式正在被提議作為標準,並且是新的 Python 十進位制型別的基礎。此材料的大部分由 Rexx 語言的設計者 Mike Cowlishaw 編寫。

PEP 328:多行匯入

一項語言更改是對語法的微小調整,旨在使從模組匯入許多名稱變得更容易。在 from module import names 語句中,names 是一個以逗號分隔的名稱序列。如果序列很長,您可以從同一個模組編寫多個匯入,或者可以使用反斜槓轉義行尾,如下所示:

from SimpleXMLRPCServer import SimpleXMLRPCServer,\
            SimpleXMLRPCRequestHandler,\
            CGIXMLRPCRequestHandler,\
            resolve_dotted_attribute

Python 2.4 中的語法更改只是允許將名稱放在括號內。Python 會忽略帶括號的表示式中的換行符,因此不再需要反斜槓。

from SimpleXMLRPCServer import (SimpleXMLRPCServer,
                                SimpleXMLRPCRequestHandler,
                                CGIXMLRPCRequestHandler,
                                resolve_dotted_attribute)

PEP 還建議所有 import 語句都是絕對匯入,使用前導 . 字元來指示相對匯入。PEP 的這部分未在 Python 2.4 中實現,但在 Python 2.5 中完成。

另請參閱

PEP 328 - 匯入:多行和絕對/相對

由 Aahz 編寫。多行匯入由 Dima Dorfman 實現。

PEP 331:與區域設定無關的浮點/字串轉換

locale 模組允許 Python 軟體選擇各種轉換和顯示約定,這些轉換和顯示約定本地化為特定的國家或語言。但是,該模組小心地不更改數字區域設定,因為 Python 實現中的各種函式要求將數字區域設定保持設定為 'C' 區域設定。通常這是因為程式碼正在使用 C 庫的 atof() 函式。

但是,不設定數字區域設定給使用第三方 C 庫的擴充套件帶來了麻煩,因為它們沒有設定正確的區域設定。 激勵示例是 GTK+,其使用者介面小部件沒有以當前區域設定顯示數字。

PEP 中描述的解決方案是在 Python API 中新增三個新函式,它們執行僅限 ASCII 的轉換,忽略區域設定。

  • PyOS_ascii_strtod(str, ptr)PyOS_ascii_atof(str, ptr) 都將字串轉換為 C double

  • PyOS_ascii_formatd(buffer, buf_len, format, d)double 轉換為 ASCII 字串。

這些函式的程式碼來自 GLib 庫 (https://developer-old.gnome.org/glib/2.26/),其開發人員慷慨地重新許可了相關函式並將其捐贈給了 Python 軟體基金會。locale 模組現在可以更改數字區域設定,從而使 GTK+ 等擴充套件產生正確的結果。

另請參閱

PEP 331 - 與區域設定無關的浮點/字串轉換

由 Christian R. Reis 編寫,並由 Gustavo Carneiro 實現。

其他語言更改

以下是 Python 2.4 對核心 Python 語言所做的所有更改。

  • 為函式和方法添加了裝飾器 (PEP 318)。

  • 增加了內建的 set()frozenset() 型別 (PEP 218)。其他新的內建函式包括 reversed(seq) 函式 (PEP 322)。

  • 增加了生成器表示式 (PEP 289)。

  • 某些數值表示式不再返回限制為 32 位或 64 位的值 (PEP 237)。

  • 現在可以在 from module import names 語句中用括號括起名稱列表 (PEP 328)。

  • dict.update() 方法現在接受與 dict 建構函式相同的引數形式。這包括任何對映、任何鍵/值對的可迭代物件以及關鍵字引數。(由 Raymond Hettinger 貢獻。)

  • 字串方法 ljust()rjust()center() 現在接受一個可選引數來指定除空格以外的填充字元。(由 Raymond Hettinger 貢獻。)

  • 字串還獲得了一個 rsplit() 方法,該方法的工作方式類似於 split() 方法,但從字串末尾開始拆分。(由 Sean Reifschneider 貢獻。)

    >>> 'www.python.org'.split('.', 1)
    ['www', 'python.org']
    'www.python.org'.rsplit('.', 1)
    ['www.python', 'org']
    
  • 在列表的 sort() 方法中添加了三個關鍵字引數,cmpkeyreverse。這些引數使 sort() 的一些常見用法更加簡單。所有這些引數都是可選的。

    對於 cmp 引數,該值應該是一個比較函式,它接受兩個引數,並根據引數的比較方式返回 -1、0 或 +1。然後,此函式將用於對列表進行排序。以前,這是可以提供給 sort() 的唯一引數。

    key 應該是一個單引數函式,它接受一個列表元素並返回該元素的比較鍵。然後使用比較鍵對列表進行排序。以下示例不區分大小寫地對列表進行排序

    >>> L = ['A', 'b', 'c', 'D']
    >>> L.sort()                 # Case-sensitive sort
    >>> L
    ['A', 'D', 'b', 'c']
    >>> # Using 'key' parameter to sort list
    >>> L.sort(key=lambda x: x.lower())
    >>> L
    ['A', 'b', 'c', 'D']
    >>> # Old-fashioned way
    >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
    >>> L
    ['A', 'b', 'c', 'D']
    

    最後一個示例使用 cmp 引數,這是執行不區分大小寫排序的舊方法。它可以工作,但比使用 key 引數慢。使用 key 為列表中的每個元素呼叫一次 lower() 方法,而使用 cmp 將為每個比較呼叫兩次,因此使用 key 可以節省 lower() 方法的呼叫次數。

    對於簡單的鍵函式和比較函式,通常可以透過使用未繫結的方法來避免 lambda 表示式。例如,上面的不區分大小寫的排序最好寫成

    >>> L.sort(key=str.lower)
    >>> L
    ['A', 'b', 'c', 'D']
    

    最後,reverse 引數接受一個布林值。如果該值為 true,則列表將按相反順序排序。現在可以編寫 L.sort(reverse=True),而不是 L.sort(); L.reverse()

    現在保證排序的結果是穩定的。這意味著具有相同鍵的兩個條目將以與輸入時相同的順序返回。例如,你可以按姓名對人員列表進行排序,然後按年齡對列表進行排序,從而得到一個按年齡排序的列表,其中年齡相同的人員按姓名排序。

    (sort() 的所有更改均由 Raymond Hettinger 貢獻。)

  • 有一個新的內建函式 sorted(iterable),它的工作方式類似於就地 list.sort() 方法,但可以在表示式中使用。區別在於

  • 輸入可以是任何可迭代物件;

  • 對新形成的副本進行排序,保持原始副本不變;並且

  • 表示式返回新的排序副本

    >>> L = [9,7,8,3,2,4,1,6,5]
    >>> [10+i for i in sorted(L)]       # usable in a list comprehension
    [11, 12, 13, 14, 15, 16, 17, 18, 19]
    >>> L                               # original is left unchanged
    [9,7,8,3,2,4,1,6,5]
    >>> sorted('Monty Python')          # any iterable may be an input
    [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']
    
    >>> # List the contents of a dict sorted by key values
    >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)
    >>> for k, v in sorted(colormap.iteritems()):
    ...     print k, v
    ...
    black 4
    blue 2
    green 3
    red 1
    yellow 5
    

    (由 Raymond Hettinger 貢獻。)

  • 整數運算將不再觸發 OverflowWarningOverflowWarning 警告將在 Python 2.5 中消失。

  • 直譯器獲得了一個新的開關 -m,它接受一個名稱,在 sys.path 上搜索相應的模組,並將該模組作為指令碼執行。例如,現在可以使用 python -m profile 執行 Python 分析器。(由 Nick Coghlan 貢獻。)

  • eval(expr, globals, locals)execfile(filename, globals, locals) 函式以及 exec 語句現在接受任何對映型別作為 locals 引數。以前,這必須是常規的 Python 字典。(由 Raymond Hettinger 貢獻。)

  • zip() 內建函式和 itertools.izip() 現在在不帶引數呼叫時返回一個空列表。以前,它們會引發 TypeError 異常。這使得它們更適合與可變長度的引數列表一起使用

    >>> def transpose(array):
    ...    return zip(*array)
    ...
    >>> transpose([(1,2,3), (4,5,6)])
    [(1, 4), (2, 5), (3, 6)]
    >>> transpose([])
    []
    

    (由 Raymond Hettinger 貢獻。)

  • 在匯入模組時遇到故障不再在 sys.modules 中留下部分初始化的模組物件。留下的不完整的模組物件會迷惑對同一模組的進一步匯入,使其成功,從而導致令人困惑的錯誤。(由 Tim Peters 修復。)

  • None 現在是一個常量;將新值繫結到名稱 None 的程式碼現在是語法錯誤。(由 Raymond Hettinger 貢獻。)

最佳化

  • 列表和元組切片的內部迴圈已得到最佳化,現在執行速度快了大約三分之一。字典的內部迴圈也得到了最佳化,從而提高了 keys()values()items()iterkeys()itervalues()iteritems() 的效能。(由 Raymond Hettinger 貢獻。)

  • 用於增長和縮小列表的機制針對速度和空間效率進行了最佳化。由於更高效的程式碼路徑和更少地使用底層系統 realloc(),從列表中追加和彈出現在執行得更快。列表推導式也受益。list.extend() 也得到了最佳化,並且不再在擴充套件基本列表之前將其引數轉換為臨時列表。(由 Raymond Hettinger 貢獻。)

  • list()tuple()map()filter()zip() 現在使用提供 __len__() 方法的非序列引數執行速度快了幾倍。(由 Raymond Hettinger 貢獻。)

  • 方法 list.__getitem__()dict.__getitem__()dict.__contains__() 現在實現為 method_descriptor 物件,而不是 wrapper_descriptor 物件。這種訪問形式使其效能提高了一倍,並使其更適合用作函式式引數:map(mydict.__getitem__, keylist)。(由 Raymond Hettinger 貢獻。)

  • 添加了一個新的操作碼 LIST_APPEND,它簡化了列表推導式的生成的位元組碼,並將其速度提高了大約三分之一。(由 Raymond Hettinger 貢獻。)

  • 窺孔位元組碼最佳化器已得到改進,可生成更短、更快的位元組碼;值得注意的是,生成的位元組碼更具可讀性。(由 Raymond Hettinger 增強。)

  • 形如 s = s + "abc"s += "abc" 語句中的字串連線現在在某些情況下執行得更有效率。這種最佳化不會出現在其他 Python 實現中,例如 Jython,因此你不應該依賴它;當你想要有效地將大量字串粘合在一起時,仍然建議使用字串的 join() 方法。(由 Armin Rigo 貢獻。)

2.4 最佳化的最終結果是,Python 2.4 執行 pystone 基準測試的速度比 Python 2.3 快約 5%,比 Python 2.2 快 35%。(pystone 不是一個特別好的基準測試,但它是最常用的 Python 效能測量方法。你自己的應用程式可能會顯示 Python 2.4 帶來的更大或更小的收益。)

新的、改進的和已棄用的模組

像往常一樣,Python 的標準庫收到了一些增強功能和錯誤修復。以下是按模組名稱字母順序排列的最顯著更改的部分列表。有關更完整的更改列表,請查閱原始碼樹中的 Misc/NEWS 檔案,或檢視 CVS 日誌以獲取所有詳細資訊。

  • asyncore 模組的 loop() 函式現在有一個 count 引數,允許您執行有限次數的輪詢迴圈。預設值仍然是無限迴圈。

  • base64 模組現在對 Base64、Base32 和 Base16 編碼和解碼具有更完整的 RFC 3548 支援,包括可選的大小寫摺疊和可選的替代字母表。(由 Barry Warsaw 貢獻。)

  • bisect 模組現在有一個底層的 C 實現,以提高效能。(由 Dmitry Vasiliev 貢獻。)

  • 由 Hye-Shik Chang 維護的東亞編解碼器 CJKCodecs 集合已整合到 2.4 中。新的編碼是

  • 中文(中國):gb2312、gbk、gb18030、big5hkscs、hz

  • 中文(中華民國):big5、cp950

  • 日語:cp932、euc-jis-2004、euc-jp、euc-jisx0213、iso-2022-jp、

    iso-2022-jp-1、iso-2022-jp-2、iso-2022-jp-3、iso-2022-jp-ext、iso-2022-jp-2004、shift-jis、shift-jisx0213、shift-jis-2004

  • 韓語:cp949、euc-kr、johab、iso-2022-kr

  • 添加了一些其他新編碼:HP Roman8、ISO_8859-11、ISO_8859-16、PCTP-154 和 TIS-620。

  • UTF-8 和 UTF-16 編解碼器現在可以更好地處理接收到的部分輸入。以前,StreamReader 類會嘗試讀取更多資料,從而無法從流中恢復解碼。現在,read() 方法將返回儘可能多的資料,並且將來的呼叫將從上次呼叫停止的位置恢復解碼。(由 Walter Dörwald 實現。)

  • 有一個新的 collections 模組,用於各種專門的集合資料型別。目前它只包含一種型別,deque,一個雙端佇列,支援從兩端高效地新增和刪除元素

    >>> from collections import deque
    >>> d = deque('ghi')        # make a new deque with three items
    >>> d.append('j')           # add a new entry to the right side
    >>> d.appendleft('f')       # add a new entry to the left side
    >>> d                       # show the representation of the deque
    deque(['f', 'g', 'h', 'i', 'j'])
    >>> d.pop()                 # return and remove the rightmost item
    'j'
    >>> d.popleft()             # return and remove the leftmost item
    'f'
    >>> list(d)                 # list the contents of the deque
    ['g', 'h', 'i']
    >>> 'h' in d                # search the deque
    True
    

    一些模組,例如 Queuethreading 模組,現在利用 collections.deque 來提高效能。(由 Raymond Hettinger 貢獻。)

  • ConfigParser 類已略有增強。read() 方法現在返回已成功解析的檔案列表,如果傳遞的 value 引數不是字串,則 set() 方法會引發 TypeError。(由 John Belmonte 和 David Goodger 貢獻。)

  • curses 模組現在支援 ncurses 擴充套件 use_default_colors()。在終端支援透明度的平臺上,這使得可以使用透明背景。(由 Jörg Lehmann 貢獻。)

  • difflib 模組現在包含一個 HtmlDiff 類,該類建立一個 HTML 表格,顯示文字的兩個版本的並排比較。(由 Dan Gass 貢獻。)

  • email 包已更新到 3.0 版本,該版本刪除了各種已棄用的 API 並移除了對 Python 2.3 之前版本的支援。該軟體包的 3.0 版本對 MIME 訊息使用新的增量解析器,該解析器可在 email.FeedParser 模組中使用。新解析器不需要將整個訊息讀取到記憶體中,並且如果訊息格式不正確也不會引發異常;相反,它會在訊息的 defect 屬性中記錄任何問題。(由 Anthony Baxter、Barry Warsaw、Thomas Wouters 和其他人開發。)

  • heapq 模組已轉換為 C。由此帶來的十倍速度提升使該模組適合處理大量資料。此外,該模組還有兩個新函式 nlargest()nsmallest(),它們使用堆來查詢資料集中的 N 個最大或最小值,而無需付出完全排序的代價。(由 Raymond Hettinger 貢獻。)

  • httplib 模組現在包含各種與 HTTP 相關的 RFC 文件中定義的 HTTP 狀態程式碼的常量。常量具有諸如 OKCREATEDCONTINUEMOVED_PERMANENTLY 等名稱;使用 pydoc 獲取完整列表。(由 Andrew Eland 貢獻。)

  • imaplib 模組現在支援 IMAP 的 THREAD 命令(由 Yves Dionne 貢獻)和新的 deleteacl()myrights() 方法(由 Arnaud Mazin 貢獻)。

  • itertools 模組獲得了一個 groupby(iterable[, *func*]) 函式。iterable 是可以迭代以返回元素流的東西,可選的 func 引數是一個接受元素並返回鍵值的函式;如果省略,則鍵只是元素本身。groupby() 然後將元素分組為具有匹配鍵值的子序列,並返回一系列包含鍵值和子序列迭代器的 2 元組。

    這是一個使其更清晰的示例。key 函式只是返回一個數字是偶數還是奇數,因此 groupby() 的結果是返回連續的奇數或偶數執行。

    >>> import itertools
    >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]
    >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):
    ...    print key_val, list(it)
    ...
    0 [2, 4, 6]
    1 [7]
    0 [8]
    1 [9, 11]
    0 [12, 14]
    >>>
    

    groupby() 通常與排序的輸入一起使用。groupby() 的邏輯類似於 Unix uniq 過濾器,這使其便於消除、計數或識別重複元素

    >>> word = 'abracadabra'
    >>> letters = sorted(word)   # Turn string into a sorted list of letters
    >>> letters
    ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']
    >>> for k, g in itertools.groupby(letters):
    ...    print k, list(g)
    ...
    a ['a', 'a', 'a', 'a', 'a']
    b ['b', 'b']
    c ['c']
    d ['d']
    r ['r', 'r']
    >>> # List unique letters
    >>> [k for k, g in groupby(letters)]
    ['a', 'b', 'c', 'd', 'r']
    >>> # Count letter occurrences
    >>> [(k, len(list(g))) for k, g in groupby(letters)]
    [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
    

    (由 Hye-Shik Chang 貢獻。)

  • itertools 還獲得了一個名為 tee(iterator, N) 的函式,該函式返回 N 個獨立的迭代器,這些迭代器複製 iterator。如果省略 N,則預設值為 2。

    >>> L = [1,2,3]
    >>> i1, i2 = itertools.tee(L)
    >>> i1,i2
    (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)
    >>> list(i1)               # Run the first iterator to exhaustion
    [1, 2, 3]
    >>> list(i2)               # Run the second iterator to exhaustion
    [1, 2, 3]
    

    請注意,tee() 必須保留迭代器返回的值的副本;在最壞的情況下,它可能需要保留所有值。因此,如果前導迭代器在長輸入流中遠遠領先於後導迭代器,則應謹慎使用此方法。如果分隔很大,那麼您不妨改用 list()。當迭代器彼此緊密跟蹤時,tee() 是理想的。可能的應用包括書籤、視窗或前瞻迭代器。(由 Raymond Hettinger 貢獻。)

  • locale 模組添加了許多函式,例如 bind_textdomain_codeset() 來指定特定的編碼和一系列 l*gettext() 函式,這些函式返回所選編碼的訊息。(由 Gustavo Niemeyer 貢獻。)

  • 為簡化日誌配置,logging 包的 basicConfig() 函式添加了一些關鍵字引數。預設行為是將訊息記錄到標準錯誤輸出,但可以透過指定各種關鍵字引數來記錄到特定檔案,更改日誌格式或設定日誌級別。例如:

    import logging
    logging.basicConfig(filename='/var/log/application.log',
        level=0,  # Log all messages
        format='%(levelname):%(process):%(thread):%(message)')
    

    logging 包的其他新增功能包括一個方便的 log(level, msg) 方法,以及一個 TimedRotatingFileHandler 類,該類會在定時的時間間隔輪換其日誌檔案。該模組已經有一個 RotatingFileHandler 類,該類在檔案超過特定大小時輪換日誌。這兩個類都派生自一個新的 BaseRotatingHandler 類,該類可用於實現其他輪換處理程式。

    (由 Vinay Sajip 實現的更改。)

  • marshal 模組現在在解包資料結構時共享駐留字串。這可能會縮小某些 pickle 字串的大小,但主要作用是使 .pyc 檔案顯著縮小。(由 Martin von Löwis 貢獻。)

  • nntplib 模組的 NNTP 類增加了 description()descriptions() 方法,用於檢索單個新聞組或一系列新聞組的描述。(由 Jürgen A. Erhard 貢獻。)

  • operator 模組添加了兩個新函式,attrgetter(attr)itemgetter(index)。這兩個函式都返回一個可呼叫物件,該物件接受一個引數並返回相應的屬性或項;當與 map()sorted() 一起使用時,這些可呼叫物件是極佳的資料提取器。例如:

    >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
    >>> map(operator.itemgetter(0), L)
    ['c', 'd', 'a', 'b']
    >>> map(operator.itemgetter(1), L)
    [2, 1, 4, 3]
    >>> sorted(L, key=operator.itemgetter(1)) # Sort list by second tuple item
    [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
    

    (由 Raymond Hettinger 貢獻。)

  • optparse 模組以各種方式進行了更新。該模組現在透過 gettext.gettext() 傳遞其訊息,從而可以對 Optik 的幫助和錯誤訊息進行國際化。選項的幫助訊息現在可以包含字串 '%default',該字串將被選項的預設值替換。(由 Greg Ward 貢獻。)

  • 長期計劃是在未來的某個 Python 版本中棄用 rfc822 模組,而支援 email 包。為此,email.Utils.formatdate 函式已更改為可作為 rfc822.formatdate() 的替代品使用。您可能需要考慮到這一點來編寫新的電子郵件處理程式碼。(由 Anthony Baxter 實現的更改。)

  • os 模組中添加了一個新的 urandom(n) 函式,該函式返回一個包含 n 個位元組隨機資料的字串。此函式提供了對特定於平臺的隨機性來源的訪問,例如 Linux 上的 /dev/urandom 或 Windows CryptoAPI。(由 Trevor Perrin 貢獻。)

  • 另一個新函式:如果 path 指定的檔案存在,則 os.path.lexists(path) 返回 true,無論它是否是符號連結。這與現有的 os.path.exists(path) 函式不同,如果 path 是指向不存在的目的地的符號連結,則該函式返回 false。(由 Beni Cherniavsky 貢獻。)

  • posix 模組中添加了一個新的 getsid() 函式,該模組是 os 模組的基礎。(由 J. Raynor 貢獻。)

  • poplib 模組現在支援透過 SSL 的 POP。(由 Hector Urtubia 貢獻。)

  • profile 模組現在可以分析 C 擴充套件函式。(由 Nick Bastin 貢獻。)

  • random 模組有一個名為 getrandbits(N) 的新方法,該方法返回長度為 N 位的長整數。現有的 randrange() 方法現在在適當的情況下使用 getrandbits(),從而更有效地生成任意大的隨機數。(由 Raymond Hettinger 貢獻。)

  • re 模組接受的正則表示式語言已擴充套件為簡單的條件表示式,寫為 (?(group)A|B)group 是一個數字組 ID 或一個在表示式前面用 (?P<group>...) 定義的組名。如果指定的組匹配,正則表示式模式 A 將針對字串進行測試;如果該組不匹配,則將使用模式 B。(由 Gustavo Niemeyer 貢獻。)

  • 感謝 Gustavo Niemeyer 的大量工作,re 模組也不再是遞迴的。在遞迴正則表示式引擎中,某些模式會導致消耗大量的 C 堆疊空間,並且可能導致堆疊溢位。例如,如果將一個包含 30000 個字元 a 的字串與表示式 (a|b)+ 匹配,則每個字元都會消耗一個堆疊幀。Python 2.3 嘗試檢查堆疊溢位並引發 RuntimeError 異常,但某些模式可能會繞過檢查,如果運氣不好,Python 可能會出現段錯誤。Python 2.4 的正則表示式引擎可以毫無問題地匹配此模式。

  • signal 模組現在對 signal.signal() 函式的引數執行更嚴格的錯誤檢查。例如,您不能在 SIGKILL 訊號上設定處理程式;以前版本的 Python 會靜默接受此操作,但 2.4 會引發 RuntimeError 異常。

  • socket 模組添加了兩個新函式。socketpair() 返回一對連線的套接字,而 getservbyport(port) 查詢給定埠號的服務名稱。(由 Dave Cole 和 Barry Warsaw 貢獻。)

  • sys.exitfunc() 函式已被棄用。程式碼應使用現有的 atexit 模組,該模組可以正確處理呼叫多個退出函式。最終,sys.exitfunc() 將成為一個純粹的內部介面,僅供 atexit 訪問。

  • 現在,tarfile 模組預設生成 GNU 格式的 tar 檔案。(由 Lars Gustäbel 貢獻。)

  • 現在,threading 模組提供了一種非常簡單的方法來支援執行緒區域性資料。該模組包含一個 local 類,其屬性值對於不同的執行緒是區域性的。

    import threading
    
    data = threading.local()
    data.number = 42
    data.url = ('www.python.org', 80)
    

    其他執行緒可以為 numberurl 屬性分配和檢索它們自己的值。您可以子類化 local 來初始化屬性或新增方法。(由 Jim Fulton 貢獻。)

  • 現在,timeit 模組在計時迴圈期間會自動停用週期性垃圾回收。此更改使連續計時更具可比性。(由 Raymond Hettinger 貢獻。)

  • 現在,weakref 模組支援更廣泛的物件,包括 Python 函式、類例項、集合、凍結集合、雙端佇列、陣列、檔案、套接字和正則表示式模式物件。(由 Raymond Hettinger 貢獻。)

  • 現在,xmlrpclib 模組支援多呼叫擴充套件,用於在單個 HTTP 操作中傳輸多個 XML-RPC 呼叫。(由 Brian Quinlan 貢獻。)

  • mpzrotorxreadlines 模組已被移除。

cookielib

cookielib 庫支援 HTTP Cookie 的客戶端處理,映象 Cookie 模組的伺服器端 Cookie 支援。Cookie 儲存在 cookie jar 中;該庫透明地將 Web 伺服器提供的 cookie 儲存在 cookie jar 中,並在連線到伺服器時從 jar 中獲取 cookie。與 Web 瀏覽器一樣,策略物件控制是否接受 cookie。

為了跨會話儲存 cookie,提供了 cookie jar 的兩種實現:一種以 Netscape 格式儲存 cookie,以便應用程式可以使用 Mozilla 或 Lynx cookie 檔案,另一種以與 Perl libwww 庫相同的格式儲存 cookie。

urllib2 已更改為與 cookielib 互動:HTTPCookieProcessor 管理一個 cookie jar,該 cookie jar 在訪問 URL 時使用。

此模組由 John J. Lee 貢獻。

doctest

感謝 Edward Loper 和 Tim Peters,doctest 模組進行了大量的重構。測試仍然可以像執行 doctest.testmod() 一樣簡單,但重構允許以各種方式自定義模組的操作

新的 DocTestFinder 類從給定物件的 docstring 中提取測試

def f (x, y):
    """>>> f(2,2)
4
>>> f(3,2)
6
    """
    return x*y

finder = doctest.DocTestFinder()

# Get list of DocTest instances
tests = finder.find(f)

新的 DocTestRunner 類然後執行單個測試,並可以生成結果摘要

runner = doctest.DocTestRunner()
for t in tests:
    tried, failed = runner.run(t)

runner.summarize(verbose=1)

上面的示例產生以下輸出

1 items passed all tests:
   2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.

DocTestRunner 使用 OutputChecker 類的例項來比較預期輸出和實際輸出。這個類接受許多自定義其行為的不同標誌;有抱負的使用者也可以編寫一個全新的 OutputChecker 子類。

預設的輸出檢查器提供了許多方便的功能。例如,使用 doctest.ELLIPSIS 選項標誌,預期輸出中的省略號(...)匹配任何子字串,從而更容易適應略有不同的輸出

def o (n):
    """>>> o(1)
<__main__.C instance at 0x...>
>>>
"""

另一個特殊字串 <BLANKLINE> 匹配一個空行

def p (n):
    """>>> p(1)
<BLANKLINE>
>>>
"""

另一個新功能是透過指定 doctest.REPORT_UDIFF(統一差異)、doctest.REPORT_CDIFF(上下文差異)或 doctest.REPORT_NDIFF(增量樣式)選項標誌來生成輸出的 diff 樣式顯示。例如

def g (n):
    """>>> g(4)
here
is
a
lengthy
>>>"""
    L = 'here is a rather lengthy list of words'.split()
    for word in L[:n]:
        print word

使用指定的 doctest.REPORT_UDIFF 執行上述函式的測試,您將獲得以下輸出

**********************************************************************
File "t.py", line 15, in g
Failed example:
    g(4)
Differences (unified diff with -expected +actual):
    @@ -2,3 +2,3 @@
     is
     a
    -lengthy
    +rather
**********************************************************************

構建和 C API 更改

以下是 Python 構建過程和 C API 的一些更改

  • 為擴充套件函式的常用返回值添加了三個新的便捷宏:Py_RETURN_NONEPy_RETURN_TRUEPy_RETURN_FALSE。(由 Brett Cannon 貢獻。)

  • 另一個新宏 Py_CLEAR,減少 obj 的引用計數並將 obj 設定為空指標。(由 Jim Fulton 貢獻。)

  • 一個新函式 PyTuple_Pack(N, obj1, obj2, ..., objN),從 Python 物件的變長引數列表構造元組。(由 Raymond Hettinger 貢獻。)

  • 一個新函式 PyDict_Contains(d, k),實現快速字典查詢,而不會遮蔽查詢過程中引發的異常。(由 Raymond Hettinger 貢獻。)

  • Py_IS_NAN(X) 宏返回 1,如果其 float 或 double 引數 X 是 NaN。(由 Tim Peters 貢獻。)

  • C 程式碼可以使用新的 PyEval_ThreadsInitialized() 函式來判斷是否已執行任何執行緒操作,從而避免不必要的鎖定。如果此函式返回 false,則不需要鎖定操作。(由 Nick Coghlan 貢獻。)

  • 一個新函式 PyArg_VaParseTupleAndKeywords()PyArg_ParseTupleAndKeywords() 相同,但接受 va_list 而不是多個引數。(由 Greg Chapman 貢獻。)

  • 新的方法標誌 METH_COEXIST,允許在槽中定義的函式與具有相同名稱的 PyCFunction 共存。這可以將諸如 set.__contains__() 之類的方法的訪問時間減半。(由 Raymond Hettinger 貢獻。)

  • 現在,Python 可以使用額外的分析功能進行構建,旨在幫助開發 Python 核心的人員。向 configure 指令碼提供 --enable-profiling 將允許您使用 gprof 分析直譯器,並提供 --with-tsc 開關啟用使用奔騰的時間戳計數器暫存器進行分析。請注意,--with-tsc 開關的命名略有不妥,因為分析功能也適用於 PowerPC 平臺,儘管該處理器架構不將該暫存器稱為“TSC 暫存器”。(由 Jeremy Hylton 貢獻。)

  • tracebackobject 型別已重新命名為 PyTracebackObject

特定於埠的更改

  • Windows 埠現在可以在 MSVC++ 7.1 以及 6 版本下構建。(由 Martin von Löwis 貢獻。)

移植到 Python 2.4

本節列出先前描述的可能需要更改程式碼的更改

  • 左移和過大的十六進位制/八進位制常量不再觸發 FutureWarning 並返回限制為 32 或 64 位的值;相反,它們返回長整數。

  • 整數運算將不再觸發 OverflowWarningOverflowWarning 警告將在 Python 2.5 中消失。

  • zip() 內建函式和 itertools.izip() 現在返回一個空列表,而不是在不帶引數呼叫時引發 TypeError 異常。

  • 您不能再比較 datedatetime 模組提供的例項。不同類的兩個例項現在將始終不相等,並且相對比較(<, >)將引發 TypeError

  • dircache.listdir() 現在將異常傳遞給呼叫者,而不是返回空列表。

  • LexicalHandler.startDTD() 過去接收公共 ID 和系統 ID 的順序錯誤。這已被糾正;依賴於錯誤順序的應用程式需要修復。

  • 如果省略了 mutate 引數且相關,fcntl.ioctl() 現在會發出警告。

  • tarfile 模組現在預設生成 GNU 格式的 tar 檔案。

  • 在匯入模組時遇到失敗不再在 sys.modules 中留下部分初始化的模組物件。

  • None 現在是一個常量;將新值繫結到名稱 None 的程式碼現在是語法錯誤。

  • signals.signal() 函式現在會為某些非法值引發 RuntimeError 異常;以前這些錯誤會靜默地傳遞。例如,您不能再在 SIGKILL 訊號上設定處理程式。

鳴謝

作者要感謝以下人員為本文的各種草稿提供建議、更正和幫助:Koray Can、Hye-Shik Chang、Michael Dyck、Raymond Hettinger、Brian Hurt、Hamish Lawson、Fredrik Lundh、Sean Reifschneider、Sadruddin Rejeb。