Python 2.x中的字符串使用哪种编码?

时间:2018-04-20 11:52:41

标签: python string encoding python-2.x python-internals

python 2.x中用于编码字符串的默认编码是什么?我已经读过有两种方法可以声明字符串。

string = 'this is a string'
unicode_string = u'this is a unicode string'

第二个字符串是Unicode格式。 第一个字符串的编码是什么?

4 个答案:

答案 0 :(得分:10)

根据Python default/implicit string encodings and conversions(简明地叙述其Py2部分,以尽量减少重复):

实际上有多个独立的"默认" Python 2中的字符串编码,由其功能的不同部分使用。

  • 解析代码和字符串文字:

      来自文字的
    • str - 将包含文件中的原始字节,不进行转码
    • 来自文字的
    • unicode - 文件中的字节为decode&d;文件&#39; s "source encoding",默认为ascii < / LI>
    • with unicode_literals future,文件中的所有文字都被视为Unicode文字
  • 转码/类型转换:

    • str<->unicode类型转换,encode / decode w / o参数使用sys.getdefaultencoding()完成
      • 几乎总是ascii,因此任何国家字符都会导致UnicodeError
    • str只能是decode&#39; d和unicode - encode&#39; d。另外尝试将涉及隐式类型转换(具有上述结果)
  • I / O,包括print ing:

    • unicode - encode&#39; d <file>.encoding如果设置,则隐式转换为str(上述结果)
    • str - 将原始字节写入流,不进行转码。对于国家字符,终端将根据其区域设置显示不同的字形。

答案 1 :(得分:6)

字面答案是它们不一定代表任何特定的编码。在Python 2中,字符串只是一个字节数组,与Python 3中的bytes类型完全相同。对于字符串s,您可以调用s.decode()来获取Unicode字符串,但是出于这个原因,必须 *手动传递编码。您可以使用string来保存ASCII字节,或来自Windows code page 850(ASCII的超集)或UTF8字节甚至UTF16字节的字符。最后一种情况很有意思,因为即使该字符串中的字符在ASCII范围内,字节也与ASCII编码的版本不匹配(它们将与空字符交替)。 string类型甚至适用于某些二进制格式的字节,这些字节不对应于任何编码的字符串,例如图像文件的字节。

更实际的答案是通常使用ASCII。例如,文字字符串"xyz"将给出一个三字节字符串,其字节对应于这些字符的ASCII编码。

这种歧义是Python 3中字符串的行为和约定发生变化的原因。

*正如CristiFati的答案中所述,可以省略encoding= decode的{​​{1}}参数,在这种情况下,将假设ASCII。我的错误。

答案 2 :(得分:3)

正如@ArthurTacca在他的回答中所解释的那样,字符串("this is a string")只是一个字节数组(0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x61 0x20 0x73 0x74 0x72 0x69 0x6e 0x67),并且它的编码在解码上下文之外没有意义(当解释字节时)

尝试解码字符串时,默认情况下会将其解释为ascii(在 Python3 中为utf-8)。

查看[Python]: sys.getdefaultencoding()

>>> sys.version
'2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'
>>> sys.getdefaultencoding()
'ascii'
>>> "\xff".decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)

答案 3 :(得分:3)

第一个字符串没有编码。它是原始字节。向自己证明这一点的一种令人信服的方法是使用编码声明将用于解码源代码的编码更改为其他内容。通过这种方式,您可以明显地区分ASCII和字节。

将其保存到.py文件并执行:

# coding: rot13

s0 =  "this is a string"
s1 = o"this is a string"
s2 = h"guvf vf n fgevat"

nffreg s0 == s1 == s2
cevag s0
cevag s1
cevag s2

此来源以simple letter substitution cipher编码。 a-z A-Z中的字母被&#34;旋转&#34;由13个地方,其他字符不变。由于字母表中有26个字母,因此旋转两次是身份变换。请注意,编码声明本身不会轮换,如果您想了解原因,请参阅PEP 263

  • nffreg是一个断言声明,说这三个字符串都比较相等。
  • cevag是一份印刷声明。
  • s2是带有旋转的u前缀的unicode字符串。另外两个是字节串。

现在,让我们通过引入unicode文字__future__导入来更改第一个字符串的处理。请注意,必须轮换此future statement本身,否则您将收到语法错误。这会改变tokenizer / compiler组合处理第一个对象的方式,这一点很明显:

# coding: rot13
sebz __shgher__ vzcbeg havpbqr_yvgrenyf

s0 =  "guvf vf n fgevat"
s1 = o"this is a string"
s2 = h"guvf vf n fgevat"

nffreg s0 == s1 == s2
cevag s0
cevag s1
cevag s2

我们需要将文本从this is a string更改为guvf vf n fgevat,以使assert语句保持有效。 这表明第一个字符串没有编码。