Что именно делают строковые флаги "u" и "r" и что такое необработанные строковые литералы?

Задавая этот вопрос, я понял, что мало что знаю о необработанных строках. Для кого-то, претендующего на звание тренера по Джанго, это отстой.

Я знаю, что такое кодировка, и я знаю, что u'' один делает, так как я понимаю, что такое Unicode.

  • Но что делает r'' делать точно? К какой строке это приводит?

  • И прежде всего, что, черт возьми, делает ur'' делать?

  • Наконец, есть ли надежный способ вернуться от строки Unicode к простой необработанной строке?

  • Да, и, кстати, если ваша система и ваш текстовый редактор charset установлены на UTF-8, делает u'' на самом деле делать что-нибудь?

6 ответов

Решение

На самом деле нет никакой "необработанной строки "; есть необработанные строковые литералы, которые являются именно строковыми литералами, помеченными 'r' перед открытием цитаты.

"Необработанный строковый литерал" - это немного другой синтаксис строкового литерала, в котором обратный слеш, \, принимается как означающий "просто обратную косую черту" (за исключением случаев, когда он идет прямо перед кавычкой, которая в противном случае заканчивала бы литерал) - без "escape-последовательностей", представляющих символы новой строки, табуляции, возврата на одну позицию, каналов формы и так далее. В обычных строковых литералах каждая обратная косая черта должна быть удвоена, чтобы ее не принимали за начало escape-последовательности.

Этот вариант синтаксиса существует главным образом потому, что синтаксис шаблонов регулярных выражений насыщен обратными слешами (но никогда не заканчивается, поэтому вышеприведенное предложение "кроме" не имеет значения) и выглядит немного лучше, когда вы не удваиваете каждый из них -- это все. Он также приобрел некоторую популярность для выражения собственных путей к файлам Windows (с обратными слешами вместо обычных слешей, как на других платформах), но это очень редко требуется (поскольку нормальные слэши в основном работают также и в Windows) и несовершенным (из-за предложения "кроме" выше).

r'...' является байтовой строкой (в Python 2.*), ur'...' является строкой Unicode (опять же, в Python 2.*), и любой из трех других типов цитирования также производит точно такие же типы строк (например, r'...', r'''...''', r"...", r"""...""" все байтовые строки и т. д.).

Не уверен, что вы подразумеваете под " возвращением " - нет встроенных указателей назад и вперед, потому что нет необработанного строкового типа, это просто альтернативный синтаксис для выражения совершенно обычных строковых объектов, байтов или юникодов, какими они могут быть.

И да, в Python 2.*, u'...' конечно всегда отличается от просто '...' - первая строка в юникоде, вторая строка байтов. В чем может быть выражена кодировка литерала - это совершенно ортогональный вопрос.

Например, рассмотрим (Python 2.6):

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

Разумеется, объект Unicode занимает больше места в памяти (очевидно, очень небольшая разница для очень короткой строки;-).

В Python есть два типа строк: традиционные str типа и новее unicode тип. Если вы введете строковый литерал без u впереди вы получаете старый str тип, который хранит 8-битные символы, и с u впереди вы получите более новый unicode тип, который может хранить любой символ Unicode.

r вообще не меняет тип, он просто меняет интерпретацию строкового литерала. Без r, обратные слеши рассматриваются как escape-символы. С rобратные слеши рассматриваются как буквальные. В любом случае, тип один и тот же.

ur это, конечно, строка Unicode, где обратные косые черты являются буквальными обратными косыми чертами, а не частью escape-кодов.

Вы можете попытаться преобразовать строку Unicode в старую строку, используя str() функции, но если есть какие-либо символы Юникода, которые не могут быть представлены в старой строке, вы получите исключение. Вы можете заменить их сначала вопросительными знаками, если хотите, но, конечно, это приведет к тому, что эти символы станут нечитаемыми. Не рекомендуется использовать str введите, если вы хотите правильно обрабатывать символы Юникода.

"Необработанная строка" означает, что она хранится в том виде, в котором она появилась. например, "\" - это просто обратный слеш вместо экранирования.

Позвольте мне объяснить это просто: в Python 2 вы можете хранить строки в 2 разных типах.

Первый - ASCII, который является типом str в python, он использует 1 байт памяти. (256 символов, будет хранить в основном английские алфавиты и простые символы)

Второй тип - это UNICODE, который является типом Unicode в Python, он использует 2 байта памяти. (65536 символов, так что сюда входят все символы всех языков на земле)

По умолчанию python предпочитает тип str, но если вы хотите сохранить строку в типе Unicode, вы можете поместить u перед текстом как u'text ' или вы можете сделать это, вызвав unicode (' text ')

Так что у вас просто короткий способ вызвать функцию для приведения str к юникоду. Это оно!

Теперь, начиная с первой части, вы помещаете его перед текстом, чтобы сообщить компьютеру, что текст является необработанным текстом, обратная косая черта не должна быть экранирующим символом. r '\ n' не будет создавать символ новой строки. Это просто текст, содержащий 2 символа.

Если вы хотите преобразовать str в unicode, а также поместить туда необработанный текст, используйте ur, потому что ru вызовет ошибку.

СЕЙЧАС важная часть:

Вы не можете сохранить одну обратную косую черту, используя r, это единственное исключение. Так что этот код выдаст ошибку: r '\'

Чтобы сохранить обратную косую черту (только одну), вам нужно использовать '\\'

Если вы хотите сохранить более 1 символа, вы все равно можете использовать r, например, r'\\' произведет 2 обратных слеша, как вы и ожидали.

Я не знаю причину, по которой r не работает с одним хранилищем с обратной косой чертой, но причина пока никем не описана. Я надеюсь, что это ошибка.

Префикс "u" обозначает, что значение имеет тип unicode скорее, чем str,

Необработанные строковые литералы с префиксом "r" экранируют любые escape-последовательности внутри них, поэтому len(r"\n") равен 2. Поскольку они экранируют escape-последовательности, вы не можете завершить строковый литерал одной обратной косой чертой: это недопустимая escape-последовательность (например, r"\").

"Raw" не является частью типа, это просто один из способов представления значения. Например, "\\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 escape-символов является предпочтительным способом включения не-ASCII-данных в строковые литералы.

Строковые литералы Unicode

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

Необработанные строковые литералы

Если вы хотите создать строковый литерал, состоящий только из легко вводимых символов, таких как английские буквы или цифры, вы можете просто ввести их: 'hello world'. Но если вы хотите включить еще несколько экзотических персонажей, вам придется использовать обходной путь. Один из обходных путей - это escape-последовательности. Таким образом, вы можете, например, представить новую строку в своей строке, просто добавив два легко вводимых символа\nв строковый литерал. Поэтому, когда вы печатаете'hello\nworld'строка, слова будут напечатаны на отдельных строках. Это очень удобно!

С другой стороны, бывают ситуации, когда вы хотите создать строковый литерал, содержащий escape-последовательности, но не хотите, чтобы они интерпретировались 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'и никакие escape-последовательности не будут интерпретироваться Python. Строка будет напечатана точно так, как вы ее создали.

Необработанные строковые литералы не полностью "сырые"?

Многие люди ожидают, что необработанные строковые литералы будут необработанными в том смысле, что "все, что помещено в кавычки, игнорируется Python". Это неправда. Python по-прежнему распознает все escape-последовательности, он просто не интерпретирует их - вместо этого он оставляет их без изменений. Это означает, что необработанные строковые литералы по-прежнему должны быть действительными строковыми литералами.

Из лексического определения строкового литерала:

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
Другие вопросы по тегам