在 Python 2 中将 'b' 字符添加到字符串文字的等价函数是什么?

Jua*_*oto 3 python string binary

我可以对字符串变量应用什么函数,它会导致与b在字符串文字前添加修饰符的结果相同的结果?

我在这个问题中b读到了有关Python 2字符串文字修饰符的内容,该修饰符附加b到字符串使其成为字节字符串(主要是为了在使用 时 Python 2 和 Python 3 之间的兼容性2to3)。我想获得的结果是相同的,但应用于变量,如下所示:

def is_binary_string_equal(string_variable):
    binary_string = b'this is binary'
    return convert_to_binary(string_variable) == binary_string

>>> convert_to_binary('this is binary')
[1] True
Run Code Online (Sandbox Code Playgroud)

的正确定义是convert_to_binary什么?

aba*_*ert 5

首先,请注意在 Python 2.x 中,b前缀实际上什么都不做。b'foo''foo'都是完全相同的字符串文字。的b存在只是为了让你写的代码是既Python的2.X和Python 3.x的兼容:您可以使用b'foo',表示“我想在这两个版本字节”,并u'foo'表示“我想的Unicode两个版本”,并只是简单'foo'的意思是“我想要str两个版本中的默认类型,即使在 3.x 中是 Unicode,在 2.x 中是字节”。

因此,“在 Python 2 中将 'b' 字符添加到字符串文字的功能等价物”实际上什么都不做。

但是让我们假设您实际上有一个 Unicode 字符串(就像您从 Python 3 中的纯文字或文本文件中得到的一样,即使在 Python 2 中您只能通过显式解码或使用某些函数来获取这些字符串)你,就像用codecs.open)打开文件一样。因为这是一个有趣的问题。


简短的回答是:string_variable.encode(encoding)

但在你能做到这一点之前,你需要知道你想要什么编码。对于文字字符串,您不需要它,因为当您b在源代码中使用前缀时,Python知道您想要什么编码:与源代码文件相同的编码。并读取、输入用户类型、通过套接字传入的消息——可以是任何东西,而 Python 不知道;你必须告诉它。**

在许多情况下(特别是如果您使用的是最近的非 Windows 机器并处理本地数据),可以安全地假设答案是 UTF-8,因此您可以拼写convert_to_binary_string(string_variable)string_variable.encode('utf8'). 但“许多”并不是“全部”。*** 这就是文本编辑器和网络浏览器让用户选择编码的原因——因为有时只有用户真正知道。

* 请参阅PEP 263以了解如何指定编码以及为什么要这样做。

** 您也可以使用bytes(s, encoding),它是 的同义词s.encode(encoding)。而且,在这两种情况下,您都可以encoding省略参数——但它默认为比您实际想要的更可能是 ASCII 的东西,所以不要这样做。

*** 例如,许多较旧的网络协议被定义为 Latin-1。许多 Windows 文本文件都是以任何 OEM 字符集设置的形式创建的——在美国系统上通常是 cp1252,但还有数百种其他可能性。有时sys.getdefaultencoding()locale.getpreferredencoding()得到您想要的东西,但是当您处理某人上传的文件采用机器的首选编码而不是您的首选编码时,这显然不起作用。


在相关编码是“无论这个特定的源文件是什么”的特殊情况下,您几乎必须知道以某种方式带外。* 一旦脚本或模块被编译和加载,就不再可能告诉它最初是什么编码。**

但不应该有太多的理由想要那样。毕竟,如果两个二进制字符串相等,并且使用相同的编码,则 Unicode 字符串也相等,反之亦然,因此您可以将代码编写为:

def is_binary_string_equal(string_variable):
    binary_string = u'this is binary'
    return string_variable == binary_string
Run Code Online (Sandbox Code Playgroud)

*当然,默认值已记录在案——3.0 为 UTF-8,2.x 为 ASCII 或 Latin-1,具体取决于您的版本。但是你可以覆盖它,正如 PEP 263 解释的那样。

** 好吧,您可以使用该inspect模块来查找源,然后使用该importlib模块开始处理它,等等——但这只有在文件仍然存在并且自上次编译后未被编辑时才有效。