Что именно делают строковые флаги "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