Що саме роблять прапори рядків "u" та "r", а що таке "необмежені" літери?


652

Задаючи це запитання , я зрозумів, що не знаю багато про сирі рядки. Для когось, хто претендує на тренер Джанго, це гарно.

Я знаю, що таке кодування, і я знаю, що u''поодинці робить, коли отримую те, що є Unicode.

  • Але що саме робить r''? Який рядок це призводить до?

  • І перш за все, що чорт робить ur''?

  • Нарешті, чи є якийсь надійний спосіб повернутися з рядка Unicode до простого необмеженого рядка?

  • Ну, і, до речі, якщо ваша система та схема редактора тексту встановлені на UTF-8, u''насправді щось робить?

Відповіді:


683

Насправді немає жодної "сирої струни "; Є необроблені рядкові літерали , які є саме строковими літералами, позначеними знаком "" 'r'перед початком цитати.

"Сирий буквений рядок" - це дещо інший синтаксис для рядкового літералу, в якому зворотна косої риси \сприймається як значення "просто зворотній косою рисою" (за винятком випадків, коли вони надходять прямо перед цитатою, яка в іншому випадку припиняє літерал) - ні "послідовності втечі" для відображення нових рядків, вкладок, зворотних просторів, форм-стрічок тощо. У звичайних літеральних рядках кожен зворотний проріз повинен бути подвоєний вдвічі, щоб уникнути його прийняття як початок послідовності проходження.

Цей варіант синтаксису існує здебільшого тому, що синтаксис регулярних виразів виразів важкий з косою косою рисою (але ніколи в кінці, тому пункт «крім» вище не має значення), і це виглядає трохи краще, коли ви уникаєте подвоєння кожного з них - - це все. Він також набув деякої популярності для вираження власних шляхів до файлів Windows (з косою косою рисою, а не з звичайними косою рисою, як на інших платформах), але це дуже рідко потрібно (оскільки звичайні косої риси в основному добре працюють і в Windows) і недосконалі (через пункт "крім" вище).

r'...'є байт рядка (в Python 2. *), ur'...'це рядок Unicode (знову ж , в Python 2. *), і будь-який з трьох інших видів процитувати також виробляє одні і ті ж типи рядків (так, наприклад r'...', r'''...''', r"...", r"""..."""є всі рядки байтів тощо).

Не впевнений, що ви маєте на увазі під "поверненням назад " - немає внутрішніх напрямків назад і вперед, тому що немає необмеженого рядкового типу , це просто альтернативний синтаксис для вираження ідеально нормальних рядкових об'єктів, байтів або Unicode, якими вони можуть бути.

І так, в Python 2. *, u'...' це , звичайно , завжди відрізняється від всього '...'- колишній є рядком Юникода, останній рядок байт. Те, що кодування буквалу може бути виражене, є повністю ортогональним питанням.

Наприклад, врахуйте (Python 2.6):

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

Об'єкт Unicode, звичайно, займає більше місця в пам'яті (очевидно, дуже мала різниця для дуже короткого рядка ;-).


6
Розуміння "r" не означає жодних проблем або питань кодування, це набагато простіше.
e-satis

23
Зауважте, що ru "C: \ foo \ нестабільний" не вдасться, оскільки \ u - послідовність утечі unicode в режимі ru r режиму немає \ u.
Кертіс Яллоп

26
Зауважте, що uі rне є комутаційними: ur'str'працює, ru'str'не працює . (принаймні в ipython 2.7.2 на win7)
RafiK

7
Щойно перевірив rрядки і помітив, що якщо він \ є останнім символом, він не буде сприйматися як буквальний, а натомість уникає завершальної цитати, викликаючи SyntaxError: EOL while scanning string literal. Тому \\ все-таки потрібно використовувати для остаточного примірника \ будь-яких рядків, що закінчуються зворотною косою рисою.
Ентелеформ

1
python 3.x - sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(Ubuntu 16.04 з язиком UTF8). Точно так же type('cioa') == type(r'cioa') == type(u'cioa'). Але НЕ, інтерполяція необроблених рядків має значення, томуsys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Даррен Вебер,

177

У python є два типи рядків: традиційний strі новіший unicode. Якщо ви введете рядковий літерал без uфронту, ви отримаєте старий strтип, який зберігає 8-бітові символи, а з uфронтом ви отримаєте новий unicodeтип, який може зберігати будь-який символ Unicode.

Тип rвзагалі не змінює, він просто змінює інтерпретацію рядкового літералу. Без цього rнахили в косому напрямку розглядаються як символи втечі. Зі rзворотними нахилами слід вважати буквальні. У будь-якому випадку, тип однаковий.

ur це, звичайно, рядок Unicode, де рисові косої риси є буквальними зворотніми косою рисою, а не частиною кодів втечі.

Ви можете спробувати перетворити рядок Unicode у стару рядок за допомогою str()функції, але якщо є якісь символи Unicode, які не можуть бути представлені у старому рядку, ви отримаєте виняток. Ви можете замінити їх спочатку знаками запитання, якщо хочете, але це, звичайно, спричинить нечитабельність цих символів. Не рекомендується використовувати strтип, якщо ви хочете правильно обробити символи unicode.


Спасибі, прийняли. Як я вже сказав, я знаю, що таке unicode, я не знав, що означає "r" і що буде поєднанням "u" і "r". Я знаю, що краще знаю, ура.
e-satis

6
У зворотному рядковому літералі зворотні риски не трактуються як буквальні, тому r"\"є синтаксичною помилкою.


60

"необроблена рядок" означає, що вона зберігається так, як вона з'являється Наприклад, '\'це просто зворотний нахил, а не втеча .


3
... якщо тільки це не останній символ рядка, в такому випадку він не уникає цитати, що завершується.
jez

36

Префікс "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

Кодування вихідного файлу просто визначає, як інтерпретувати вихідний файл, інакше це не впливає на вирази чи типи. Однак рекомендується уникати коду, коли кодування, яке не ASCII, змінило б значення:

Файли, що використовують ASCII (або UTF-8, для Python 3.0), не повинні містити файли cookie-кодування. Latin-1 (або UTF-8) слід використовувати лише тоді, коли в коментарі чи докстрингу потрібно згадати ім’я автора, для якого потрібна Latin-1; в іншому випадку використання \ x, \ u або \ U-перешкод є кращим способом включення даних, що не належать до ASCII, в рядкові літерали.


30

Дозвольте мені пояснити це просто: У python 2 ви можете зберігати рядок у двох різних типах.

Перший - це ASCII, який є str типу в python, він використовує 1 байт пам'яті. (256 символів, зберігатимуть переважно англійські алфавіти та прості символи)

2-й тип - UNICODE, який є однокодовим у python. 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 не працює з одним зворотним нахилом, але причину ще ніхто не описав. Я сподіваюся, що це помилка.


9
Ви помітите, що це не тільки r'\'незаконно, ви навіть не можете поставити жодного '\'в жоден рядок. Так само, як r'xxxxxx\'і незаконна струна.
розбіг

що з python 3?
Кріш

1
@Krissh Усі рядки python 3 підтримуються Unicode. Його тип буде str. Детальніше для кращого розуміння читайте тут: medium.com/better-programming/…
off99555

4

Можливо, це очевидно, можливо, ні, але ви можете зробити рядок '\' , зателефонувавши 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оцінює True у python3?
Хабіб Первад

5
@HabeebPerwad, це через строкове інтернування . Ви ніколи не повинні покладатися на той факт, якийx is yтрапляється оцінюватиTrueчерез стажування. Натомість використовуйтеx == y(якщо ви не перевіряєте, чи x і y точно той самий об'єкт, що зберігається в одній позиції пам'яті, тобто).
Лукобратор

4

Unicode рядкові літерали

Літеральні рядки Unicode (рядкові літерали з префіксом u) більше не використовуються в Python 3. Вони все ще дійсні, але лише для сумісності з Python 2.

Сирі літеральні рядки

Якщо ви хочете створити строковий літерал , що складається тільки легко тіпізіруемого символи , такі як англійські букви або цифри, ви можете просто ввести їх: 'hello world'. Але якщо ви хочете включити ще кілька екзотичних персонажів, вам доведеться скористатися деяким способом вирішення. Одним із способів вирішення є послідовності Escape . Таким чином, ви можете, наприклад, представити новий рядок у рядку, просто додавши два символи, що легко набираються, \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\'не є дійсними.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.