为什么 Python3 str(bytes) 转换为文字字符串 b'<str>'

我正在使用 python3。以下是解释问题的示例。


# python3

Python 3.6.8 (default, Sep 26 2019, 11:57:09) 

[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import sys

>>> sys.getdefaultencoding()

'utf-8'

>>> help(str)

 |  str(object='') -> str

 |  str(bytes_or_buffer[, encoding[, errors]]) -> str

 |  

 |  Create a new string object from the given object. If encoding or

 |  errors is specified, then the object must expose a data buffer

 |  that will be decoded using the given encoding and error handler.

 |  Otherwise, returns the result of object.__str__() (if defined)

 |  or repr(object).

 |  encoding defaults to sys.getdefaultencoding().

 |  errors defaults to 'strict'.


>>> d = b'abcd'

>>> type(d)

<class 'bytes'>

>>> print(d)

b'abcd'

>>> len(d)

4

>>> m = str(d)

>>> type(m)

<class 'str'>

>>> print(m)

b'abcd'

>>> len(m)

7

>>> m.encode()

b"b'abcd'"

>>> 

>>> m = str(d, encoding='utf-8')

>>> type(m)

<class 'str'>

>>> print(m)

abcd

>>> len(m)

4

>>> 

在帮助(str)中提到“编码默认为 sys.getdefaultencoding()”仍然 str(d)转换带有 b'' 的字符串。注意字符串的长度现在是 7。问题是,

  1. 为什么需要明确指定默认编码才能从字节中生成正确的字符串

  2. 如何回到字节 - 新类型是字符串。(对字符串进行编码将添加额外的 b)

  3. 有没有办法让 pylint 捕捉/警告这个问题。


慕尼黑8549860
浏览 135回答 4
4回答

慕后森

str()for与is forbytes相同,正是因为您最终不会滥用它。这是一个更复杂的示例,其中源字符串是表情符号。repr()bytes>>> s = "😸">>> len(s)1&nbsp; # One codepoint.>>> b = s.encode("utf-8")>>> len(b)4&nbsp; # Four bytes.>>> print(b)b'\xf0\x9f\x98\xb8'&nbsp; # Repr of the bytes, not to be interpreted.>>> print(repr(b))b'\xf0\x9f\x98\xb8'&nbsp; # Same as above!>>> s2 = b.decode("utf-8")&nbsp; # Decode back to string from bytes.>>> s == s2True>>>也就是说,使用str.encode()从字符串中获取字节,bytes.decode()从字节中获取字符串。

萧十郎

您不是将其用作转换函数(如在 C 和 C++ 中),而是将其用作值的str字符串表示形式(要打印,因此它可能与 不同)。repr()问题是二进制数组没有好的可打印字符串,所以我假设没有特定的str()函数,所以它退回到repr(),它添加了一些额外的注释(对于开发人员),比如前缀b'。在不知道编码的情况下,Python 无法将二进制数据转换为字符串。(二进制编码:在aASCII0x61中,字符串被解码:a表示a)。所以你可能想要d.decode('utf-8')。注意:系统编码是另一回事。它用于终端输入和输出,但不用于二进制数组,或从磁盘读取的一般数据。

ABOUTYOU

有没有办法让 pylint 捕捉/警告这个问题我认为 pylint 不会捕捉到它,但如果您愿意在代码中添加类型注释,mypy 会捕捉到它。如果使用 flag 执行实例, Python 将在实例str上调用时发出警告。bytes-b$ python3 -b -c 'str(b"a")'-c:1: BytesWarning: str() on a bytes instance请注意,警告只发出一次,AFAICT。如果使用 执行-bb,将引发异常。python3 -bb -c 'str(b"a")'Traceback (most recent call last):&nbsp; File "<string>", line 1, in <module>BytesWarning: str() on a bytes instance

小唯快跑啊

如果指定了编码 [..],则对象必须公开一个数据缓冲区,该缓冲区将使用给定的编码 [..] 进行解码。object.__str__()否则,返回(如果已定义)或的结果repr(object)。这几乎可以回答您的问题。如果您省略encoding参数,则repr(object)使用,这将导致"b'...'"作为结果字符串值。如果您确实提供了encoding参数,那么它将尝试使用该编码解码提供的对象。这是两个根本不同的操作:生成对象的字符串表示形式,这是非常安全的,不会真的失败。解码二进制对象,即尝试以某种方式解释其内容,这很可能会失败。这两个操作由两种不同的函数调用方式表示str。当您只希望执行 #1 时,您不希望隐式触发变体 #2 并有潜在的错误条件来处理一些隐式设置的全局值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python