"u"和"r"字符串标志究竟做了什么,以及什么是原始字符串文字?

e-s*_*tis 600 python unicode python-2.x rawstring

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

我知道编码是什么,而且我知道u''自从我得到什么是Unicode以来我们独自做了什么.

  • 但到底r''做了什么呢?它会产生什么样的字符串?

  • And above all, what the heck does ur'' do?

  • Finally, is there any reliable way to go back from a Unicode string to a simple raw string?

  • Ah, and by the way, if your system and your text editor charset are set to UTF-8, does u'' actually do anything?

Ale*_*lli 641

没有任何"原始字符串 "; 有原始字符串文字,它们正是'r'在开头引号之前标记的字符串文字.

"原始字符串文字"是字符串文字的略有不同的语法,其中反斜杠,\意思是"只是反斜杠"(除非它恰好在引用之前,否则将终止文字) - 否"转义序列"代表换行符,制表符,退格键,换页符等.在普通的字符串文字中,每个反斜杠必须加倍,以避免被视为转义序列的开始.

这种语法变体的存在主要是因为正则表达式模式的语法带有反斜杠(但从不在最后,所以上面的"except"子句无关紧要)并且当你避免将它们加倍时看起来好一点 - - 就这样.它也表达了一些流行来表达本机Windows文件路径(使用反斜杠而不是像其他平台上的常规斜杠),但这很少需要(因为正常的斜杠在Windows上工作得很好)并且不完美(由于"except"子句以上).

r'...'是一个字节串(在Python 2*),ur'...'是Unicode字符串(再次,在Python 2*),以及任何其他3种引用的也产生完全相同的类型字符串(因此,例如r'...',r'''...''',r"...",r"""..."""都是字节串,依此类推).

不确定你的意思是" 返回 " - 没有内在的前后方向,因为没有原始的字符串类型,它只是表达完全正常的字符串对象,字节或unicode的替代语法.

是的,在Python 2*,u'...' 当然总是从刚不同'...'-前者是一个unicode字符串,后者是一个字节的字符串.可以表达文字的编码是完全正交的问题.

例如,考虑(Python 2.6):

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34
Run Code Online (Sandbox Code Playgroud)

Unicode对象当然需要更多的内存空间(非常短的字符串的差别很小,显然;-).

  • 请注意,`u`和`r`不是可交换的:`ur'str'`有效,`ru'str'.不行.(至少在win7上的ipython 2.7.2中) (23认同)
  • 请注意,ru"C:\ foo\unstable"将失败,因为\ u是ru模式下的unicode转义序列.r模式没有\ u. (21认同)
  • 刚刚测试了`r`字符串并注意到如果`\`是最后一个字符,它不会被视为文字,而是转义结束引号,导致`SyntaxError:EOL,同时扫描字符串文字`.所以`\\`仍然必须用在以反斜杠结尾的任何字符串中```的最后一个实例. (5认同)
  • 理解"r"并不意味着任何类型或编码问题,它更简单. (4认同)
  • https://docs.python.org/2/reference/lexical_analysis.html#string-literals (4认同)
  • python 3.x - `sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')`(使用 UTF8 lang 的 Ubuntu 16.04)。类似地,`type('cioa') == type(r'cioa') == type(u'cioa')`。但是,原始字符串插值会产生影响,因此 `sys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')` (2认同)

Mar*_*ers 167

python中有两种类型的字符串:传统str类型和较新unicode类型.如果在没有u前面的情况下键入字符串文字,则会得到str存储8位字符的旧类型,并且u在前面可以获得unicode可以存储任何Unicode字符的较新类型.

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

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

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

  • 在原始字符串文字中,反斜杠不被视为文字,这就是"r"\"`是语法错误的原因. (6认同)
  • 仅适用于Python 2。 (4认同)

xia*_*ong 56

'raw string'表示它按照显示方式存储.例如,'\'只是反斜杠而不是转义.

  • ...除非它是字符串的最后一个字符,在这种情况下它确实会转义结束引号。 (12认同)

小智 34

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

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

"Raw"不是该类型的一部分,它只是表示价值的一种方式.例如,"\\n"r"\n"是相同的值,就像32,0x200b100000是相同的.

你可以有unicode原始字符串文字:

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2
Run Code Online (Sandbox Code Playgroud)

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

使用ASCII(或UTF-8,用于Python 3.0)的文件不应具有编码cookie.Latin-1(或UTF-8)只应在注释或docstring需要提及需要Latin-1的作者名称时使用; 否则,使用\ x,\ u或\ U转义是在字符串文字中包含非ASCII数据的首选方法.


off*_*555 29

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

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

第二种类型是UNICODE,它是python中的unicode类型,它使用2个字节的内存.(65536个字符,所以这包括地球上所有语言的所有字符)

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

所以只是调用一个函数将str转换unicode的简短方法.而已!

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

如果你想将str转换为unicode并将原始文本放在那里,请使用ur,因为ru会引发错误.

现在,重要的部分:

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

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

如果你想存储超过1个字符,你仍然可以使用rr'\\'将产生2个反斜杠,如你所料.

我不知道为什么r不适用于一个反斜杠存储,但其原因尚未被任何人描述.我希望这是一个bug.

  • 你会注意到`r'\'`是非法的,你甚至不能在任何字符串的尾部放一个`'\'`.就像`r'xxxxxx \'`是一个非法的字符串. (9认同)
  • @Krissh 所有 python 3 字符串都支持 Unicode。它的类型是“str”。阅读更多内容以更好地理解:https://medium.com/better-programming/strings-unicode-and-bytes-in-python-3-everything-you-always-wanted-to-know-27dc02ff2686 (2认同)

Jey*_*mon 12

Unicode 字符串文字

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

原始字符串文字

如果你想创建一个字符串组成的仅易键式字符,如英文字母或数字,你可以简单地输入他们:'hello world'。但是,如果您还想包含一些更奇特的字符,则必须使用一些解决方法。一种解决方法是转义序列。通过这种方式,您可以例如通过向\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.'
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以只在字符串文字前加上这样的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>
Run Code Online (Sandbox Code Playgroud)

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


小智 5

Maybe this is obvious, maybe not, but you can make the string '\' by calling 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
Run Code Online (Sandbox Code Playgroud)

  • @HabeebPerwad,那是因为 [_string interning_](http://guilload.com/python-string-interning/)。由于实习,你永远不应该依赖这样一个事实,即 `x is y` 恰好评估为 `True`。而是使用`x == y`(如果您不检查x 和y 是否与存储在单个内存位置的对象完全相同)。 (6认同)
  • `x is y` 在 python3 中评估为 True? (4认同)