2010-07-03 37 views
98

我還在學習Python和我有一個疑問:爲什麼要在python中通過字符串聲明unicode?

在蟒蛇的2.6.x我通常聲明編碼文件頭這樣的(如PEP 0263

# -*- coding: utf-8 -*- 

在那之後,我的琴絃寫如往常:

a = "A normal string without declared Unicode" 

但是每當我看到一個python項目代碼,編碼沒有在頭上聲明。相反,它是這樣的每個字符串聲明:

a = u"A string with declared Unicode" 

有什麼區別?這是什麼目的?我知道Python 2.6.x默認設置ASCII編碼,但是它可以被頭聲明覆蓋,所以每個字符串聲明有什麼意義?

附錄:似乎我混淆了字符串編碼的文件編碼。感謝您的解釋:)

+4

'#編碼:utf8'足夠好,無需' - * - ' – jellyfish 2016-02-03 11:40:59

+0

@jellyfish我假設你想鍵入'#編碼:UTF -8'。 – 2017-12-07 20:30:34

+0

應該是'#coding = utf-8'。 https://www.python.org/dev/peps/pep-0263/ – 2017-12-18 22:24:51

回答

141

這是兩個不同的東西,正如其他人提及。

當您指定# -*- coding: utf-8 -*-時,您告訴Python您保存的源文件是utf-8。 Python 2的默認值是ASCII(對於Python 3,它是utf-8)。這隻會影響解釋器如何讀取文件中的字符。

一般來說,無論編碼是什麼,將高位Unicode字符嵌入文件可能不是最好的辦法;你可以使用字符串unicode轉義符,它們可以在任何一種編碼中工作。


當你聲明與前面一個u,像u'This is a string'一個字符串,它告訴Python的編譯器該字符串是Unicode,而不是字節。口譯員大多透明地處理這個問題;最明顯的區別是你現在可以在字符串中嵌入unicode字符(也就是說,u'\u2665'現在是合法的)。您可以使用from __future__ import unicode_literals使其成爲默認值。

這隻適用於Python 2;在Python 3中,缺省值是Unicode,並且您需要在前面指定一個b(如b'These are bytes',聲明一個字節序列)。

+0

感謝您的解釋!我將此設置爲接受,因爲它是最完整的一個:) – 2010-07-03 04:38:48

+2

Python 2的默認源編碼是** ascii **。 – 2010-07-03 05:35:22

+23

將高Unicode字符嵌入到文件中實際上是一個好主意。我懷疑非英語的用戶想要在他們的字符串中閱讀unicode escapes。 – 2010-07-03 05:40:27

10

這並沒有設置字符串的格式;它設置文件的格式。即使使用該標題,"hello"也是一個字節字符串,而不是Unicode字符串。爲了使它成爲Unicode,你將不得不在任何地方都使用u"hello"。標題只是讀取.py文件時使用什麼格式的提示。

+0

那時我錯了,我以爲他們是一樣的。所以使用unicode字符串是i18n? – 2010-07-03 03:51:23

+0

@Oscar:是的,大部分。如果你使用Django或其他網站創建網站,並且必須處理非ASCII字符的人,那麼這是另一種可能的用途。 – icktoofay 2010-07-03 05:34:38

19

正如其他人所說,# coding:指定源文件保存在其中的編碼。下面是一些例子來說明這一點:

保存在磁盤上爲CP437(我的控制檯編碼)的文件,但沒有宣佈編碼

b = 'über' 
u = u'über' 
print b,repr(b) 
print u,repr(u) 

輸出:

File "C:\ex.py", line 1 
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no 
encoding declared; see http://www.python.org/peps/pep-0263.html for details 

# coding: cp437文件輸出增加:

über '\x81ber' 
über u'\xfcber' 

起初,Python不知道編碼並抱怨非ASCII字符。一旦知道了編碼,字節串就會得到實際在磁盤上的字節。對於Unicode字符串,Python讀取\ x81,知道在cp437中是ü,並將其解碼爲Unicode碼點ü即U + 00FC。當打印字節字符串時,Python將十六進制值81直接發送到控制檯。當打印Unicode字符串時,Python正確地檢測到我的控制檯編碼爲cp437,並將Unicode ü轉換爲ü的cp437值。

下面是與申報,並保存在一個文件中會發生什麼UTF-8:

├╝ber '\xc3\xbcber' 
über u'\xfcber' 

在UTF-8,ü被編碼爲十六進制字節C3 BC,所以字節字符串包含這些字節,但Unicode字符串與第一個示例相同。 Python讀取兩個字節並正確解碼。 Python錯誤地打印了字節串,因爲它直接向我的cp437控制檯發送了代表ü的兩個UTF-8字節。

這裏,文件被宣佈CP437,但保存在UTF-8:

├╝ber '\xc3\xbcber' 
├╝ber u'\u251c\u255dber' 

字節串仍然有磁盤上的字節(UTF-8十六進制字節C3 BC),但解釋他們兩個cp437字符而不是單個UTF-8編碼字符。這兩個字符轉換爲Unicode代碼點,並且所有東西都打印錯誤。

+0

+1爲例子:) – 2010-07-03 12:01:18

0

如果你使用python 2,補充一點:from __future__ import unicode_literals

相關問題