IT-Swarm.Net

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

显然,以下是有效的语法

my_string = b'The string'

我想知道:

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

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

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

另外,出于好奇,是否有比bu更多的符号来做其他事情?

603
Jesse Webb

引用 Python 2.x文档

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

Python 3文档 陈述:

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

312
NPE

Python 3.x 明确区分类型:

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

如果您熟悉Java或C#,请将str视为String,将bytes视为byte[]。如果您熟悉SQL,请将str视为NVARCHAR,将bytes视为BINARYBLOB。如果您熟悉Windows注册表,请将str视为REG_SZ,将bytes视为REG_BINARY。如果你熟悉C(++),那么就忘记你所学到的关于char和字符串的一切,因为 一个字符IS不是字节 。这个想法早已过时。

如果要表示文本,请使用str

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

如果要表示结构等低级二进制数据,请使用bytes

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

您可以 编码strbytes对象。

>>> '\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'...' literals = Unicode字符序列= 3.x str
  • str = '...' literals =混乱的字节/字符序列
    • 通常是文本,以某种未指定的编码进行编码。
    • 但也用于表示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而不是选项卡),三重引号'''...'''"""..."""允许多行字符串文字。

513
dan04

B表示字节串。

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

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

如果用一个字节字符串取1个字节,你将从0-255得到一个8位值,如果由于编码产生的字符大于1个字节,它可能不代表完整的字符。

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

15
gecko

它将其转换为bytes文字(或2.x中的str),并且对于2.6+有效。

r前缀导致反斜杠被“解释”(不被忽略,差异 确实 无关紧要)。

8
Ignacio Vazquez-Abrams

这是一个例子,缺少'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

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

7
user3053230

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

为了摆脱b'....'只需使用下面的代码服务器文件

stri="Response from server"    
c.send(stri.encode())

客户端文件

print(s.recv(1024).decode())

然后它会打印出来

服务器响应

6
Nani Chintha

除了别人所说的,请注意unicode中的单个字符可以包含多个字节

Unicode工作的方式是它采用旧的[ASCII格式(7位代码看起来像0xxx xxxx)并添加 多字节序列 其中所有字节以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
2
xjcl

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

import json
data = b'{"key":"value"}'
print(json.loads(data))

{“核心价值”}


烧瓶:

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

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

在flask/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)

{'核心价值'}

0
Karam Qusai