在问这个问题时,我意识到我对原始字符串不太了解。对于自称是Django教练的人来说,这太糟糕了。
我知道什么是编码,我知道只有“u”才能做什么,因为我得到了什么是Unicode。
但“r”到底做什么?它会产生什么样的字符串?最重要的是,你到底在干什么?最后,有没有可靠的方法可以从Unicode字符串返回到简单的原始字符串?哦,顺便问一下,如果您的系统和文本编辑器字符集设置为UTF-8,那么您实际上做了什么吗?
在问这个问题时,我意识到我对原始字符串不太了解。对于自称是Django教练的人来说,这太糟糕了。
我知道什么是编码,我知道只有“u”才能做什么,因为我得到了什么是Unicode。
但“r”到底做什么?它会产生什么样的字符串?最重要的是,你到底在干什么?最后,有没有可靠的方法可以从Unicode字符串返回到简单的原始字符串?哦,顺便问一下,如果您的系统和文本编辑器字符集设置为UTF-8,那么您实际上做了什么吗?
当前回答
Unicode字符串文字
Python 3中不再使用Unicode字符串文字(前缀为u的字符串文字)。它们仍然有效,但只是为了与Python 2兼容。
生字符串
如果你想创建一个字符串文字,它只包含英文字母或数字等容易键入的字符,你可以简单地键入它们:“helloworld”。但是,如果您还想包含一些更具异国情调的角色,则必须使用一些变通方法。
其中一个解决方法是Escape序列。这样,例如,只需在字符串文字中添加两个易于键入的字符,就可以在字符串中表示新行。因此,当您打印“hello\nworld”字符串时,单词将打印在单独的行上。这很方便!
另一方面,有时您可能希望在字符串中包含实际的字符\和n–您可能不希望它们被解释为新行。看看这些例子:
'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”或以反斜杠“helloworld\”结尾的字符串文本(原始或非原始)无效。
其他回答
Unicode字符串文字
Python 3中不再使用Unicode字符串文字(前缀为u的字符串文字)。它们仍然有效,但只是为了与Python 2兼容。
生字符串
如果你想创建一个字符串文字,它只包含英文字母或数字等容易键入的字符,你可以简单地键入它们:“helloworld”。但是,如果您还想包含一些更具异国情调的角色,则必须使用一些变通方法。
其中一个解决方法是Escape序列。这样,例如,只需在字符串文字中添加两个易于键入的字符,就可以在字符串中表示新行。因此,当您打印“hello\nworld”字符串时,单词将打印在单独的行上。这很方便!
另一方面,有时您可能希望在字符串中包含实际的字符\和n–您可能不希望它们被解释为新行。看看这些例子:
'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”或以反斜杠“helloworld\”结尾的字符串文本(原始或非原始)无效。
“原始字符串”意味着它按显示方式存储。例如,“\”只是反斜杠而不是转义。
让我简单解释一下:在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。
也许这是显而易见的,也许不是,但是您可以通过调用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
Python 2中有两种字符串类型:传统的str类型和较新的unicode类型。如果键入一个字符串文本,前面没有u,则会得到存储8位字符的旧str类型,而前面有u,则得到可以存储任何unicode字符的新unicode类型。
r根本不改变类型,它只是改变字符串文本的解释方式。如果没有r,反斜杠将被视为转义字符。使用r时,反斜杠被视为文字。无论哪种方式,类型都是相同的。
ur当然是Unicode字符串,其中反斜杠是字面反斜杠,而不是转义码的一部分。
您可以尝试使用str()函数将Unicode字符串转换为旧字符串,但如果有任何Unicode字符无法在旧字符串中表示,则会出现异常。如果你愿意,你可以先用问号代替它们,但这当然会导致这些字符无法阅读。如果要正确处理unicode字符,建议不要使用str类型。