'b'字符在字符串文字前面做了什么?

Jes*_*ebb 724 python string unicode binary

显然,以下是有效的语法

my_string = b'The string'
Run Code Online (Sandbox Code Playgroud)

我想知道:

  1. 这是什么b字在前面的字符串是什么意思?
  2. 使用它有什么影响?
  3. 使用它的适当情况是什么?

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

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

而且,只是出于好奇,有没有比多符号bu是做其他事情?

dan*_*n04 597

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

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

如果您熟悉Java或C#,请考虑stras Stringbytesas byte[].如果您熟悉SQL,请考虑stras NVARCHARbytesas BINARYBLOB.如果您熟悉Windows注册表,请考虑stras REG_SZbytesas REG_BINARY.如果你熟悉C(++),那就忘记你所学到的一切char和字符串,因为一个字符不是字节.这个想法早已过时.

str想要表示文本时使用.

print('???? ????')
Run Code Online (Sandbox Code Playgroud)

您可以使用bytes,当你想表示相同结构的低级别的二进制数据.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]
Run Code Online (Sandbox Code Playgroud)

您可以编码一个str到一个bytes对象.

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'
Run Code Online (Sandbox Code Playgroud)

你可以解码bytes成一个str.

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'
Run Code Online (Sandbox Code Playgroud)

但你不能自由地混合这两种类型.

>>> 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
Run Code Online (Sandbox Code Playgroud)

b'...'表示法是因为它允许字节0x01-0x7F与ASCII字符,而不是十六进制数进行指定有点混乱.

>>> b'A' == b'\x41'
True
Run Code Online (Sandbox Code Playgroud)

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

>>> 'A' == b'A'
False
Run Code Online (Sandbox Code Playgroud)

在Python 2.x中

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

  • unicode= u'...'literals = Unicode字符序列= 3.x.str
  • str= '...'literals =混乱的字节/字符序列
    • 通常是文本,以某种未指定的编码进行编码.
    • 但也用于表示struct.pack输出等二进制数据.

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

所以是的,b'...'Python中的文字与PHP中的文字具有相同的目的.

另外,出于好奇,是否有更多符号而不是b和u做其他事情?

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

  • `'שלוםעולם'=='hello world'` (10认同)
  • 这比仅仅引用文档的接受答案要清楚得多.给我的文档没有意义,因此在文档中提供进一步的上下文是很棒的.谢谢! (6认同)
  • 谢谢!读完这些句子后我明白了:“为了简化 2.x 到 3.x 的转换,b'...' 文字语法被反向移植到 Python 2.6,以便区分二进制字符串(应该是 3.x 中的字节)来自文本字符串(在 3.x 中应该是 str)。b 前缀在 2.x 中没有任何作用,但告诉 2to3 脚本不要将其转换为 3.x 中的 Unicode 字符串。 (5认同)
  • 我可以提出修改建议吗?`但我必须强调,字符不是字节。`。你能在之后立即添加什么是字符吗?因为什么是角色的精确定义将有助于理解。 (4认同)
  • ''A'== b'A' - > False`检查*真的*清楚了.其余部分非常好,但到目前为止,我还没有正确理解字节字符串*不是真正的文本.* (3认同)
  • “字符不是字节”是 C++ 草案中错误的逻辑推论。C++从来没有那种“想法”。C++ 将字节定义为“足够大以容纳执行环境基本字符集的任何成员的数据存储的可寻址单元”。这就像说玻璃杯可以盛水一样。每个水都是一杯。 (3认同)
  • 除了`u`、`b`、`r`,Python 3.6 还引入了用于字符串格式化的f-string。示例`f'温度为{tmp_value}摄氏度'` (3认同)
  • +1 为 `.decode('UTF-8')`。正在搜索如何将通过服务器 POST 请求收到的 b' 字符串更改回 unicode。 (2认同)
  • b"some string".decode('UTF-8'),我相信很多人都在寻找 (2认同)

NPE*_*NPE 366

引用Python 2.x文档:

Python 2中忽略前缀'b'或'B'; 它表示文字应该成为Python 3中的字节文字(例如,当代码自动转换为2to3时).'u'或'b'前缀后面可以跟一个'r'前缀.

Python 3中的文件状态:

字节文字总是以'b'或'B'为前缀; 它们生成字节类型的实例而不是str类型.它们可能只包含ASCII字符; 数字值为128或更大的字节必须用转义表示.

  • 否则,这是一个已经理解它的人的答案。 (18认同)
  • 围绕引用的文档更简单的语言叙述将使这更好的答案恕我直言 (14认同)
  • 实际上,如果你从`__future__`导入`unicode_literals`,这将"反转"这个特定字符串的行为(在Python 2.x中) (7认同)
  • 所以听起来像Python <v3会忽略这个额外的角色.在v3中你需要使用ab字符串而不是常规字符串会是什么情况? (4认同)
  • @Gweebz - 如果您实际上是在特定编码中键入字符串而不是使用unicode转义(例如,b'\ xff\xfe\xe12'而不是'\ u32e1'). (4认同)

gec*_*cko 18

b表示字节串.

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

如果您有多字符串对象并且您使用了单个字符,则它将是一个字符串,并且根据编码,它可能超过1个字节.

如果用了1个字节与字节的字符串,你会得到从0-255一个8位的值,如果由于编码这些字符是> 1个字节它可能无法代表一个完整的字符.

TBH我会使用字符串,除非我有一些特定的低级别使用字节的原因.


小智 12

从服务器端,如果我们发送任何响应,它将以字节类型的形式发送,因此它将在客户端中显示为 b'Response from server'

为了摆脱,b'....'只需使用以下代码:

服务器文件:

stri="Response from server"    
c.send(stri.encode())
Run Code Online (Sandbox Code Playgroud)

客户端文件:

print(s.recv(1024).decode())
Run Code Online (Sandbox Code Playgroud)

然后它将打印 Response from server

  • @MichaelErickson 不,`b'x'` **不**“做`'x'.encode()`。它只是创建一个相同类型的值。如果你不相信我,请尝试评估`b '\u1000' == '\u1000'.encode()`。 (2认同)

Bil*_*lly 11

这个问题的答案是,它确实:

data.encode()
Run Code Online (Sandbox Code Playgroud)

并为了解码它(删除b,因为有时你不需要它)

用:

data.decode()
Run Code Online (Sandbox Code Playgroud)

  • *这是不正确的*。“字节”文字*在编译时*通过不同的机制进行解释;它们**不是**`data.encode()`调用的语法糖,**不是**在该过程中创建**,并且**不是**在`""`中解释文本相同**。特别是,例如 `b"\u1000"` **不会**创建​​一个表示任何有意义的编码*中的 Unicode 字符 `0x1000` 的 `bytes` 对象;它创建一个存储数值“[92, 117, 49, 48, 48, 48]”的“bytes”对象——对应于反斜杠、小写u、数字1和三个数字0。 (9认同)

xjc*_*jcl 10

除了其他人所说的,请注意 unicode 中的单个字符可以由多个字节组成

unicode 的工作方式是采用旧的 ASCII 格式(看起来像 0xxx xxxx 的 7 位代码)并添加多字节序列,其中所有字节都以 1 (1xxx xxxx) 开头来表示超出 ASCII 的字符,以便 Unicode向后-与 ASCII兼容

>>> len('Öl')  # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8')  # convert str to bytes 
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8'))  # 3 bytes encode 2 characters !
3
Run Code Online (Sandbox Code Playgroud)


Hat*_*ind 9

b"hello"不是一个字符串(尽管它看起来像一个),而是一个字节序列。它是一个由 5 个数字组成的序列,如果将它们映射到字符表,则该序列将类似于h e l l o。然而,值本身不是字符串,Python 只是有一种方便的语法,可以使用文本字符而不是数字本身来定义字节序列。这可以节省您的打字时间,而且字节序列通常被解释为字符。然而,情况并非总是如此 - 例如,读取 JPG 文件会在内部产生一系列无意义的字母,b"..."因为 JPG 具有非文本结构。

.encode().decode()在字符串和字节之间进行转换。


Ign*_*ams 8

它将其转换为bytes文字(或str2.x),并且对2.6+有效.

r前缀导致反斜杠需要"不解释"(不被忽略,差异确实物质).

  • 无论哪种方式都是2.x中的`str`,所以可以说它被忽略了.从`__future__`模块导入`unicode_literals`时,区别很重要. (2认同)

小智 8

这是一个例子,缺少'b'会在Python 3.x中抛出TypeError异常

>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface
Run Code Online (Sandbox Code Playgroud)

添加'b'前缀可以解决问题.


Kar*_*sai 6

您可以使用 JSON 将其转换为字典

import json
data = b'{"key":"value"}'
print(json.loads(data))
Run Code Online (Sandbox Code Playgroud)

{“核心价值”}


烧瓶:

这是烧瓶中的一个例子。在终端线上运行:

import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})
Run Code Online (Sandbox Code Playgroud)

在烧瓶/routes.py

@app.route('/', methods=['POST'])
def api_script_add():
    print(request.data) # --> b'{"hi":"Hello"}'
    print(json.loads(request.data))
return json.loads(request.data)
Run Code Online (Sandbox Code Playgroud)

{'核心价值'}