“u”和“r”string标记究竟做什么,以及什么是原始string文字?
当问这个问题时 ,我意识到我对原始string的了解不多。 对于自称是Django教练的人来说,这很糟糕。
我知道什么是编码,而且我知道自己得到什么是Unicode。
但是, r
做了什么? 它会导致什么样的string?
而最重要的是,你到底做了什么?
最后,是否有任何可靠的方法从Unicodestring返回到一个简单的原始string?
嗯,顺便说一下,如果你的系统和你的文本编辑器字符集设置为UTF-8, u
真的做了什么?
没有任何“原始string ”; 有原始的string文字 ,正是在开始引号之前用'r'
标记的string文字。
一个“原始string文字”是一个string文字稍微不同的语法,其中一个反斜杠\
,被认为是“只是一个反斜杠”(除非它正好在一个引号之前,否则会终止文字)没有“转义序列”来表示换行符,制表符,退格符,表单提要等等。 在正常的string文字中,每个反斜杠必须加倍以避免被当作转义序列的开始。
这种语法变体的存在主要是因为正则expression式模式的语法是反斜杠(但从来没有在最后,所以上面的“except”子句并不重要),而且当你避免每一个都加倍时, – 就这样。 它也得到了一些stream行的expression本地Windows文件path(反斜杠,而不是像其他平台上的正常斜线),但这是非常less需要的(因为正常的斜线大多在Windows上工作正常)和不完善(由于“except”子句以上)。
r'...'
是一个字节string(在Python 2. *中), ur'...'
是一个Unicodestring(同样在Python 2. *中),而其他三种引用中的任何一种相同types的string(例如r'...'
, r'''...'''
, r"..."
, r"""..."""
都是字节串,如此)。
不确定“ 回头 ”是什么意思 – 没有内在的前后方向,因为没有原始的stringtypes ,它只是一个替代的语法来expression完全正常的string对象,字节或unicode,因为它们可能是。
是的,在Python 2. *中, u'...'
当然总是不同于'...'
– 前者是一个unicodestring,后者是一个字节string。 什么编码的文字可能会expression是一个完全正交的问题。
例如,考虑(Python 2.6):
>>> sys.getsizeof('ciao') 28 >>> sys.getsizeof(u'ciao') 34
Unicode对象当然需要更多的内存空间(对于一个非常短的string,显然是非常小的差异;-)。
Python中有两种types的string:传统的str
types和较新的unicode
types。 如果你在前面input一个没有u
的string,你将得到一个存储8位字符的旧的str
types,在前面你得到一个新的unicode
types,它可以存储任何Unicode字符。
r
根本不改变types,只是改变了string的解释方式。 没有r
,反斜杠被视为转义字符。 与r
,反斜杠被视为文字。 无论哪种方式,types是相同的。
ur
当然是一个Unicodestring,其中反斜杠是文字反斜杠,而不是转义代码的一部分。
您可以尝试使用str()
函数将Unicodestring转换为旧string,但是如果有任何unicode字符无法在旧string中表示,则会发生exception。 如果您愿意,可以先用问号replace它们,但当然这会导致这些字符不可读。 如果你想正确处理unicode字符,build议不要使用str
types。
'原始string'意味着它被存储。 例如,'\'只是一个反斜杠而不是转义。
“u”前缀表示该值具有typesunicode
而不是str
。
带有“r”前缀的原始string文字,转义其中的任何转义序列,因此len(r"\n")
是2.因为它们转义转义序列,所以不能用一个反斜杠结束string文字:那不是有效的转义序列(例如r"\"
)。
“原始”不是types的一部分,它只是表示价值的一种方式。 例如, "\\n"
和r"\n"
是相同的值,就像0b100000
和0b100000
是相同的。
你可以有unicode原始string文字:
>>> u = ur"\n" >>> print type(u), len(u) <type 'unicode'> 2
源文件编码只是决定如何解释源文件,否则不会影响expression式或types。 但是, build议避免使用ASCII以外的编码来改变含义的代码:
使用ASCII(或UTF-8,用于Python 3.0)的文件不应该有编码cookie。 只有当评论或文档string需要提及需要拉丁语-1的作者姓名时,才应使用Latin-1(或UTF-8); 否则,使用\ x,\ u或\ U转义是将非ASCII数据包含在string文本中的首选方式。
让我简单地解释一下:在Python 2中,可以将string存储为2种不同的types。
第一个是在Python中是strtypes的ASCII ,它使用1个字节的内存。 (256个字符,大部分会存储英文字母和简单符号)
第二种types是python中的unicodetypes的UNICODE ,它使用2个字节的内存。 (65536个字符,所以这包括地球上所有语言的所有字符)
默认情况下,python会更喜欢strtypes,但是如果你想以unicodetypes存储string,你可以把u放在文本前面,比如u'text',或者你可以通过调用unicode('text')来实现。
所以你只是一个简单的方法来调用一个函数来投送到Unicode 。 而已!
现在r部分,你把它放在文本的前面告诉计算机,文本是原始文本,反斜杠不应该是一个逃避字符。 r'\ n'不会创build新的行字符。 这只是包含2个字符的纯文本。
如果你想将str转换为unicode,并且在那里放入原始文本,请使用ur,因为ru会引发错误。
现在,重要的部分:
你不能使用r来存储一个反斜杠,这是唯一的例外。 所以这段代码会产生错误: r'\'
要存储一个反斜杠(只有一个),你需要使用'\\'
如果你想存储超过1个字符,你仍然可以像r'\'那样使用r,如你所期望的那样会产生2个反斜杠。
我不知道r为什么不能在一个反斜杠存储中工作的原因,但是原因还没有被任何人描述。 我希望这是一个错误。
也许这是显而易见的,也许不是,但你可以通过调用x = chr(92)来创buildstring'\'
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