“u”和“r”字符串标志究竟做了什么,以及什么是原始字符串文字?

时间:2010-01-17 16:22:58

标签: python unicode python-2.x rawstring

在问this question时,我意识到我对原始字符串知之甚少。对于那些自称是Django训练师的人来说,这很糟糕。

我知道编码是什么,而且我知道单独使用u''是什么,因为我得到的是Unicode。

  • r''到底做了什么?它会产生什么样的字符串?

  • 最重要的是ur''做了什么?

  • 最后,有没有可靠的方法从Unicode字符串返回到简单的原始字符串?

  • 啊,顺便说一下,如果您的系统和文本编辑器字符集设置为UTF-8,u''实际上做了什么吗?

7 个答案:

答案 0 :(得分:595)

实际上并没有“raw string ”;有原始字符串文字,它们正是在开头引号之前用'r'标记的字符串文字。

“原始字符串文字”是字符串文字的略有不同的语法,其中反斜杠\被视为“只是反斜杠”(除非它出现在引号之前)否则终止文字) - 没有“转义序列”来表示换行符,制表符,退格键,换页符等。在普通的字符串文字中,每个反斜杠必须加倍,以避免被视为转义序列的开始。

这种语法变体的存在主要是因为正则表达式模式的语法很重,反斜杠(但从不在最后,因此上面的“except”子句并不重要)当你避免加倍时,它看起来好一点他们 - 就是这样。它也表达了一些流行来表达本机Windows文件路径(使用反斜杠而不是像其他平台上的常规斜杠),但这很少需要(因为正常的斜杠在Windows上工作得很好)并且不完美(由于“except”子句上文)。

r'...'是一个字节字符串(在Python 2. *中),ur'...'是一个Unicode字符串(同样,在Python 2. *中),并且其他三种引用中的任何一种也会产生完全相同类型的字符串(例如r'...'r'''...'''r"..."r"""..."""都是字节字符串,依此类推。)

不确定“go back ”是什么意思 - 没有内在的后退和前进方向,因为没有原始字符串 type ,它只是一种替代语法表达完全正常的字符串对象,字节或unicode,因为它们可能是。

是的,在Python 2. *中,u'...' 当然总是与'...'不同 - 前者是unicode字符串,后者是字节串。可以表达文字的编码是完全正交的问题。

例如,考虑(Python 2.6):

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

当然,Unicode对象需要更多的内存空间(非常短的字符串的差别非常小; - )。

答案 1 :(得分:156)

python中有两种类型的字符串:传统的str类型和较新的unicode类型。如果您在前面没有u的情况下键入字符串文字,则会获得存储8位字符的旧str类型,并且前面的u会获得较新的unicode可以存储任何Unicode字符的类型。

r根本不会更改类型,它只会更改字符串文字的解释方式。如果没有r,反斜杠将被视为转义字符。使用r,反斜杠被视为文字。无论哪种方式,类型都是相同的。

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

您可以尝试使用str()函数将Unicode字符串转换为旧字符串,但如果有任何unicode字符无法在旧字符串中表示,则会出现异常。如果您愿意,可以先用问号替换它们,但当然这会导致这些字符不可读。如果要正确处理unicode字符,建议不要使用str类型。

答案 2 :(得分:48)

'raw string'表示它按照显示的方式存储。例如,'\'只是反斜杠而不是转义

答案 3 :(得分:32)

“u”前缀表示值的类型为unicode,而不是str

带有“r”前缀的原始字符串文字会转义其中的任何转义序列,因此len(r"\n")为2.因为它们会转义转义序列,所以不能使用单个反斜杠结束字符串文字:这不是有效的转义序列(例如r"\")。

“Raw”不是该类型的一部分,它只是表示该值的一种方式。例如,"\\n"r"\n"是相同的值,就像320x200b100000一样。

您可以使用unicode原始字符串文字:

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2

源文件编码只确定如何解释源文件,否则不会影响表达式或类型。但是,recommended避免使用ASCII以外的编码改变含义的代码:

  

使用ASCII(或UTF-8,适用于Python 3.0)的文件不应具有编码cookie。 Latin-1(或UTF-8)只应在注释或docstring需要提及需要Latin-1的作者名称时使用;否则,使用\ x,\ u或\ U转义是在字符串文字中包含非ASCII数据的首选方法。

答案 4 :(得分:25)

让我简单解释一下: 在python 2中,您可以将字符串存储为2种不同的类型。

第一个是 ASCII ,它在python中是 str 类型,它使用1个字节的内存。 (256个字符,主要存储英文字母和简单符号)

第二种类型是 UNICODE ,它在python中是 unicode 类型,它使用2个字节的内存。 (65536个字符,所以这包括地球上所有语言的所有字符)

默认情况下,python会选择 str 类型,但如果您想将字符串存储在 unicode 类型中,则可以将 u 放在您可以通过 unicode(&#39; text&#39;)

来完成 u&#39; text&#39; 这样的文字

所以只是调用函数将 str 强制转换为 unicode 的简短方法。那就是它!

现在 r 部分,你把它放在文本前面告诉计算机文本是原始文本,反斜杠不应该是一个转义字符。 r&#39; \ n&#39; 不会创建换行符。它只是包含2个字符的纯文本。

如果您想将 str 转换为 unicode 并将原始文本放入其中,请使用 ur ,因为 ru 会引发错误。

现在,重要的部分:

您不能使用 r 存储一个反斜杠,它是唯一的例外。 因此,此代码会产生错误: r&#39; \&#39;

要存储反斜杠(只有一个),您需要使用&#39; \\&#39;

如果您想存储超过1个字符,您仍然可以使用 r ,例如 r&#39; \\&#39; 会产生2个反斜杠,如您所料。

我不知道为什么 r 不能使用一个反斜杠存储,但原因还没有被任何人描述。我希望这是一个错误。

答案 5 :(得分:4)

也许这很明显,也许不是,但你可以通过调用 x = chr(92) 来创建字符串&#39; \&#39; p>

x=chr(92)
print type(x), len(x) # <type 'str'> 1
y='\\'
print type(y), len(y) # <type 'str'> 1
x==y   # True
x is y # False

答案 6 :(得分:0)

Unicode字符串文字

Unicode字符串文字(以u为前缀的字符串文字)在Python 3中为no longer used。它们仍然有效,但在Python 2中为just for compatibility purposes

原始字符串文字

如果要创建仅由易于键入的字符(例如英文字母或数字)组成的字符串文字,则只需键入以下内容即可:'hello world'。但是,如果您还想包含一些其他奇特的字符,则必须使用一些解决方法。解决方法之一是Escape sequences。这样,例如,您只需在字符串文字中添加两个易于键入的字符\n,就可以在字符串中表示新行。因此,当您打印'hello\nworld'字符串时,单词将被打印在单独的行上。非常方便!

另一方面,在某些情况下,您想创建一个包含转义序列的字符串文字,但又不希望它们被Python解释。您希望它们原始。看下面的例子:

'New updates are ready in c:\windows\updates\new'
'In this lesson we will learn what the \n escape sequence does.'

在这种情况下,您可以在字符串文字前加上r字符,例如:r'hello\nworld',Python不会解释任何转义序列。字符串将完全按照您创建的样子打印。

原始字符串文字不是完全“原始”吗?

许多人期望原始字符串文字是原始的,这意味着“引号之间的任何内容都会被Python忽略” 。那是不对的。 Python仍然可以识别所有转义序列,只是不解释它们-而是使它们保持不变。这意味着原始字符串文字仍然必须是有效的字符串文字

Lexical definition的字符串文字:

shortstringitem ::=  shortstringchar | stringescapeseq
shortstringchar ::=  <any source character except "\" or newline or the quote>
stringescapeseq ::=  "\" <any source character>

根据词汇定义,很明显,包含裸引号字符'hello'world'或以反斜杠'hello world\'结尾的字符串文字(无论是否原始)都是无效的。