在询问 this question 时,我意识到我对原始字符串知之甚少。对于自称是 Django 培训师的人来说,这很糟糕。
我知道什么是编码,而且我知道单独的 u''
做什么,因为我知道了什么是 Unicode。
但是 r'' 究竟做了什么?它会产生什么样的字符串?
最重要的是,你到底是做什么的?
最后,是否有任何可靠的方法可以从 Unicode 字符串返回到简单的原始字符串?
啊,顺便说一句,如果您的系统和文本编辑器字符集设置为 UTF-8,那么 u'' 实际上会执行任何操作吗?
实际上没有任何“原始字符串”;有原始的 字符串文字,它们正是在开始引号之前用 'r'
标记的字符串文字。
“原始字符串文字”与字符串文字的语法略有不同,其中反斜杠 \
被视为“只是一个反斜杠”(除非它出现在否则会终止文字的引号之前) -- 没有“转义序列”来表示换行符、制表符、退格符、换页符等。在普通字符串文字中,每个反斜杠必须加倍以避免被视为转义序列的开始。
这种语法变体的存在主要是因为正则表达式模式的语法带有大量反斜杠(但从不在末尾,因此上面的“except”子句无关紧要)并且当您避免将它们中的每一个加倍时,它看起来会更好一些 - - 就这样。表达本机 Windows 文件路径(使用反斜杠而不是其他平台上的常规斜杠)也获得了一定的普及,但这很少需要(因为普通斜杠在 Windows 上也能正常工作)并且不完美(由于“except”子句以上)。
r'...'
是字节字符串(在 Python 2.* 中),ur'...'
是 Unicode 字符串(同样,在 Python 2.* 中),其他三种引用中的任何一种也产生完全相同类型的字符串 (例如 r'...'
、r'''...'''
、r"..."
、r"""..."""
都是字节字符串,依此类推)。
不确定“返回”是什么意思 - 本质上没有前后方向,因为没有原始字符串类型,它只是表达完全正常的字符串对象、字节或 unicode 的另一种语法。
是的,在 Python 2.* 中,u'...'
is 当然总是与 '...'
不同——前者是 unicode 字符串,后者是字节字符串。可以用什么编码来表达文字是一个完全正交的问题。
例如,考虑(Python 2.6):
>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34
Unicode 对象当然会占用更多的内存空间(很明显,对于非常短的字符串来说差异非常小;-)。
python中有两种类型的字符串:传统的str
类型和较新的unicode
类型。如果您键入一个字符串文字,前面没有 u
,您会得到旧的 str
类型,它存储 8 位字符,而前面有 u
,您会得到新的 unicode
类型,可以存储任何 Unicode 字符.
r
根本不改变类型,它只是改变了字符串文字的解释方式。如果没有 r
,反斜杠将被视为转义字符。使用 r
,反斜杠被视为文字。无论哪种方式,类型都是相同的。
ur
当然是一个 Unicode 字符串,其中反斜杠是文字反斜杠,而不是转义码的一部分。
您可以尝试使用 str()
函数将 Unicode 字符串转换为旧字符串,但如果有任何 Unicode 字符无法在旧字符串中表示,则会出现异常。如果您愿意,可以先用问号替换它们,但这当然会导致这些字符不可读。如果要正确处理 unicode 字符,不建议使用 str
类型。
r"\"
是语法错误的原因。
'raw string' 表示按其出现的方式存储。例如,'\'
只是一个 反斜杠 而不是 转义。
“u”前缀表示该值的类型为 unicode
而不是 str
。
带有“r”前缀的原始字符串文字会转义其中的任何转义序列,因此 len(r"\n")
是 2。因为它们会转义转义序列,所以不能以单个反斜杠结束字符串文字:这不是有效的转义序列(例如r"\"
)。
“原始”不是类型的一部分,它只是表示值的一种方式。例如,"\\n"
和 r"\n"
是相同的值,就像 32
、0x20
和 0b100000
是相同的。
您可以使用 unicode 原始字符串文字:
>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2
源文件编码只是决定如何解释源文件,它不影响表达式或类型。但是,recommended 是为了避免使用 ASCII 以外的编码会改变含义的代码:
使用 ASCII(或 UTF-8,对于 Python 3.0)的文件不应该有编码 cookie。仅当注释或文档字符串需要提及需要 Latin-1 的作者姓名时,才应使用 Latin-1(或 UTF-8);否则,使用 \x、\u 或 \U 转义是在字符串文字中包含非 ASCII 数据的首选方式。
让我简单解释一下:在 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 不能与一个反斜杠存储一起使用,但原因还没有被任何人描述。我希望这是一个错误。
r'\'
是非法的,您甚至不能在任何字符串的尾部放置一个 '\'
。就像 r'xxxxxx\'
是一个非法字符串一样。
str
。在此处阅读更多内容以更好地理解:medium.com/better-programming/…
r'\'
按预期给出 SyntaxError: unterminated string literal
,并在以下位置注明:docs.python.org/3/reference/…:Even in a raw literal, quotes can be escaped with a backslash, but the backslash remains in the result...
@Jeyekomon 在另一个答案中也指出了这一点。
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 开始:
string ::= "'" stringitem* "'"
stringitem ::= stringchar | escapeseq
stringchar ::= <any source character except "\" or newline or the quote>
escapeseq ::= "\" <any source character>
很明显,包含裸引号字符的字符串文字(无论是否原始):'hello'world'
或以反斜杠结尾:'hello world\'
是无效的。
也许这很明显,也许不是,但是您可以通过调用 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
x is y
在 python3 中计算为 True?
x is y
由于实习而恰好评估为 True
的事实。而是使用 x == y
(如果您不检查 x 和 y 是否是存储在单个内存位置的完全相同的对象,即)。
u
和r
不可交换:ur'str'
有效,ru'str'
无效。 (至少在win7上的ipython 2.7.2中)r
字符串并注意到如果\
是最后一个字符,它将不会被视为文字而是转义结束引号,从而导致SyntaxError: EOL while scanning string literal
。因此,在任何以反斜杠结尾的字符串中,\\
仍然必须用于\
的最终实例。sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')
(带有 UTF8 语言的 Ubuntu 16.04)。同样,type('cioa') == type(r'cioa') == type(u'cioa')
。但是,原始字符串插值会有所不同,所以sys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')