781

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

我知道什么是编码,而且我知道u''单独做什么,因为我知道什么是 Unicode。

  • 但是具体r''做什么呢?它会产生什么样的字符串?

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

  • 最后,是否有任何可靠的方法可以从 Unicode 字符串返回到简单的原始字符串?

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

4

7 回答 7

802

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

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

这种语法变体的存在主要是因为正则表达式模式的语法带有大量反斜杠(但从不在末尾,因此上面的“except”子句无关紧要)并且当您避免将它们中的每一个加倍时,它看起来会更好一些 - - 就这样。表达本机 Windows 文件路径(使用反斜杠而不是其他平台上的常规斜杠)也获得了一定的普及,但这很少需要(因为普通斜杠在 Windows 上也能正常工作)并且不完美(由于“except”子句多于)。

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

不确定“返回”是什么意思 - 本质上没有前后方向,因为没有原始字符串类型,它只是表达完全正常的字符串对象、字节或 unicode 的另一种语法。

是的,在 Python 2.*u'...' ,当然总是与 just 不同'...'——前者是 unicode 字符串,后者是字节字符串。可以用什么编码来表达文字是一个完全正交的问题。

例如,考虑(Python 2.6):

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

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

于 2010-01-17T16:38:39.220 回答
206

python中有两种类型的字符串:传统str类型和新unicode类型。如果你输入一个没有u前面的字符串文字,你会得到str存储 8 位字符的旧类型,而u前面你会得到unicode可以存储任何 Unicode 字符的新类型。

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

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

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

于 2010-01-17T16:26:17.340 回答
70

“原始字符串”表示它按其出现的方式存储。例如,'\'只是一个反斜杠而不是转义.

于 2012-03-06T01:21:38.443 回答
39

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

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

第二种类型是UNICODE,它是python 中的unicode类型。Unicode 存储所有类型的语言。

默认情况下,python 更喜欢str类型,但如果你想以unicode类型存储字符串,你可以将u放在文本前面,如u'text'或者你可以通过调用unicode('text')来做到这一点

所以u只是调用函数将str转换为unicode的一种简短方法。就是这样!

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

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

现在,重要的部分:

您不能使用r存储一个反斜杠,这是唯一的例外。所以这段代码会产生错误:r'\'

要存储反斜杠(只有一个),您需要使用'\\'

如果您想存储超过 1 个字符,您仍然可以使用r,例如r'\\'会如您预期的那样产生 2 个反斜杠。

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

于 2015-08-25T21:01:29.890 回答
38

“u”前缀表示该值具有类型unicode而不是str.

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

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

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

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

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

使用 ASCII(或 UTF-8,对于 Python 3.0)的文件不应该有编码 cookie。仅当注释或文档字符串需要提及需要 Latin-1 的作者姓名时,才应使用 Latin-1(或 UTF-8);否则,使用 \x、\u 或 \U 转义是在字符串文字中包含非 ASCII 数据的首选方式。

于 2010-01-17T16:25:51.447 回答
14

Unicode 字符串文字

Unicode 字符串文字(以 为前缀的字符串文字u不再在 Python 3 中使用。它们仍然有效,但只是为了与 Python 2 兼容。

原始字符串文字

如果您想创建一个仅包含易于输入的字符(如英文字母或数字)的字符串文字,您只需输入它们:'hello world'. 但是,如果您还想包含一些更奇特的字符,则必须使用一些解决方法。解决方法之一是Escape 序列。例如,通过这种方式,您可以通过\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 仍然可以识别所有的转义序列,它只是不解释它们——而是让它们保持不变。这意味着原始字符串文字仍然必须是有效的字符串文字

从字符串文字的词法定义

string     ::=  "'" stringitem* "'"
stringitem ::=  stringchar | escapeseq
stringchar ::=  <any source character except "\" or newline or the quote>
escapeseq  ::=  "\" <any source character>

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

于 2019-07-23T14:15:42.707 回答
5

也许这很明显,也许不是,但是您可以通过调用x=chr(92)来创建字符串'\'

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
于 2017-05-15T07:37:24.807 回答