在问这个问题时,我意识到我对原始字符串不太了解。对于自称是Django教练的人来说,这太糟糕了。
我知道什么是编码,我知道只有“u”才能做什么,因为我得到了什么是Unicode。
但“r”到底做什么?它会产生什么样的字符串?最重要的是,你到底在干什么?最后,有没有可靠的方法可以从Unicode字符串返回到简单的原始字符串?哦,顺便问一下,如果您的系统和文本编辑器字符集设置为UTF-8,那么您实际上做了什么吗?
在问这个问题时,我意识到我对原始字符串不太了解。对于自称是Django教练的人来说,这太糟糕了。
我知道什么是编码,我知道只有“u”才能做什么,因为我得到了什么是Unicode。
但“r”到底做什么?它会产生什么样的字符串?最重要的是,你到底在干什么?最后,有没有可靠的方法可以从Unicode字符串返回到简单的原始字符串?哦,顺便问一下,如果您的系统和文本编辑器字符集设置为UTF-8,那么您实际上做了什么吗?
当前回答
让我简单解释一下:在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不能与一个反斜杠存储一起工作的原因,但目前还没有人描述原因。我希望这是一个bug。
其他回答
让我简单解释一下:在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不能与一个反斜杠存储一起工作的原因,但目前还没有人描述原因。我希望这是一个bug。
“u”前缀表示值的类型为unicode而不是str。
带“r”前缀的原始字符串文本对其中的任何转义序列进行转义,因此len(r“\n”)为2。因为它们是转义序列,所以不能用一个反斜杠结束字符串文字:这不是有效的转义序列(例如r“\”)。
“Raw”不是类型的一部分,它只是表示值的一种方式。例如,“\\n”和r“\n”是相同的值,就像32、0x20和0b100000是相同的。
可以使用unicode原始字符串文字:
>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2
源文件编码只决定如何解释源文件,否则不会影响表达式或类型。但是,建议避免使用非ASCII编码会改变含义的代码:
使用ASCII(或UTF-8,对于Python 3.0)的文件不应有编码cookie。只有当注释或文档字符串需要提及需要拉丁-1的作者名称时,才应使用拉丁-1(或UTF-8);否则,使用\x、\u或\u转义是在字符串文本中包含非ASCII数据的首选方式。
Python 2中有两种字符串类型:传统的str类型和较新的unicode类型。如果键入一个字符串文本,前面没有u,则会得到存储8位字符的旧str类型,而前面有u,则得到可以存储任何unicode字符的新unicode类型。
r根本不改变类型,它只是改变字符串文本的解释方式。如果没有r,反斜杠将被视为转义字符。使用r时,反斜杠被视为文字。无论哪种方式,类型都是相同的。
ur当然是Unicode字符串,其中反斜杠是字面反斜杠,而不是转义码的一部分。
您可以尝试使用str()函数将Unicode字符串转换为旧字符串,但如果有任何Unicode字符无法在旧字符串中表示,则会出现异常。如果你愿意,你可以先用问号代替它们,但这当然会导致这些字符无法阅读。如果要正确处理unicode字符,建议不要使用str类型。
也许这是显而易见的,也许不是,但是您可以通过调用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
实际上没有任何“原始字符串”;有一些原始字符串文字,它们正好是在开头引号前用“r”标记的字符串文字。
“原始字符串文字”是字符串文字的一种稍有不同的语法,其中反斜杠\被视为“仅反斜杠”的意思(除非它正好在引号之前,否则会终止文字)——没有“转义序列”来表示换行符、制表符、退格符、表单提要等。在正常字符串文字中,每个反斜杠必须加倍,以避免作为转义序列的开始。
这种语法变体之所以存在,主要是因为正则表达式模式的语法中有大量的反斜杠(但永远不会在末尾,所以上面的“except”子句无关紧要),并且当您避免将它们中的每一个都加倍时,它看起来会更好一些——仅此而已。它还流行于表示本机Windows文件路径(使用反斜杠代替其他平台上的正斜杠),但这很少需要(因为通常的斜杠在Windows上也很好),而且不完美(由于上面的“except”子句)。
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对象占用了更多的内存空间(很明显,对于非常短的字符串,差异很小;-)。