2010-07-03 36 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

相关问题