Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

P.S. Кодировка в исходном коде Python




P. S. Кодировка в исходном коде Python

Python 3 предполагает, что ваш исходный код — т. е. каждый файл. py — записан в кодировке UTF-8.

☞ В Python 2, кодировкой по умолчанию для файлов. py была кодировка ASCII. В Python 3 кодировка по умолчанию — UTF-8.

Если вы желаете использовать другую кодировку в вашем коде, вы можете разместить объявление кодировки на первой строке каждого файла. Например, для кодировки windows-1252 объявление выглядит следующим образом:

# -*- coding: windows-1252 -*-

Объявление кодировки также может располагаться на второй строке файла, если первой строкой является путь к интерпретатору Python.

#! /usr/bin/python3
# -*- coding: windows-1252 -*-

За дополнительной информацией обращайтесь к PEP 263: Defining Python Source Code Encodings.

Материалы для дальнейшего чтения

  • On Unicode in Python:
  • Python Unicode HOWTO
  • What’s New In Python 3: Text vs. Data Instead Of Unicode vs. 8-bit
  • PEP 261 explains how Python handles astral characters outside of the Basic Multilingual Plane (i. e. characters whose ordinal value is greater than 65535)
  • On Unicode in general:
  • The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and * Character Sets (No Excuses! )
  • On the Goodness of Unicode
  • On Character Strings
  • Characters vs. Bytes
  • On character encoding in other formats:
  • Character encoding in XML
  • Character encoding in HTML
  • On strings and string formatting:
  • string — Common string operations
  • Format String Syntax
  • Format Specification Mini-Language
  • PEP 3101: Advanced String Formatting

Регулярные выражения

❝ Некоторые люди, во время решения одной проблемы думают: «Я знаю, я буду использовать регулярные выражения». Теперь у них две проблемы… ❞ — Jamie Zawinski

Погружение

Каждый новый язык программирования имеет встроенные функции для работы со строками. В Python, строки имеют методы для поиска и замены: index(), find(), split(), count(), replace() и т. д. Но эти методы ограничены для простейших случаев. Например метод index() ищет простую жёстко заданную часть строки и поиск всегда регистрозависимый. Чтобы выполнить регистронезависимый поиск по строке s, вы должны вызвать s. lower() или s. upper() для того чтобы быть уверенным что строка имеет соответствующий регистр для поиска. Методы replace() и split() имеют те же ограничения.

Если ваша задача может быть решена при помощи этих методов, лучше использовать их. Они простые и быстрые, легко читаемые, много может быть сказано о быстром, простом и удобочитаемом коде. Но если вы обнаружите что вы используете большое количество строковых функций с условиями if для обработки специальных случаев, или используете множество последовательных вызовов split() и join() чтобы нарезать на кусочки ваши строки, значит вы нуждаетесь в регулярных выражениях.

Регулярные выражения это мощный и (по большей части) стандартизированный способ для поиска, замены и парсинга текста при помощи комплексных шаблонов. Хотя синтаксис регулярных выражений довольно сложный и выглядит непохожим на нормальный код (прим. пер. «смахивает на perl»), конечный результат часто более удобочитаемый чем набор из последовательных функций для строк. Существует даже способ поместить комментарии внутрь регулярных выражений, таким образом вы можете включить небольшую документацию в регулярное выражение.

Если вы пользовались регулярными выражениями в других языках (таких как Perl, JavaScript, или PHP), синтаксис Python-а будет для вас достаточно привычным. Прочитайте обзор модуля re для того чтобы узнать о доступных функциях и их аргументах.

Учебный пример: Адрес Улицы

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

> > > s = '100 NORTH MAIN ROAD'
> > > s. replace('ROAD', 'RD. ') ①
'100 NORTH MAIN RD. '
> > > s = '100 NORTH BROAD ROAD'
> > > s. replace('ROAD', 'RD. ') ②
'100 NORTH BRD. RD. '
> > > UNIQae610d7ca506639d-nowiki-00000003-QINU ③
'100 NORTH BROAD RD. '
> > > import re ④
> > > re. sub('ROAD$', 'RD. ', s) ⑤
'100 NORTH BROAD RD. '

 

  • ① Моя задача стандартизировать адрес улицы, например 'ROAD' всегда выражается сокращением 'RD. '. На первый взгляд мне показалось, что это достаточно просто, и я могу использовать метод replace(). В конце концов, все данные уже в верхнем регистре и несовпадение регистра не составит проблемы. Строка поиска 'ROAD' являлась константой и обманчиво простой пример s. replace() вероятно работает.
  • ② Жизнь же, напротив, полна противоречивых примеров, и я быстро обнаружил один из них. Проблема заключалась в том что 'ROAD' появилась в адресе дважды, один раз как 'ROAD', а во второй как часть названия улицы 'BROAD'. Метод replace() обнаруживал 2 вхождения и слепо заменял оба, разрушая таким образом правильный адрес.
  • ③ Чтобы решить эту проблему вхождения более одной подстроки 'ROAD', вам необходимо прибегнуть к следующему: искать и заменять 'ROAD' в последних четырёх символах адреса (s[-4: ]), оставляя строку отдельно (s[: -4]). Как вы могли заметить, это уже становится громоздким. К примеру, шаблон зависит от длины заменяемой строки. (Если вы заменяли 'STREET' на 'ST. ', вам придется использовать s[: -6] и s[-6: ]. replace(... ). ) Не хотели бы вы вернуться к этому коду через полгода для отладки? Я не хотел бы.
  • ④ Пришло время перейти к регулярным выражениям. В Python все функции, связанные с регулярными выражениями содержится в модуле re.
  • ⑤ Взглянем на первый параметр: 'ROAD$'. Это простое регулярное выражение которое находит 'ROAD' только в конце строки. Знак $ означает «конец строки». (Также существует символ ^, означающий «начало строки». ) Используя функцию re. sub() вы ищете в строке s регулярное выражение 'ROAD$' и заменяете на 'RD. '. Оно совпадает с 'ROAD' в конце строки s, но не совпадает с 'ROAD', являющимся частью названия 'BROAD', так как оно находится в середине строки s.

Продолжая историю про обработку адресов, я скоро обнаружил, что предыдущий пример совпадения 'ROAD' на конце адреса был недостаточно хорош, так как не все адреса включали в себя определение улицы. Некоторые адреса просто оканчивались названием улицы. Я избегал этого в большинстве случаев, но если название улицы было 'BROAD', тогда регулярное выражение совпадало с 'ROAD' на конце строки 'BROAD', чего я совершенно не хотел.

> > > s = '100 BROAD'
> > > re. sub('ROAD$', 'RD. ', s)
'100 BRD. '
> > > re. sub('\\bROAD$', 'RD. ', s) ①
'100 BROAD'
> > > re. sub(r'\bROAD$', 'RD. ', s) ②
'100 BROAD'
> > > s = '100 BROAD ROAD APT. 3'
> > > re. sub(r'\bROAD$', 'RD. ', s) ③
'100 BROAD ROAD APT. 3'
> > > re. sub(r'\bROAD\b', 'RD. ', s) ④
'100 BROAD RD. APT 3'

 

  • ① В действительности я хотел совпадения с 'ROAD' когда оно на конце строки и является самостоятельным словом (а не частью большего). Чтобы описать это в регулярном выражении необходимо использовать '\b', что означает «слово должно оказаться прямо тут. » В Python это сложно, так как '\' знак в строке должен быть экранирован. Иногда это называют как «бедствие бэкслэша» и это одна из причин почему регулярные выражения проще в Perl чем в Python. Однако недостаток Perl в том что регулярные выражения смешиваются с другим синтаксисом, если у вас ошибка, достаточно сложно определить где она, в синтаксисе или в регулярном выражении.
  • ② Чтобы обойти проблему «бедствие бэкслэша» вы можете использовать то, что называется неформатированная строка (raw string), путём применения префикса строки при помощи символа 'r'. Это скажет Python-у что ничего в этой строке не должно быть экранировано; '\t' это табулятор, но r'\t' это символ бэкслэша '\', а следом за ним буква 't'. Я рекомендую всегда использовать неформатированную строку, когда вы имеете дело с регулярными выражениями; с другой стороны всё становится достаточно путанным (несмотря на то что наше регулярное выражения уже достаточно запутано).
  • *вздох* К неудаче я скоро обнаружил больше причин противоречащих моей логике. В этом случае адрес улицы содержал в себе цельное отдельное слово 'ROAD' и оно не было на конце строки, так как адрес содержал номер квартиры после определения улицы. Так как слово 'ROAD' не находится в конце строки, регулярное выражение re. sub() его пропускало и мы получали на выходе ту же строку что и на входе, а это то чего вы не хотите.
  • ④ Чтобы решить эту проблему я удалил символ '$' и добавил ещё один '\b'. Теперь регулярное выражение совпадало с 'ROAD' если оно являлось цельным словом в любой части строки, на конце, в середине и в начале.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...