2017-01-01 42 views
0

這裏是一個控制檯演示:使用utf8時,爲什麼有些字符在使用pprint顯示時轉換爲 u表示法?

>>> x = "a b" 
>>> x 
'a\u200ab' 
>>> repr(x) 
"'a\\u200ab'" 

所以它似乎打印字符串確實pprint使用相同的技術。

不可否認,在與x綁定的初始值中的&b之間的空白字符實際上是U + 200a。但是,當使用UTF-8輸入和輸出編碼時,爲什麼要將任何字符轉換爲\ u表示法來輸出?

問題2當然是一個怎樣才能知道整個字符集是以哪種方式轉換的?

問題3當然是如何抑制這種行爲?

回答

1

我終於發現,解釋它的文檔。 從Python Unicode documentation

INT Py_UNICODE_ISPRINTABLE(Py_UNICODE CH)

Return 1 or 0 depending on whether ch is a printable character. Nonprintable characters are those characters defined in the Unicode character database as 「Other」 or 「Separator」, excepting the ASCII space (0x20) which is considered printable. (Note that printable characters in this context are those which should not be escaped when repr() is invoked on a string. It has no bearing on the handling of strings written to sys.stdout or sys.stderr.) 

這部分回答了第一個問題(事實,而不是原因),並導致確切的答案爲問題2

Unicode space separator characters

我想,視覺上毫不含糊的願望是事實的原因......所有這些分隔符都看起來「相同」(空格)。如果您正在檢查紙質日誌,但是如果在線檢查它,則複製/粘貼到十六進制顯示工具或This wonderfully helpful Unicode decoder當然是足夠的,而不會在使用哪個分隔符的細節時中斷文本的流動不重要(在我看來,這是非紙質時間的大部分)。創建海峽的一個子類有不同的再版(破壞現有的代碼)或用格式化功能創建pprint的子類,避免調用再版爲STR:

問題3顯然可以通過以下兩種方式之一來完成,但直接包含該值。

3

pprint打印您傳遞它的對象的表示形式。從the docs

的pprint模塊提供能力「漂亮地打印」任意 Python數據結構,其中可被用作輸入到 解釋的形式。

而且「它可以被用作輸入解釋一表」是指你的對象的表示,即它什麼方法__repr__回報。

如果要使用__str__方法而不是__repr__打印字符串,請不要使用pprint


下面是一個Python 3代碼片段會找出得到使用\u換碼代表字符:

for i in range(1500): 
    c = chr(i) 
    r = repr(c) 
    if r'\u' in r: 
     print('{0:4} {0:04x} {1} {2}'.format(i, r, c)) 

輸出

888 0378 '\u0378' ͸ 
889 0379 '\u0379' ͹ 
896 0380 '\u0380' ΀ 
897 0381 '\u0381' ΁ 
898 0382 '\u0382' ΂ 
899 0383 '\u0383' ΃ 
907 038b '\u038b' ΋ 
909 038d '\u038d' ΍ 
930 03a2 '\u03a2' ΢ 
1328 0530 '\u0530' ԰ 
1367 0557 '\u0557' ՗ 
1368 0558 '\u0558' ՘ 
1376 0560 '\u0560' ՠ 
1416 0588 '\u0588' ֈ 
1419 058b '\u058b' ֋ 
1420 058c '\u058c' ֌ 
1424 0590 '\u0590' ֐ 
1480 05c8 '\u05c8' ׈ 
1481 05c9 '\u05c9' ׉ 
1482 05ca '\u05ca' ׊ 
1483 05cb '\u05cb' ׋ 
1484 05cc '\u05cc' ׌ 
1485 05cd '\u05cd' ׍ 
1486 05ce '\u05ce' ׎ 
1487 05cf '\u05cf' ׏ 

注意,碼點> 0xFFFF的獲得代表必要時使用\U轉義碼。

for i in range(65535, 65600): 
    c = chr(i) 
    r = repr(c) 
    if r'\u' in r.lower(): 
     print('{0:4} {0:04x} {1} {2}'.format(i, r, c)) 

輸出

65535 ffff '\uffff' � 
65548 1000c '\U0001000c' 
65575 10027 '\U00010027' 
65595 1003b '\U0001003b' 
65598 1003e '\U0001003e' 
+0

聰明的編寫代碼來尋找他們,這可以很好地回答問題2,但不是其他問題。也許對完整列表的分析會給出線索。當然,如果代碼沒有被Unicode定義爲字符,那麼人們會希望\ u註釋,但是對於定義好的字符,我感到很驚訝。 – Victoria

+0

@Victoria \ x,\ u和\ u表示法在字符串的repr中使用時,您不應該感到驚訝。對象的repr必須是健壯且明確的。它被設計爲供程序員使用,例如在源代碼中直接在解釋器中使用。它不應該顯示給用戶:他們應該只看到使用字符串的__str__方法創建的正確格式化的輸出,例如'print(my_string)'顯示的內容。 –

+1

@維多利亞(續)有關此重要主題的更多信息,請參閱文檔中的__str__'與'__repr__'的討論,包括教程。另請參閱[這裏](http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python)和相關的鏈接頁面。 –

相關問題