“u”和“r”字符串前缀具体有什么作用?什么是原始字符串字面量?

881 投票
7 回答
685873 浏览
提问于 2025-04-15 18:07

在问了这个问题后,我意识到自己对原始字符串的了解不多。作为一个自称是Django培训师的人,这真是太糟糕了。

我知道什么是编码,也知道u''的作用,因为我明白Unicode是什么。

  • 但是r''到底是干什么的呢?它会生成什么样的字符串?

  • 最重要的是,ur''又是什么鬼?

  • 最后,有没有可靠的方法可以把Unicode字符串转换回简单的原始字符串?

  • 哦,对了,如果你的系统和文本编辑器的字符集设置为UTF-8,那么u''真的有用吗?

7 个回答

82

“原始字符串”的意思是它会按照显示的样子被存储。举个例子,'\' 就只是一个 反斜杠,而不是一个 转义字符

226

在Python 2中,有两种字符串类型:传统的 str 类型和更新的 unicode 类型。如果你输入一个字符串时没有在前面加 u,那么你得到的是旧的 str 类型,它只能存储8位字符;而如果在前面加上 u,你就得到了更新的 unicode 类型,它可以存储任何Unicode字符。

这里的 r 并不会改变字符串的类型,它只是改变了字符串的解释方式。如果没有 r,反斜杠会被当作转义字符来处理;而加上 r 后,反斜杠就会被当作普通字符来看待。无论如何,字符串的类型都是一样的。

ur 当然是一个Unicode字符串,其中的反斜杠是普通的反斜杠,而不是转义代码的一部分。

你可以尝试用 str() 函数把Unicode字符串转换成旧的字符串,但如果里面有任何不能用旧字符串表示的Unicode字符,你就会遇到错误。如果你愿意,可以先把这些字符替换成问号,但这样会导致这些字符变得不可读。如果你想正确处理Unicode字符,建议不要使用 str 类型。

886

其实没有什么“原始字符串”;只有“原始字符串字面量”,就是在开头加了一个'r'的字符串。

所谓“原始字符串字面量”,是一种稍微不同的字符串写法。在这种写法中,反斜杠\就表示“就是一个反斜杠”(除了在它后面跟着一个会结束字符串的引号时)——没有什么“转义序列”来表示换行、制表符、退格、分页等等。在普通字符串中,每个反斜杠必须写成两个反斜杠,以免被当成转义序列的开始。

这种语法的变化主要是因为正则表达式的模式中反斜杠用得很多(但它不会出现在最后,所以上面提到的“例外”就不重要了),这样写起来看起来更好看,不用每次都写两个反斜杠——就是这样。此外,它在表示Windows的文件路径时也变得有点流行(因为Windows用反斜杠,而其他平台用普通的斜杠),但这其实很少需要(因为普通斜杠在Windows上也大多数可以用)而且并不完美(因为上面提到的“例外”)。

r'...'在Python 2.*中是字节字符串,ur'...'是Unicode字符串(同样在Python 2.*中),其他三种引号的写法也会产生完全相同类型的字符串(比如r'...'r'''...'''r"..."r"""..."""都是字节字符串,依此类推)。

不太明白你说的“回到后面”是什么意思——其实没有什么本质上的前后方向,因为没有原始字符串类型,它只是表达普通字符串对象的一种替代语法,无论是字节字符串还是Unicode字符串。

而且在Python 2.*中,u'...'当然和'...'是有区别的——前者是Unicode字符串,后者是字节字符串。字面量可能用什么编码表示是一个完全不同的问题。

例如,考虑(Python 2.6):

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34

当然,Unicode对象会占用更多的内存空间(对于非常短的字符串来说,差别很小,显而易见;-)。

撰写回答