2016-04-21 56 views
2

unicode的範圍究竟有什麼預期的語義字符在正則表達式的範圍,如果範圍內的一個或兩個端點是BMP之外?我觀察到下面的輸入行爲在Python 2.7和3.5不同:Python的語義涉及星光層

import re 
bool(re.match(u"[\u1000-\U00021111]", "\u1234")) 

在我2.7我得到False,在3.5我得到True。後者對我有意義。前者或許是代理對\ud844\udd11扯到由於\U00021111,但即便如此,我不明白,因爲\u1000-\ud844應包括\u1234就好了。

  • 這是指定的地方?
  • 這是預期的行爲?
  • 這是否僅僅依賴於Python版本,或者還有關於UTF-16與UTF-32的編譯時標誌?
  • 有沒有一種方法可以獲得一致的行爲而不區分大小寫?
  • 如果案件的區別是不可避免的,條件是什麼令人興奮的?

回答

3

只需使用u前綴輸入字符串來告訴Python這是一個Unicode字符串:

>>> bool(re.match(u"[\u1000-\U00021111]", u"\u1234")) # <= See u"\u1234" 
True 

在Python 2.7,則需要每次處理它們時的字符串解碼爲Unicode。在Python 3中,默認情況下,所有字符串都是Unicode,它在docs中陳述。

+1

謝謝!我沒有注意到這一點,我感到很蠢。但是,根本問題仍然是:'bool(re.match(u「[u1000- \ U00021111]」,u「\ ueeee」))'仍然會給出不同的結果。我知道,在回答問題後編輯問題是一種不好的方式,這樣回答就不再適用了。無論如何,你可以跟我一起做,還是應該發佈一個新問題? – MvG

+0

請檢查[此Python 2.7 IDEONE演示](https://ideone.com/p9Jsgv)。 'print(bool(re.match(u「[\ u1000- \ U00021111]」,u「\ ueeee」)))'打印'True'。你的Python 2.7應該設置爲允許Unicode輸入(參見'# - * - coding:utf-8 - * - 'pragma)。 –

+2

@WiktorStribiżew'#coding:utf8'在這種情況下什麼都不做。它聲明瞭源文件本身的編碼,並且在該源中沒有非ASCII字符。 –

2

以下是我發現至今。

PEP 261已被Python 2.2接受的版本引入了編譯時標誌來構建unicode支持,使用窄UTF-16表示或廣泛的UTF-32字符表示。檢查hex(sys.maxunicode)len(u'\U00')以在運行時間區分這些:窄版本將報告最大值0xffff和長度2,寬度最大構建0x10ffff,長度爲1。 Python 3.3隱藏了Unicode字符串的實現細節,使得所有字符串都顯示爲UTF-32(實際上並沒有浪費太多的空間,除非必要)。因此,在3.3之前的狹窄構建會將星體平面上的代碼點分解爲代理對,並且將獨立的代理獨立地用於構建正則表達式和要匹配的字符串。或者至少我沒有發現相反的跡象。

由於Wiktor的指出,我的例子是平原愚蠢的,因爲我忘了u前綴,第二個字符串字面。因此,Python 2將解析這不是一個轉義序列,而是作爲一個字節字符串。這就解釋了爲什麼它看起來好像代碼沒有包含在該範圍內,即使考慮了代理對之後。

至於預期的行爲:因爲Python 3.3基於構建類型的區別應該變得過時。將每個代碼點作爲一個單元來處理,無論是哪一架飛機,都應該是Python 3的前進方向。但是,對於較窄版本的向後兼容性,對舊版本而言是一個矛盾的目標。

+0

Python 3.3使用靈活的Unicode表示(我認爲它不會隱藏實現,例如,一個寬的python構建 - 它正好相反:對於窄python構建中的非BMP字符,該抽象​​泄漏)。這是不明顯的爲什麼正則表達式模塊不能處理代理對。 – jfs

+0

@ J.F.Sebastian:我同意代理對*不能由re模塊處理,但我的觀察結果表明*沒有被處理。我猜想,這起初並不簡單,後來又退出了向後兼容。許多其他基於UTF-16的語言也是這樣做的:Java,JavaScript ......我不確定我理解你對抽象泄漏的觀點。但是我認爲在Python級別上3.3+和3.3之間應該沒有區別,儘管在擴展模塊級別上會有差異。這是你的意思嗎? – MvG

+2

我們達成了一致意見,但是存在一個微小的差別:你說:*「Python 3.3 **隱藏**實現細節」*,我說一個狹窄的python構建**暴露了**(缺陷)的實現。結果是一樣的,不同之處在於你放置了口音/壓力。 「抽象泄漏」意味着狹義的Python構建不尊重Unicode字符串是Python中的一系列Unicode代碼點(一個Unicode代碼點可能表示爲兩個代碼點(代理對))的概念。 – jfs