Chính xác thì những gì các chuỗi cờ của Uv và và rv làm gì, và chuỗi ký tự thô là gì?


652

Trong khi hỏi câu hỏi này , tôi nhận ra tôi không biết nhiều về chuỗi thô. Đối với ai đó tự xưng là huấn luyện viên Django, điều này thật tệ.

Tôi biết mã hóa là gì và tôi biết u''một mình làm gì vì tôi nhận được Unicode là gì.

  • Nhưng những gì r''làm chính xác? Nó dẫn đến loại chuỗi nào?

  • Và trên hết, cái quái ur''gì làm?

  • Cuối cùng, có cách nào đáng tin cậy để quay lại từ chuỗi Unicode thành chuỗi thô đơn giản không?

  • À, và nhân tiện, nếu hệ thống và bộ biên tập văn bản của bạn được đặt thành UTF-8, u''thực sự có làm gì không?

Câu trả lời:


683

Không thực sự có bất kỳ " chuỗi thô " nào; có các chuỗi ký tự thô , chính xác là các chuỗi ký tự được đánh dấu bởi một 'r'trước khi trích dẫn mở đầu.

Một "chuỗi ký tự thô" là một cú pháp hơi khác nhau đối với một chuỗi ký tự, trong đó một dấu gạch chéo ngược, \được hiểu là "chỉ một dấu gạch chéo ngược" (ngoại trừ khi nó xuất hiện ngay trước một trích dẫn có thể chấm dứt nghĩa đen) - không "Trình tự thoát" để thể hiện các dòng mới, tab, khoảng cách, nguồn cấp dữ liệu, v.v. Trong các chuỗi ký tự thông thường, mỗi dấu gạch chéo ngược phải được nhân đôi để tránh bị bắt làm chuỗi bắt đầu.

Biến thể cú pháp này tồn tại chủ yếu là do cú pháp của các mẫu biểu thức chính quy nặng nề với dấu gạch chéo ngược (nhưng không bao giờ ở cuối, vì vậy mệnh đề "ngoại trừ" ở trên không thành vấn đề) và có vẻ tốt hơn một chút khi bạn tránh nhân đôi mỗi trong số chúng - - đó là tất cả. Nó cũng được phổ biến để thể hiện đường dẫn tệp Windows gốc (với dấu gạch chéo ngược thay vì dấu gạch chéo thông thường như trên các nền tảng khác), nhưng điều đó rất hiếm khi cần (vì các dấu gạch chéo thông thường cũng hoạt động tốt trên Windows) và không hoàn hảo (do mệnh đề "ngoại trừ" ở trên).

r'...'là một chuỗi byte (bằng Python 2. *), ur'...'là một chuỗi Unicode (một lần nữa, bằng Python 2. *), và một trong ba loại khác trích dẫn cũng sản xuất một cách chính xác các loại tương tự của chuỗi (ví dụ như vậy r'...', r'''...''', r"...", r"""..."""là tất cả các chuỗi byte, v.v.).

Không chắc chắn ý của bạn là gì khi " quay lại " - về bản chất không có hướng quay lại và chuyển tiếp, bởi vì không có kiểu chuỗi thô , nó chỉ là một cú pháp thay thế để diễn tả các đối tượng chuỗi hoàn toàn bình thường, byte hoặc unicode như chúng có thể.

Và vâng, bằng Python 2. *, u'...' dĩ nhiên luôn luôn khác biệt với chỉ '...'- cựu là một chuỗi unicode, sau này là một chuỗi byte. Những gì mã hóa theo nghĩa đen có thể được thể hiện là một vấn đề hoàn toàn trực giao.

Ví dụ: xem xét (Python 2.6):

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34

Tất nhiên, đối tượng Unicode chiếm nhiều dung lượng bộ nhớ hơn (sự khác biệt rất nhỏ đối với một chuỗi rất ngắn, rõ ràng ;-).


6
Hiểu "r" không ngụ ý bất kỳ vấn đề về loại hoặc mã hóa nào, nó đơn giản hơn nhiều.
e-satis

23
Lưu ý rằng ru "C: \ foo \ không ổn định" sẽ thất bại vì \ u là chuỗi thoát unicode trong chế độ ru. Chế độ r không có \ u.
Curtis Yallop

26
Lưu ý rằng urkhông giao hoán: ur'str'công trình, ru'str'không. (ít nhất là trong ipython 2.7.2 trên win7)
RafiK

7
Chỉ cần kiểm tra các rchuỗi và nhận thấy rằng nếu \ là ký tự cuối cùng, nó sẽ không được coi là một nghĩa đen mà thay vào đó thoát khỏi trích dẫn kết thúc, gây ra SyntaxError: EOL while scanning string literal. Vì vậy, \\ vẫn phải được sử dụng cho trường hợp cuối cùng \ trong bất kỳ chuỗi nào kết thúc bằng dấu gạch chéo ngược.
Enteleform

1
python 3.x - sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(Ubuntu 16.04 với lang UTF8). Tương tự , type('cioa') == type(r'cioa') == type(u'cioa'). NHƯNG, phép nội suy chuỗi thô tạo ra sự khác biệt, vì vậysys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Darren Weber

177

Có hai loại chuỗi trong python: strloại truyền thống và unicodeloại mới hơn . Nếu bạn nhập một chuỗi ký tự mà không có uphía trước, bạn sẽ có strloại cũ lưu trữ các ký tự 8 bit và uở phía trước, bạn sẽ nhận được unicodeloại mới hơn có thể lưu trữ bất kỳ ký tự Unicode nào.

Các rkhông thay đổi kiểu nào cả, nó chỉ thay đổi cách các chuỗi chữ được giải thích. Không có r, dấu gạch chéo ngược được coi là ký tự thoát. Với r, dấu gạch chéo ngược được coi là nghĩa đen. Dù bằng cách nào, loại là như nhau.

ur tất nhiên là một chuỗi Unicode trong đó dấu gạch chéo ngược là dấu gạch chéo ngược theo nghĩa đen, không phải là một phần của mã thoát.

Bạn có thể thử chuyển đổi một chuỗi Unicode thành một chuỗi cũ bằng cách sử dụng str()hàm, nhưng nếu có bất kỳ ký tự unicode nào không thể được biểu diễn trong chuỗi cũ, bạn sẽ có một ngoại lệ. Bạn có thể thay thế chúng bằng dấu chấm hỏi trước nếu bạn muốn, nhưng tất nhiên điều này sẽ khiến những ký tự đó không thể đọc được. Không nên sử dụng strloại nếu bạn muốn xử lý chính xác các ký tự unicode.


Cảm ơn, chấp nhận. Như tôi đã nói, tôi đã hiểu được unicode là gì, tôi không biết "r" nghĩa là gì và sự kết hợp của "u" và "r" là gì. Tôi biết rõ hơn, chúc mừng.
e-satis

6
Dấu gạch chéo ngược không được coi là bằng chữ trong chuỗi ký tự thô, đó là lý do tại sao r"\"là lỗi cú pháp.

4
Chỉ áp dụng cho Python 2.
PaulMcG

60

'chuỗi thô' có nghĩa là nó được lưu trữ khi nó xuất hiện. Ví dụ, '\'chỉ là dấu gạch chéo ngược thay vì thoát .


3
... Trừ khi đó là ký tự cuối cùng của chuỗi, trong trường hợp đó, nó thoát khỏi dấu ngoặc kép.
18:30

36

Một tiền tố "u" biểu thị giá trị có loại unicodechứ không phải str.

Các chuỗi ký tự thô, với tiền tố "r", thoát khỏi bất kỳ chuỗi thoát nào trong chúng, vì vậy len(r"\n")2. Vì chúng thoát các chuỗi thoát, bạn không thể kết thúc một chuỗi ký tự bằng một dấu gạch chéo ngược: đó không phải là một chuỗi thoát hợp lệ (ví dụ r"\").

"Nguyên" không phải là một phần của loại, nó chỉ là một cách để thể hiện giá trị. Ví dụ, "\\n"r"\n"là những giá trị giống hệt nhau, giống như 32, 0x200b100000giống hệt nhau.

Bạn có thể có unicode chuỗi ký tự thô:

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

Mã hóa tệp nguồn chỉ xác định cách diễn giải tệp nguồn, nó không ảnh hưởng đến các biểu thức hoặc loại khác. Tuy nhiên, nên tránh mã nơi mã hóa khác ASCII sẽ thay đổi ý nghĩa:

Các tệp sử dụng ASCII (hoặc UTF-8, cho Python 3.0) không nên có cookie mã hóa. Latin-1 (hoặc UTF-8) chỉ nên được sử dụng khi nhận xét hoặc chuỗi ký tự cần đề cập đến tên tác giả yêu cầu Latin-1; mặt khác, sử dụng thoát \ x, \ u hoặc \ U là cách ưa thích để đưa dữ liệu không phải ASCII vào chuỗi ký tự.


30

Hãy để tôi giải thích một cách đơn giản: Trong python 2, bạn có thể lưu trữ chuỗi theo 2 loại khác nhau.

Cái đầu tiên là ASCII , loại str trong python, nó sử dụng 1 byte bộ nhớ. (256 ký tự, sẽ lưu trữ hầu hết các bảng chữ cái tiếng Anh và các ký hiệu đơn giản)

Loại thứ 2 là UNICODE là loại unicode trong python. Unicode lưu trữ tất cả các loại ngôn ngữ.

Theo mặc định, python sẽ thích loại str nhưng nếu bạn muốn lưu trữ chuỗi ở loại unicode, bạn có thể đặt u ở phía trước văn bản như u'text ' hoặc bạn có thể làm điều này bằng cách gọi unicode (' text ')

Vì vậy, u chỉ là một cách ngắn để gọi một hàm để chuyển str thành unicode . Đó là nó!

Bây giờ là phần r , bạn đặt nó ở phía trước văn bản để nói với máy tính rằng văn bản là văn bản thô, dấu gạch chéo ngược không phải là một ký tự thoát. r '\ n' sẽ không tạo một ký tự dòng mới. Đó chỉ là văn bản đơn giản chứa 2 ký tự.

Nếu bạn muốn chuyển đổi str thành unicode và cũng đặt văn bản thô vào đó, hãy sử dụng urru sẽ phát sinh lỗi.

BÂY GIỜ, phần quan trọng:

Bạn không thể lưu trữ một dấu gạch chéo ngược bằng cách sử dụng r , đó là ngoại lệ duy nhất. Vì vậy, mã này sẽ tạo ra lỗi: r '\'

Để lưu trữ dấu gạch chéo ngược (chỉ một), bạn cần sử dụng '\\'

Nếu bạn muốn lưu trữ nhiều hơn 1 ký tự, bạn vẫn có thể sử dụng r như r '\' sẽ tạo ra 2 dấu gạch chéo ngược như bạn mong đợi.

Tôi không biết lý do tại sao r không hoạt động với một bộ lưu trữ dấu gạch chéo ngược nhưng lý do chưa được mô tả bởi bất kỳ ai. Tôi hy vọng rằng đó là một lỗi.


9
Bạn sẽ nhận thấy không chỉ r'\'là bất hợp pháp, thậm chí bạn không thể đặt một cái '\'ở bất kỳ đuôi nào. Giống như r'xxxxxx\'là một chuỗi bất hợp pháp.
thợ lặn

còn trăn 3 thì sao?
Krissh

1
@Krissh Tất cả 3 chuỗi python đều được hỗ trợ Unicode. Loại của nó sẽ là str. Đọc thêm để hiểu rõ hơn tại đây: Medium.com/better-programming/ từ
off99555

4

Có thể điều này là hiển nhiên, có thể không, nhưng bạn có thể tạo chuỗi '\' bằng cách gọi 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

4
x is yđánh giá là True trong python3?
Habeeb Perwad

5
@HabeebPerwad, đó là vì thực tập chuỗi . Bạn không bao giờ nên dựa vào thực tế x is yxảy ra để đánh giá Truevì thực tập. Thay vào đó hãy sử dụng x == y(nếu bạn không kiểm tra xem x và y có chính xác là cùng một đối tượng được lưu trữ tại một vị trí bộ nhớ không, nghĩa là).
Lucubrator

4

Chuỗi ký tự Unicode

Các chuỗi ký tự Unicode (chuỗi ký tự có tiền tố bởi u) không còn được sử dụng trong Python 3. Chúng vẫn hợp lệ mà chỉ nhằm mục đích tương thích với Python 2.

Chuỗi ký tự thô

Nếu bạn muốn tạo một chuỗi ký tự chỉ bao gồm các ký tự dễ đánh máy như chữ cái hoặc số tiếng Anh, bạn chỉ cần nhập chúng : 'hello world'. Nhưng nếu bạn muốn bao gồm cả một số nhân vật kỳ lạ hơn, bạn sẽ phải sử dụng một số cách giải quyết. Một trong những cách giải quyết là các chuỗi Escape . Ví dụ, bằng cách này, bạn có thể biểu thị một dòng mới trong chuỗi của mình bằng cách thêm hai ký tự dễ đánh máy \nvào chuỗi ký tự của bạn. Vì vậy, khi bạn in 'hello\nworld'chuỗi, các từ sẽ được in trên các dòng riêng biệt. Điều đó rất tiện dụng!

Mặt khác, có một số tình huống khi bạn muốn tạo một chuỗi ký tự có chứa các chuỗi thoát nhưng bạn không muốn chúng được Python giải thích. Bạn muốn chúng là nguyên liệu . Hãy xem những ví dụ này:

'New updates are ready in c:\windows\updates\new'
'In this lesson we will learn what the \n escape sequence does.'

Trong các tình huống như vậy, bạn chỉ có thể đặt tiền tố chuỗi ký tự bằng rký tự như thế này: r'hello\nworld'và không có chuỗi thoát nào sẽ được Python giải thích. Chuỗi sẽ được in chính xác như bạn đã tạo nó.

Chuỗi ký tự thô không hoàn toàn "thô"?

Nhiều người mong đợi các chuỗi ký tự thô là thô theo nghĩa "mọi thứ được đặt giữa các trích dẫn đều bị Python bỏ qua" . Điều đó không đúng. Python vẫn nhận ra tất cả các chuỗi thoát, nó chỉ không giải thích chúng - thay vào đó chúng không thay đổi. Nó có nghĩa là chuỗi ký tự thô vẫn phải là chuỗi ký tự chuỗi hợp lệ .

Từ định nghĩa từ vựng của một chuỗi ký tự:

string     ::=  "'" stringitem* "'"
stringitem ::=  stringchar | escapeseq
stringchar ::=  <any source character except "\" or newline or the quote>
escapeseq  ::=  "\" <any source character>

Rõ ràng là chuỗi ký tự (thô hoặc không) chứa ký tự trích dẫn trần: 'hello'world'hoặc kết thúc bằng dấu gạch chéo ngược: 'hello world\'không hợp lệ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.