在 Python 中, 字符串的类型可以归为三类: str,bytes,bytearray, 其中 str 和 bytes 是不可变类型, 而 bytearray 是可变类型. 由于 Python 2.X 和 Python 3.X 的区别, 相应的, 它们在 Python 2.X 和 Python 3.X 中有不同的意义.
在 Python 2.X 中, str 即可以表示 8bit 的文本(例如 ASCII 文本, Latin-1 文本), 也可以表示二进制数据, 也就是说, 在 Python 2.X 中, str 和 bytes 类型是等价的; 如果要表示 Unicode 文本, 需要单独使用 unicode 字符串; 而 bytearray 只有在 Python 2.6 中才有, 表示可以修改的 bytes 数据;
在 Python 3.X, str 表示 Unicode 文本, bytes 表示二进制数据, 二者不等价; bytearray 和 Python 2.X 中的意义一样, 也表示可以修改的 bytes 数据.
所有的的字符串问题, 包括读写文件, 都可以归纳为上述问题.
str,bytes 和 bytearray 相互转换
- 1 Python 2.X
- # str 与 bytes 等价
- >>>B = b'spam' # bytes 字面量
- >>>S = 'eggs' # str 字面量
- >>>type(B), type(S)
- (<type 'str'>, <type 'str'>)
- # str 与 unicode 的转换, 也即 bytes 与 unicode 的转换
- >>>str(u'spam') #unicode 转换为 str
- spam
- >>>unicode('spam') #str 转换为 unicode,unicode 函数可以选择编码, 默认是平台编码
- u'spam'
- # str 与 bytearray 的转换, 也即 bytes 与 bytearray 的转换
- >>>S = 'spam'
- >>>C = bytearray(S)
- >>>C
- bytearray(b'spam')
- 2 Python 3.X
- # str 与 bytes 的转换, 有两种方法:
- # 1 使用 str 类型的 encode 方法
- # 2 使用 bytes 函数
- >>>S = 'eggs'
- >>>S.encode()
- b'eggs'
- >>>bytes(S, encoding='ascii')
- b'eggs'
- # bytes 与 str 的转换, 有两种方法:
- # 1 使用 bytes 类型的 decode 方法
- # 2 使用 str 函数
- >>>B = b'spam'
- >>>B.decode()
- 'spam'
- >>>str(B, encode='asci')
- 'spam'
- # str 与 bytearray 的转换
- >>>S = 'spam'
- >>>C = bytearray(S, 'latin1') # 必须指明编码
- >>>C
- bytearray(b'spam')
- # bytes 与 bytearray 的转换
- >>>B = b'spam'
- >>>C = bytearray(B)
- >>>C
- bytearray(b'spam')
对于上面的由 bytes 转换为 str 的例子, 如果调用 str 函数不传递编码参数'ascii', 那么 str 函数并不是使用平台的默认编码, 而是返回 bytes 对象的一个 print string, 看例子就明白了:
- >>>B = b'spam'
- >>>str(B)
- "b'spam'"
字面量的表示方法
1 Pyhon 2.X
在 Python 2.X 中, 声明字面量可以使用前缀 b/B,u/U. 其中对于 Python 2.X 来说, 不使用前缀和使用前缀 b/B 的效果是一样的, 都表示 str(或者 bytes)类型, 如果要表示 unicode 字符串, 则必须带前缀 u/U.
2 Python 3.X
在 Python 3.X 中, 声明字面量可以使用 b/B,u/U 前缀. 其中, 对于 Python 3.X 来说, 不使用前缀和使用前缀 u/U 的效果是一样的, 都表示 str 类型(也即 unicode 字符串), 如果要表示 bytes 类型, 那么必须加前缀 b/B. 但是需要注意一点的就是, u/U 前缀在 Python 3.0 中不支持.
字面量中嵌入字符编码
Python 支持在字符串字面量中直接嵌入字符编码, 字符编码的形式可以为 \ xNN, 也可以是 \ uNNNN, 也可以是 \ UNNNNNNNN.
1 Python 2.X
由于 str 类型 (也即是 bytes 类型) 在 Python 2.X 中是 8bit 的, 因此只能使用 \ XNN 的形式; 对于 unicode 字符串, 可以使用上面三种形式:
- >>>S = '\x31' # 字符'1'的编码为 \ x31
- >>>S
- '1'
- >>>S = '\u0031' # \u 形式不支持
- >>>S
- '\\u0031'
- >>>S = '\U00000031' # \U 形式不支持
- >>>S
- '\\U00000031'
- >>>S = u'\x31'
- >>>S
- u'1'
- >>>S = u'\u0031'
- >>>S
- u'1'
- >>>S = '\U00000031'
- >>>S
- u'1'
- 2 Python 3.X
由于 Python 3.X 中 str 类型就是 unicod 的, 所以支持上述三种形式, 相反, Python 3.X 中的 bytes 类型只支持 \ xNN:
- >>>S = '\x31'
- >>>S
- '1'
- >>>S = '\u0031'
- >>>S
- '1'
- >>>S = '\U00000031'
- >>>S
- '1'
- >>>S = b'\x31'
- >>>S
- b'1'
- >>>S = b'\u0031' #不识别
- >>>S
- b'\\u0031'
- >>>S = b'\U00000031' #不识别
- >>>S
- b'\\U00000031'
为了进一步的理解, 我们可以使用 len 函数来看长度. 对于 Python 2.X 和 Python 3.X, 凡是打印出字符'1'的, 使用 len 计算长度都是 1, 凡是不识别的, 对于 \ u 形式, len 计算的长度是 6, 对于 \ U 形式, len 计算的长度是 10.
类型混用
1 Python 2.X
在 Python 2.X 中, 如果 unicode 字符串与 bytes 类型 (也即 str 类型) 混用, 如果 bytes 类型中只包含 ASCII 字符, 那么, Python 自动将 bytes 类型转换成 unicode 字符串:
- >>>u'ab' + 'cd'
- u'abcd'
- >>>u'ab' + 'cd\xef' # 含有非 ASCII 字符, 不支持
- UnicdoeDecodeError:'ascii' codec can't decode byte 0xef in position 2:orinal not in range(120)
- 2 Python 3.X
unicode 字符串与 bytes 类型混用, Python 不会自动转换, 必须手动转换成统一类型, 要么统一成 unicode 字符串, 要么统一成 bytes 类型.
来源: http://www.bubuko.com/infodetail-2638445.html