簡體   English   中英

“u”和“r”字符串前綴究竟做了什么,什么是原始字符串文字?

[英]What exactly do "u" and "r" string prefixes do, and what are raw string literals?

在問這個問題時,我意識到我對原始字符串知之甚少。 對於自稱是 Django 培訓師的人來說,這很糟糕。

我知道編碼是什么,而且我知道u''一個人做什么,因為我知道什么是 Unicode。

  • 但是r''到底做了什么? 它會產生什么樣的字符串?

  • 最重要的是,你到底在做ur''

  • 最后,是否有任何可靠的方法可以將 go 從 Unicode 字符串返回到簡單的原始字符串?

  • 啊,順便說一下,如果您的系統和文本編輯器字符集設置為u'' ,您真的會做任何事情嗎?

沒有真正的“原始字符串”; 有原始字符串文字,它們正是在開始引號之前用'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 對象當然需要更多的內存空間(對於很短的字符串來說差別很小,顯然 ;-)。

python中有兩種類型的字符串:傳統的str類型和較新的unicode類型。 如果你輸入一個沒有u前面的字符串文字,你會得到舊的str類型,它存儲 8 位字符,而u前面你會得到可以存儲任何 Unicode 字符的較新的unicode類型。

r根本不改變類型,它只是改變字符串文字的解釋方式。 沒有r ,反斜杠被視為轉義字符。 使用r ,反斜杠被視為文字。 無論哪種方式,類型都是相同的。

ur當然是一個 Unicode 字符串,其中反斜杠是文字反斜杠,而不是轉義碼的一部分。

您可以嘗試使用str()函數將 Unicode 字符串轉換為舊字符串,但是如果舊字符串中存在無法表示的任何 unicode 字符,則會出現異常。 如果您願意,您可以先用問號替換它們,但這當然會導致這些字符不可讀。 如果要正確處理 unicode 字符,不建議使用str類型。

'raw string'意味着它在它出現時被存儲。 例如, '\\'只是一個反斜杠而不是轉義.

“u”前綴表示該值的類型為unicode而不是str

帶有“r”前綴的原始字符串文字轉義其中的任何轉義序列,因此len(r"\\n")是 2。因為它們轉義序列,您不能用單個反斜杠結束字符串文字:那不是一個有效的轉義序列(例如r"\\" )。

“原始”不是類型的一部分,它只是表示值的一種方式。 例如, "\\\\n"r"\\n"是相同的值,就像320x200b100000是相同的。

您可以使用 unicode 原始字符串文字:

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2

源文件編碼僅決定如何解釋源文件,否則不會影響表達式或類型。 但是,建議避免使用 ASCII 以外的編碼會改變含義的代碼:

使用 ASCII(或 UTF-8,對於 Python 3.0)的文件不應有編碼 cookie。 僅當評論或文檔字符串需要提及需要 Latin-1 的作者姓名時才應使用 Latin-1(或 UTF-8); 否則,使用 \\x、\\u 或 \\U 轉義是在字符串文字中包含非 ASCII 數據的首選方法。

讓我簡單解釋一下:在 python 2 中,您可以將字符串存儲為 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不能與一個反斜杠存儲一起使用的原因,但尚未有人描述原因。 我希望這是一個錯誤。

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.'

在這種情況下,您可以像這樣使用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'或以反斜杠結尾: '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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM