"string"、b"string"、u"string" Python 2/3比较

17

我已经了解在Python 2.7中r"string"通常用于正则表达式模式,我也见过u"string",我认为是用于Unicode字符串。现在,在Python 3中我们看到了b"string"

我在不同的来源/问题中搜索了这些内容,例如What does a b prefix before a python string mean?,但很难看到Python中所有这些带有前缀的字符串的全局概述,特别是在Python 2与3之间的区别。

问题:您是否有一个记忆Python中具有前缀的不同类型字符串的经验法则?(或者也许有一张表,有一列针对Python 2,另一列针对Python 3?)

NB: 我读了几个问题+答案,但没有找到一个易于记忆的、包括所有前缀/ Python 2+3的比较


3
“Euhm, r"string" 不代表正则表达式,它代表的是‘原始字符串’。u"string" 代表Unicode字符串,而 b"string" 代表字节串。这些内容都在Python文档中有解释。一个经验法则是,字母与表示名称相同。 u 代表Unicode,b 代表bytes,r 代表原始字符串。在使用它们超过两次后您会逐渐习惯。同时在Python2和Python3之间也会有不同。” - Torxed
@Torxed 是的,但这些对于Python 2和3等版本是不同的,拥有一个易于参考的比较表将非常有用。 - Basj
@Torxed 我们经常在Python 2.7中使用u"string",而在Python 3中使用"string",当运行相同的代码时,因此有必要制作一张明确的比较表,显示不同的情况和不同版本2与3之间的差异。这比阅读Py2文档、阅读Py3文档、然后阅读几个问题+答案要容易得多,弄清楚2和3之间的区别在哪里。 - Basj
有太多要整理才能完整列出不同之处。而决定哪些内容对于备忘单来说重要,哪些不重要——这取决于每个人。为自己创建一份备忘单,用你理解的方式编写,使其实用。他们已经浏览了更改以及为何做出更改的原因。有数百篇文章在他们的论坛、邮件列表和文档站点描述了更改。每个不同方面都写在每个函数/定义的文档中,以便人们知道“旧语法”是什么。 - Torxed
4个回答

16
从Python文字字面量文档中:https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals 字节文字字面量总是以“b”或“B”为前缀;它们生成bytes类型的实例,而不是str类型。它们只能包含ASCII字符;带有数值大于或等于128的字节必须使用转义符表示。
字符串和字节文字字面量都可以选择以字母“r”或“R”作为前缀;这样的字符串称为原始字符串,并将反斜杠视为文字字符。因此,在字符串文字中,原始字符串中的'\\U'和'\\u'转义字符不特殊处理。由于Python 2.x的原始Unicode文字与Python 3.x的行为不同,“ur”语法不受支持。
具有“f”或“F”前缀的字符串文字是格式化字符串文字;请参见格式化的字符串文字。'f'可以与'r'组合,但不能与'b'或'u'组合,因此可能存在原始格式化字符串,但不存在格式化字节文字字面量。
所以:
- r 意味着 raw - b 意味着 bytes - u 意味着 unicode - f 意味着 format

rb 在 Python 2 中已经可用,它们在许多其他语言中也非常方便。

由于 Python 2 中的字符串字面值不是 unicode,因此创建了 u-strings 来支持国际化。从 Python 3 开始,u-strings 是默认的字符串类型,因此 "..." 的语义与 u"..." 相同。

最后,这些字符串类型中,只有 f-string 不受 Python 2 支持。


谢谢!你能否添加哪些是在2上可用的,哪些是在3上可用的?同时,将两者的默认值也加入其中可能会更有趣。例如,在2和3中,“string”的等效值分别是什么? - Basj

15
  1. u-strings 用于在 Python 2 中表示 Unicode。如果您使用的是现代应用程序,那么很可能应该将其忘记 —— 在 Python 3 中,默认字符串全部为 Unicode,如果您正在从 Python 2 迁移,则最可能使用 from __future__ import unicode_literals,这对于 Python 2 来说几乎是相同的。

  2. b-strings 用于原始字节 —— 不是“文本”,而只是字节流。很少作为源代码输入,而更常见地作为网络或低级别代码的结果 —— 读取二进制格式的数据,解包存档,使用加密库等。

    从 b 字符串转换到 str,可以通过以下方式完成:

  3. # python 3
    >>> 'hēllö'.encode('utf-8')
    b'h\xc4\x93ll\xc3\xb6'
    
    >>> b'h\xc4\x93ll\xc3\xb6'.decode()
    'hēllö'
    
    # python 2 without __future__
    >>> u'hēllö'.encode('utf-8')
    'h\xc4\x93ll\xc3\xb6'
    
    >>> 'h\xc4\x93ll\xc3\xb6'.decode('utf-8')
    u'h\u0113ll\xf6'  # this is correct representation
    
  4. r-strings 不是专门用于正则表达式的,它是“原始”字符串。与普通字符串字面值不同,r-字符串不会对转义字符给予任何特殊含义。例如,普通字符串'abc\n'长度为4,最后一个字符是特殊字符“换行符”。为了在字符串字面值中提供它,我们使用转义符\。对于原始字符串,r'abc\n'是长度为5的字符串,最后两个字符就是字面上的\n字符。通常会在以下两个地方经常看到原始字符串:

  • 正则表达式模式 —— 避免将转义字符与实际的特殊字符混淆

  • Windows系统的文件路径表示法,因为Windows系列使用\作为分隔符,普通字符串字面值看起来像'C:\\dir\\file''\\\\share\\dir',而原始字符串会更好:r'C:\dir\file'r'\\share\dir'

  1. 另一个值得注意的是f-strings,它在Python 3.6中诞生,是一种简单而强大的字符串格式化方式:
  • f'a equals {a} and b is {b}'会在运行时替换变量ab

谢谢!所以在Py2.7中,u"hello"严格等同于在Py3中的"hello" - Basj
2
是的。在 Python 2 中,您甚至可以使用 from __future__ import unicode_literals 进行编码,并且该模块中的所有 'hello' 都等同于 u'hello'。不过,“strictly” 的含义比较模糊。类型名称可能不同,某些方法可能会有所不同,但我们正在比较语言的不同主要版本,因此...它们大多数情况下是可以互换的。 - Slam

4

Python中只有两种字符串(或类似字符串的对象)。

第一种是“Unicode”字符串,它们是字符序列。 第二种是字节(或“字节串”),它们是0到255之间的整数序列,通常使用某些假定的编码(如ASCII或UTF-8,这是一种在字节流中编码Unicode字符的规范)来呈现文本。

在Python 2中,默认值"my string"是一个字节串。 前缀'u'表示“Unicode”字符串,例如u"my string"

在Python 3中,“Unicode”字符串成为默认值,因此"my string"等同于u"my string"。 要获取旧版Python 2字节串,可以使用前缀b"my string"(不适用于Python 3的最旧版本)。

还有两个前缀,但它们不影响字符串对象的类型,只影响其解释方式。 第一个是“原始”字符串,它不解释转义字符,如\n或\t。例如,原始字符串r"my_string\n"包含文字反斜杠和'n'字符,而"my_string\n"在行末包含换行符。

第二个是在Python 3的最新版本中引入的:具有前缀'f'的格式化字符串。在其中,花括号用于显示要解释的表达式。例如,在以下字符串中:

my_object = 'avocado'
f"my {0.5 + 1.0, my_object} string"

将被解释为"我的(1.5,鳄梨)字符串"(逗号创建了一个元组)。这种解释发生在读取代码时立即进行;字符串之后没有任何特殊之处。

最后,您可以使用多行字符串符号:

"""this is my
multiline
string"""

在Python 2中,如果您没有使用任何前缀或只使用了'r'前缀,则字符串为字节串;如果使用了'u'前缀,则为Unicode字符串。
在Python 3中,如果没有使用任何前缀或只使用了'r'、'f'和'u'的组合,则为Unicode字符串。如果使用了'b'前缀,则为字节串。显然不允许同时使用'b'和'u'前缀。

谢谢您的回答!所以按照经验法则,Py2的u"hello"等同于Py3的"hello",而Py2的"hello"等同于Py3的b"hello",对吗? - Basj
在Python 3.0到3.2版本中不支持'u'前缀,但在Python 3.3中重新引入了该前缀。在Python 2.6和2.7中也支持'b'前缀(但被忽略),这是为了与Python 3兼容而包含的。'f'前缀仅在Python 3.6中引入,并有可能进一步改进以消除某些限制。 - Andrew McLeod

2

这是我所观察到的(似乎得到其他答案的确认):

Python 2                       Python 3

-----------------------------------------------

"hello"                        b"hello"
b"hello"            <=>    
<type 'str'>                   <class 'bytes'>

-----------------------------------------------

u"hello"            <=>        "hello"
                               u"hello"
<type 'unicode'>               <class 'str'>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接