协慌网

登录 贡献 社区

字符串文字前的'b' 字符做什么?

显然,以下是有效的语法

my_string = b'The string'

我想知道:

  1. 字符串前面的b字符是什么意思?
  2. 使用它有什么作用?
  3. 在什么情况下可以使用它?

我在 SO 上找到了一个相关的问题 ,但是这个问题是关于 PHP 的,它指出b用于表示字符串是二进制的,与 Unicode 相反,Unicode 是使代码与 PHP 版本兼容的必需 < 6,当迁移到 PHP 6 时。我认为这不适用于 Python。

我确实在 Python 网站上找到了有关以相同语法使用u字符将字符串指定为 Unicode 的文档 。不幸的是,它在该文档的任何地方都没有提到b字符。

另外,出于好奇,是否还有比bu更多的符号可以执行其他操作?

答案

Python 3.x明确区分了两种类型:

  • str = '...'文字 = Unicode 字符序列(UTF-16 或 UTF-32,取决于 Python 的编译方式)
  • bytes = b'...'文字 = 八位字节序列(0 到 255 之间的整数)

如果您熟悉 Java 或 C#,则将str视为String并将bytes视为byte[] 。如果您熟悉 SQL,请将str视为NVARCHAR ,将bytes视为BINARYBLOB 。如果您熟悉 Windows 注册表,则将str视为REG_SZ ,将bytes视为REG_BINARY 。如果您熟悉 C(++),那么请忘记您所学到的关于char和 string 的所有知识,因为CHARACTER 并非 BYTE 。这个想法早已过时了。

要表示文本时,请使用str

print('שלום עולם')

当您要表示低级二进制数据(例如 struct)时,可以使用bytes

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]

您可以将str 编码bytes对象。

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'

您可以将bytes解码为str

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'

但是您不能随意混合使用这两种类型。

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str

b'...'表示法有些令人困惑,因为它允许使用 ASCII 字符而不是十六进制数字指定字节 0x01-0x7F。

>>> b'A' == b'\x41'
True

但是我必须强调, 字符不是字节

>>> 'A' == b'A'
False

在 Python 2.x 中

3.0 之前的 Python 版本在文本和二进制数据之间缺乏这种区别。相反,有:

  • unicode = u'...'文字 = Unicode 字符序列 = 3.x str
  • str = '...'文字 = 混杂字节 / 字符的序列
    • 通常是文本,以某种未指定的编码进行编码。
    • 而且还用于表示二进制数据,例如struct.pack输出。

为了简化从 2.x 到 3.x 的过渡,将b'...'文字语法反向移植到 Python 2.6,以允许从文本中区分二进制字符串(应为 3.x 中的bytes )。字符串(在 3.x 中应为str )。 b前缀在 2.x 中不执行任何操作,但告诉2to3脚本不要将其转换为 3.x 中的 Unicode 字符串。

因此,是的,Python 中的b'...'字面量与 PHP 中的目的相同。

另外,出于好奇,是否还有比 b 和 u 更多的符号可以执行其他操作?

r前缀创建原始字符串(例如, r'\t'是反斜杠 + t而不是制表符),并且三引号'''...'''"""..."""允许多行字符串文字。

引用Python 2.x 文档

在 Python 2 中,前缀'b' 或'B' 被忽略;它指示文字应在 Python 3 中变成字节文字(例如,当代码自动用 2to3 转换时)。前缀 “u” 或 “b” 后可以带有前缀“r”。

Python 3 文档指出:

字节字面量始终以 “b” 或 “B” 为前缀;它们产生字节类型的实例而不是 str 类型。它们只能包含 ASCII 字符;数值等于或大于 128 的字节必须用转义符表示。

b 表示字节字符串。

字节是实际数据。字符串是一种抽象。

如果您有多个字符的字符串对象并且使用了单个字符,则该字符串将是一个字符串,并且根据编码的不同,大小可能会超过 1 个字节。

如果使用 1 个字节和一个字节字符串,则您将获得 0-255 之间的单个 8 位值,并且如果由于编码而导致的那些字符大于 1 个字节,则它可能不表示完整的字符。

TBH 我将使用字符串,除非我有一些特定的低级原因要使用字节。