Как переносить длинные строки в python

от admin

A good way to make long strings wrap to newline?

In my project, I have a bunch of strings that are read in from a file. Most of them, when printed in the command console, exceed 80 characters in length and wrap around, looking ugly.

I want to be able to have Python read the string, then test if it is over 75 characters in length. If it is, then split the string up into multiple strings, then print one after the other on a new line. I also want it to be smart, not cutting off full words. i.e. «The quick brown <newline> fox. » instead of «the quick bro<newline>wn fox. » .

I’ve tried modifying similar code that truncates the string after a set length, but just trashes the string instead of putting it in a new line.

Перенос строки в Python

Перенос строки в Python можно реализовать несколькими способами. Выбор способа зависит от вида строки, которую нужно перенести:

  • Перенос строки с кодом в Python (если вы хотите повысить читаемость кода и перенести часть строки с кодом в область видимости)
  • Перенос текстовой строки в Python (если вам нужно оформить вывод текстовой строки с переносами в нужных местах)

Рассмотрим на примерах каждый из указанных вариантов.

Перенос строки с кодом в Python

PEP-8 (документ, регламентирующий правила написания кода в Python) рекомендует для хорошей читаемости кода не оставлять в одной строке больше 79 символов. На мой взгляд, такая рекомендация весьма справедлива и позволяет избавить программистов, от горизонтального (утомительного) скроллинга кода. Привести код в порядок помогут следующие возможности Python:

1. Длинные выражения в квадратных или круглых скобках можно переносить на следующую строку без дополнительных символов!

Так как в Python дополнительные пробелы в круглых или в квадратных скобках игнорируются, смело переносите длинные выражения в скобках на следующую строку.

Пример 1: Матрица, записанная таким способом, легче читается:

Так как строки матрицы заключены в квадратные скобки, мы можем их переносить без дополнительных символов.

Пример 2: аргументы функций можно переносить на новую строку, так как они заключены в круглые скобки:

2. Можно переносить строки с операторами с помощью символа обратной косой черты.

Если в выражении нет скобок, но есть операторы, используйте для переноса обратную косую черту, как показано в примере:

В данном примере обратная косая черта после оператора сложения никак не отразится на вычислениях и будет интерпретирована, как символ переноса строки.

Перенос текстовой строки в Python

Для переноса текстовой строки в Python используется специальный символ ‘\n’ . Рассмотрим на примерах:

Пример переноса строки в функции print(): даны два предложения: «Преложение 1. Предложение 2.» Нужно вывести на экран каждое предложение с новой строки.

Так как символ «\n» означает перенос строки, то второе предложение будет записано с новой строки.

Пример записи текстового файла с переносами строк:

В данном примере мы записали новый файл с содержимым:

Текст, расположенный после символа ‘\n’ записан в файле с новой строки

У нас появился Telegram-канал для изучающих Python! Канал совсем свежий, подпишись одним из первых, ведь вместе «питонить» веселее! �� Ссылка на канал: «Кодим на Python!»

Перенос длинного кода на новую строку Python

Если строка превышает 80 символов в длину — по PEP 8 её нужно разделить на несколько.

Пример

Пример слишком длинной строки

url = your_base_url + «/monitor-service/api/v1/components/744618a0-78c5-4e19-78f4-6d215bde64a5»

Чтобы сделать перенос строки — воспользуйтесь символом \

url = your_base_url + \ «/monitor-service/api/v1/components/744618a0-78c5-4e19-78f4-6d215bde64a5»

url = your_base_url + «/monitor-service/api/v1/components/» \ «744618a0-78c5-4e19-78f4-6d215bde64a5»

f-string

Если нужно перенести f-string , например:

print ( f' \n\n POST to < your_url >response status code is < response.status_code >\n ' )

Новую строку тоже нужно начать с f

Перенос при присваивании

Если нужно перенести выражение вида a = b, где b это что-то длинное:

# Правильно: # Выравнивание по открывающей скобке. foo = long_function_name(var_one, var_two, var_three, var_four) # Второй вариант так называемый «Подвешенный» отступ. foo = long_function_name ( var_one, var_two, var_three, var_four ) # Если поставить запятую в конце — закрывающую скобку можно. # поместить под первым непустым символом. result = some_function_that_takes_arguments ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , ) # Либо в начало строки. result = some_function_that_takes_arguments ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , ) # Неправильно: # Запрещено перечислять аргументы в первой строке # если следующая не выровнена. foo = long_function_name(var_one, var_two, var_three, var_four)

Объявление функций

Если нужно объявить функцию с большим числом параметров:

# Правильно: # Нужно отступить на 4 пробела, чтобы выделить параметры. def long_function_name ( var_one, var_two, var_three, var_four): print (var_one) # Неправильно # Параметры не выделяются и читать неудобно def long_function_name ( var_one, var_two, var_three, var_four): print (var_one)

Ветвления на основе if разрешено оформлять следующими способами:

# Без отступа. if (this_is_one_thing and that_is_another_thing): do_something() # Хороший приём — добавить комментарий, который улучшит читаемость # в редакторах с подсветкой синтаксиса. if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something() # Разрешено добавить отступ перед and. if (this_is_one_thing and that_is_another_thing): do_something()

Объявление списков

Списки можно объявлять двумя способами:

my_list = [ 1 , 2 , 3 , 4 , 5 , 6 , ] my_list = [ 1 , 2 , 3 , 4 , 5 , 6 , ]

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Name already in use

PythonCources / lesson17.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink

1 contributor

Users who have contributed to this file

  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents

Copy raw contents

Copy raw contents

Урок 17. PEP8. imports.

PEP — Python Enhanced Proposal, рекомендация по код стайлингу (следовать обязательно:)

Гвидо ван Россум — создатель языка python

Ключевая идея Гвидо такова: код читается намного больше раз, чем пишется. Собственно, рекоммендации о стиле написания кода направлены на то, чтобы улучшить читабельность кода и сделать его согласованным между большим числом проектов. В идеале, весь код будет написан в едином стиле, и любой сможет легко его прочесть. Как говорится в PEP 20 «Читабельность имеет значение».

Это руководство о согласованности и единстве. Согласованность с этим руководством очень важна. Согласованность внутри одного проекта еще важнее. А согласованность внутри модуля или функции — самое важное. Но важно помнить, что иногда это руководство неприменимо, и понимать, когда можно отойти от рекоммендаций. Когда вы сомневаетесь, просто посмотрите на другие примеры и решите, какой выглядит лучше.

Две причины, чтобы нарушить правила:

Когда применение правила сделает код менее читабельным даже для того, кто привык читать код, который следует правилам.

Чтобы писать в едином стиле с кодом, который уже есть в проекте и который нарушает правила (может быть, в силу исторических причин) — впрочем, это возможность подчистить чужой код.

Внешний вид кода

Используйте 4 пробела на один уровень отступа. В старом коде, который вы не хотите трогать, можно продолжить пользоваться 8 пробелами для отступа.

Табуляция или пробелы?

Никогда не смешивайте символы табуляции и пробелы.

Самый распространенный способ отступов — пробелы. На втором месте — отступы только с использованием табуляции. Код, в котором используются и те, и другие типы отступов, должен быть исправлен так, чтобы отступы в нем были расставлены только с помощью пробелов. Когда вы вызываете интерпретатор в командной строке с параметром -t, он выдает предупреждения (warnings) при использовании смешанного стиля в отступах, а запустив интерпретатор с параметром -tt, вы получите в этих местах ошибки (errors). Используйте этии опции!

В новых проектах для отступов мы настоятельно рекомендуем использовать пробелы. К тому же, многие редакторы позволяют легко делать.

Максимальная длина строки

Ограничьте максимальную длину строки 79 символами.

Пока еще существует немало устройств, где длина строки равна 80 символам; к тому же, ограничив ширину окна 80 символами, мы сможем расположить несколько окон рядом друг с другом. Автоматический перенос строк на таких устройствах нарушит форматирование, и код будет труднее понять. Так что, пожалуйста, ограничьте длину строки 79 символами, и 72 символами в случае длинных блоков текста (строки документации или комментарии).

Предпочтительный способ переноса длинных строк — использование подразумевающегося продолжения строки между обычными, квадратными и фигурными скобками. В случае необходимости можно добавить еще одну пару скобок вокруг выражения, но часто лучше выглядит обратный слэш. Постарайтесь сделать правильные отступы для перенесённой строки. Предпочтительнее вставить перенос строки после бинарного оператора, но не перед ним.

Вот несколько примеров:

Отделяйте функции (верхнего уровня, не функции внутри функций) и определения классов двумя пустыми строчками.

Определения методов внутри класса отделяйте одной пустой строкой.

Дополнительные отступы строками могут быть изредка использованы для выделения группы логически связанных функций. Пустые строки могут быть пропущены, между несколькими выражениями, записанными в одну строку, например, «заглушки» функций.

Используйте (без энтузиазма) пустые строки в коде функций, чтобы отделить друг от друга логические части.

Python расценивает символ control+L как незначащий (whitespace), и вы можете использовать его, потому что многие редакторы обрабатывают его как разрыв страницы — таким образом логические части в файле будут на разных страницах.

Кодировки (PEP 263)

Код ядра python всегда должен использовать ASCII или Latin-1 кодировку (также известную как ISO-8859-1). Начиная с версии python 3.0, предпочтительной является кодировка UTF-8 (смотрите PEP 3120).

Files using ASCII (or UTF-8, for Python 3.0) should not have a coding cookie. Используйте Latin-1 (или UTF-8), только если это необходимо, чтобы указать в комментарии или строке документации имя автора, содержащее в себе символ из Latin-1. В противном случае предпочтительнее использовать escape-символы \x, \u или \U для не-ASCII символов в строках.

Начиная с версии python 3.0 в стандартной библиотеке действует следующая политика (смотрите PEP 3131): все идентификаторы обязаны содержать только ASCII символы, и означать английские слова везде, где это возможно (во многих случаях используются сокращения или неанглийские технические термины). Кроме того, строки и комментарии тоже должны содержать лишь ASCII символы. Исключения составляют: (а) test case, тестирующий не-ASCII особенности программы, и (б) имена авторов. Авторы, буквы в именах которых не из латинского алфавита, должны транслитерировать свои имена в латиницу.

Проектам с открытым кодом для широкой аудитории также рекомендуется использовать это соглашение.

Импортирование разных модулей должно быть на разных строчках, например:

В то же время, можно писать вот так:

Импортирование всегда нужно делать сразу после комментариев к модулю и строк документации, перед объявлением глобальных переменных и констант.

Группируйте импорты в следующем порядке:

  1. импорты стандартной библиотеки
  2. импорты сторонних библиотек
  3. импорты модулей текущего проекта

Вставляйте пустую строку между каждой группой импортов.

Относительные импорты крайне не рекомендуются — всегда указывайте абсолютный путь к модулю для всех импортирований. Даже сейчас, когда PEP 328 реализован в версии python 2.5, использовать явные относительные импорты нежелательно, потому что абсолютные импорты лучше переносимы и читабельны.

Когда вы импортируете класс из модуля, вполне можно писать вот так:

Если такое написание вызывает конфликт имен, тогда пишите:

И используйте «myclass.MyClass» и «foo.bar.yourclass.Yourclass» .

Пробелы в выражениях и инструкциях

Избегайте использования пробелов в следующих ситуациях:

  • Сразу после или перед скобками (обычными, фигурными и квадратными)
  • Сразу перед запятой, точкой с запятой, двоеточием:
  • Сразу перед открывающей скобкой, после которой начинается список аргументов при вызове функции:
  • Сразу перед открывающей скобкой, после которой следует индекс или срез:
  • Использование более одного пробела вокруг оператора присваивания (или любого другого) для того, чтобы выровнять его с другим таким же оператором на соседней строке:

Вседа окружайте эти бинарные операторы одним пробелом с каждой стороны: присваивание ( = , += , -= и прочие), сравнения ( == , < , > , != , <> , <= , >= , in , not in , is , is not ), логические операторы ( and , or , not ).

Ставьте пробелы вокруг арифметических операций.

  • Не используйте пробелы для отделения знака = , когда он употребляется для обозначения аргумента-ключа (keyword argument) или значения параметра по умолчанию.
  • Не используйте составные инструкции (несколько команд в одной строке).
  • Иногда можно писать тело циклов while, for или ветку if в той же строке, если команда короткая, но если команд несколько, никогда так не пишите.

Комментарии, которые противоречат коду, хуже, чем отсутствие комментариев. Всегда исправляйте комментарии, если меняете код!

Комментарии должны являться законченными предложениями. Если комментарий — фраза или предложение, первое слово должно быть написано с большой буквы, если только это не имя переменной, которая начинается с маленькой буквы (кстати, никогда не отступайте от этого правила для имен переменных).

Если комментарий короткий, можно опустить точку в конце предложения. Блок комментариев обычно состоит из одного или более абзацев, составленных из полноценных предложений, поэтому каждое предложение должно оканчиваться точкой.

Ставьте два пробела после точки в конце предложения.

Если вы пишете по-английски, не забывайте о Странке и Уайте (имеется в виду книга Strunk & White, “Elements of style”, которая является практически эталонным руководством по правильному написанию текстов на английском языке, — прим. перев.)

Программисты, которые не говорят на английском языке, пожалуйста, пишите комментарии на английском, если только вы не уверены на 120 процентов, что ваш код никогда не будут читать люди, не знающие вашего родного языка.

Блок комментариев обычно объясняет код (весь, или только некоторую часть), идущий после блока, и должен иметь тот же отступ, что и сам код. Каждая строчка такого блока должна начинаться с символа # и одного пробела после него (если только сам текст комментария не имеет отступа).

Абзацы внутри блока комментариев лучше отделять строкой, состоящей из одного символа #.

Комментарии в строке с кодом

Старайтесь реже использовать подобные комментарии.

Такой комментарий находится в той же строке, что и инструкция. «Встрочные» комментарии должны отделяться хотя бы двумя пробелами от инструкции. Они должны начинаться с символа # и одного пробела.

Комментарии в строке с кодом не нужны и только отвлекают от чтения, если они объясняют очевидное. Не пишите вот так:

Впрочем, иногда такие комметарии полезны:

Соглашения о написании хорошей документации (docstrings) увековечены (да, забавно, но автор использует именно такое слово, — прим. перев.) в PEP 257.

Пишите документацию для всех модулей, функций, классов, методов, которые объявлены как public. Строки документации необязательны для не-public методов, но лучше написать, что делает метод. Комментарий нужно писать после строки с def.

PEP 257 объясняет, как правильно и хорошо документировать. Заметьте, очень важно, чтобы закрывающие «»» стояли на отдельной строчке. А еще лучше, если перед ними будет ещё и пустая строка, например:

Для однострочной документации можно оставить «»» на той же строке.

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

Описание: Стили имен

Существует много разных стилей. Поможем вам распознать, какой стиль именования используется, независимо от того, для чего он используется.

Обычно различают следующие стили:

b (одиночная маленькая буква)

B (одиночная заглавная буква)

lowercase (слово в нижнем регистре)

lower_case_with_underscores (слова из маленьких букв с подчеркиваниями)

UPPERCASE (заглавные буквы)

UPPERCASE_WITH_UNDERSCORES (слова из заглавных букв с подчеркиваниями)

CapitalizedWords (слова с заглавными буквами, или CapWords, или CamelCase 5. Иногда называется StudlyCaps). Замечание: когда вы используете аббревиатуры в таком стиле, пишите все буквы аббревиатуры заглавными — HTTPServerError лучше, чем HttpServerError.

mixedCase (отличается от CapitalizedWords тем, что первое слово начинается с маленькой буквы)

Capitalized_Words_With_Underscores (слова с заглавными буквами и подчеркиваниями — уродливо!) Ещё существует стиль, в котором имена, принадлежащие одной логической группе, имеют один короткий префикс. Этот стиль редко используется в python, но мы упоминаем его для полноты. Например, функция os.stat() возвращает кортеж, имена в котором традиционно имеют вид st_mode, st_size, st_mtime и так далее. (Так сделано, чтобы подчеркнуть соответствие этих полей структуре системных вызовов POSIX, что помогает знакомым с ней программистам).

В библиотеке X11 используется префикс Х для всех public-функций. В python этот стиль считается излишним, потому что перед полями и именами методов стоит имя объекта, а перед именами функций стоит имя модуля.

В дополнение к этому, используются следующие специальные формы записи имен с добавлением символа подчеркивания в начало или конец имени:

_single_leading_underscore: слабый индикатор того, что имя используется для «внутренних нужд». Например, from M import * не будет импортировать объекты, чьи имена начинаются с символа подчеркивания.

single_trailing_underscore_: используется по соглашению для избежания конфликтов с ключевыми словами языка python, например:

__double_leading_underscore: изменяет имя атрибута класса, т.е. в class FooBar поле __boo становится _FooBar__boo.

double_leading_and_trailing_underscore (двойное подчеркивание в начале и в конце имени): «волшебные» объекты или атрибуты, которые «живут» в пространствах имен, управляемых пользователем (user-controlled namespaces). Например, init, import или file. Не изобретайте такие имена, используйте их только так, как написано в документации.

Имена, которых следует избегать

Никогда не используйте символы l (малелькая латинская буква «эль»), O (заглавная латинская буква «о») или I (заглавная латинская буква «ай») как однобуквенные идентификаторы.

В некоторых шрифтах эти символы неотличимы от цифры один и нуля (и символа вертикальной палочки, — прим. перев.) Если очень нужно использовать l имена, пишите вместо неё заглавную L.

Имена модулей и пакетов

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

Так как имена модулей отображаются в имена файлов, а некоторые файловые системы являются нечувствительными к регистру символов и обрезают длинные имена, очень важно использовать достаточно короткие имена модулей — это не проблема в Unix, но, возможно, код окажется непереносимым в старые версии Windows или Mac, или DOS. Когда модуль расширения, написанный на С или C++, имеет сопутствующий python-модуль (содержащий интерфейс высокого уровня), С/С++ модуль начинается с символа подчеркивания, например, _socket.

Все имена классов должны следовать соглашению CapWords почти без исключений. Классы внутреннего использования могут начинаться с символа подчеркивания.

Имена исключений (exceptions)

Так как исключения являются классами, к исключениями применяется стиль именования классов. Однако вы можете добавить Error в конце имени (если конечно исключение действительно является ошибкой).

Имена глобальных переменных

Будем надеяться, что такие имена используются только внутри одного модуля. Руководствуйтесь теми же соглашениями, что и для имен функций.

Добавляйте в модули, которые написаны так, чтобы их использовали с помощью from M import *, механизм all чтобы предотвратить экспортирование глобальных переменных. Или же, используйте старое соглашение, добавляя перед именами таких глобальных переменных один символ подчеркивания (которым вы можете обозначить те глобальные переменные, которые используются только внутри модуля).

Имена функций должны состоять из маленьких букв, а слова разделяться символами подчеркивания — это необходимо, чтобы увеличить читабельность.

Стиль mixedCase допускается в тех местах, где уже преобладает такой стиль, например во threading.py, для сохранения обратной совместимости.

Аргументы функций и методов

Всегда используйте self в качестве первого аргумента метода экземпляра объекта (instance method).

Всегда используйте cls в качестве первого аргумента метода класса (class method).

Если имя аргумента конфликтует с зарезервированным ключевым словом python, обычно лучше добавить в конец имени символ подчеркивания, чем исказить написание слова или использовать аббревиатуру. Таким образом, print_ лучше, чем prnt. (Возможно, хорошим вариантом будет подобрать синоним).

Имена методов и переменные экземпляров классов

Используйте тот же стиль, что и для имен функций: имена должны состоять из маленьких букв, а слова разделяться символами подчеркивания.

Чтобы избежать конфликта имен с подклассами, добавьте два символа подчеркивания, чтобы включить механизм изменения имен. Если класс Foo имя атрибут с именем __foo, к нему нельзя обратиться, написав Foo.__a. (Настойчивый пользователь всё равно может получить доступ, написав Foo._Foo__a). Вообще, двойное подчеркивание в именах должно использоваться, чтобы избежать конфликта имен с атрибутами классов, спроектированных так, чтобы от них наследовали подклассы.

Константы обычно объявляются на уровне модуля и записываются только заглавными буквами, а слова разделяются символами подчеркивания. Например: MAX_OVERFLOW, TOTAL.

Обязательно решите, каким должен быть метод класса или переменная экземпляра класса (в общем, атрибут) — public или не-public. Если вы сомневаетесь, выберите закрытый, не-public атрибут. Потом будет проще сделать их public, чем наоборот.

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

Мы не используем термин «закрытый член» (private), потому что на самом деле в python таких членов не бывает.

Другой тип аттрибутов классов принадлежит так называемому API подклассов (в других языках они часто называются protected). Некоторые классы проектируются так, чтобы от них наследовали другие классы, которые расширяют или модифицируют поведение базового класса. Когда вы проектируете такой класс, решите и явно укажите, какие атрибуты являются открытыми (public), какие принадлежат API подклассов (subclass API), а какие используются только базовым классом.

Теперь сформулируем рекомендации:

Открытые атрибуты не должны иметь в начале имени символа подчеркивания

Если имя открытого атрибута конфликтует с ключевым словом языка, добавьте в конец имени один символ подчеркивания. Это более предпочтительно, чем аббревиатура или искажение написания (однако, у этого правила есть исключение — аргумента который означает класс, и особенно первый аргумент метода класса (class method) должен иметь имя cls).

Назовите простые открытые атрибуты понятными именами и не пишите сложные методы доступа и изменения (accessor/mutator, get/set, — прим. перев.) Помните, что в python очень легко добавить их потом, если потребуется. В этом случае используйте свойства (properties), чтобы скрыть функциональную реализацию за синтаксисом доступа к атрибутам.

Свойства (properties) работают только в классах нового стиля (new-style classes)

Постарайтесь избавиться от побочных эффектов, связанным с функциональным поведением; впрочем, такие вещи, как кэширование, вполне допустимы.

Избегайте использования вычислительно затратных операций, потому что из-за записи с помощью атрибутов создается впечатление, что доступ происходит (относительно) быстро.

Если вы планируете класс таким образом, чтобы от него наследовались другие классы, но не хотите, чтобы подклассы унаследовали некоторые атрибуты, добавьте в имена два символа подчеркивания в начало, и ни одного — в конец. Механизм изменения имен в python (name mangling, — прим. перев.) сработает так, что имя класса добавится к имени такого атрибута, что позволит избежать конфликта имен с атрибутами подклассов.

Будьте внимательны: если подкласс будет иметь то же имя класса и имя атрибута, то вновь возникнет конфликт имен.

Механизм изменения имен может затруднить отладку или работу с getattr(), однако он хорошо документирован и легко реализуется вручную.

Не всем нравится этот механизм, поэтому старайтесь достичь компромисса между необходимостью избежать конфликта имен и возможностью доступа к этим атрибутам.

Код должен быть написан так, чтобы не зависеть от разных реализация языка (PyPy, Jython, IronPython, Pyrex, Psyco и пр.). Например, не полагайтесь на эффективную реализацию в CPython конкатенации строк в выражениях типа a+=b или a=a+b. Такие инструкции выполняются значительно медленнее в Jython. В критичных к времени выполнения частях программы используйте ».join() — таким образом склеивание строк будет выполнено за линейное время независимо от реализации python.

Сравнения с None должны обязательно выполняться с использованием операторов is или is not, а не с помощью операторов равенства или неравенства. Кроме того, не пишите if x, если имеете в виду if x is not None — если, к примеру, при тестировании такая переменная или аргумент примет значение иного типа, то при приведении к булевскому типу получится false.

Создавайте исключения на основе классов. Впрочем, начиная с версии python 2.6, мы уже не можем использовать строки в качестве исключений. В модулях или пакетах создавайте свои базовые классы исключений, наследуя их от встроенного класса Exception и обязательно их документируйте:

Здесь применимы те же правила, что и для именования классов. Если исключение по своему смыслу является ошибкой, вы можете добавить в конце имени Error.

Когда вы генерируете исключение, пишите raise ValueError(‘message’) вместо старого синтаксиса raise ValueError, message. Такое использование предпочтительнее, потому что из-за скобок не нужно использовать символы для продолжения перенесенных строк, если эти строки длинные или если используется форматирование. Старая форма записи запрещена в python 3000.

Когда код перехватывает исключения, «ловите» конкретные ошибки вместо простого выражнения except:. К примеру, пишите вот так:

Простое написание ‘except:’ также перехватит и SystemExit, и KeyboardInterrupt, что породит проблемы, например, сложнее будет завершить программу нажатием control+C. Если вы действительно собираетесь перехватить все исключения, пишите ‘except Exception:’.

Ограничьтесь использованием чистого ‘except:’ в двух случаях:

  1. Если обработчик исключения выводит пользователю всё о случившейся ошибке (например, traceback)
  2. Если нужно выполнить некоторый код после перехвата исключения, а потом вновь «бросить» его для обработки где-то в другом месте. Обычно же лучше пользоваться конструкцией try. finally . Постарайтесь заключать в каждую конструкцию try. except минимум кода, чтобы легче отлавливать ошибки.

Используйте строковые методы вместо модуля string — они всегда быстрее и имеют тот же API для unicode-строк. Можно отказаться от этого правила, если необходима совместимость с версиями python младше 2.0.

Пользуйтесь ».startswith() и ».endswith() вместо обработки частей строк (string slicing) для проверки суффиксов или префиксов. startswith() и endswith() выглядят чище и порождают меньше ошибок. Например:

Сравнение типов объектов нужно делать с помощью isinstance(), а не прямым сравнением типов:

Для последовательностей (строк, списков, кортежей) можно использовать тот факт, что пустая последовательность есть false:

Не пользуйтесь строковыми константами, которые имеют важные пробелы в конце — они невидимы, а многие редакторы (а теперь и reindent.py) обрезают их.

Не сравнивайте логические типы с True и False с помощью ==:

Модуль: любой файл *.py. Имя модуля — имя этого файла.

Встроенный модуль: «модуль», который был написан на Си, скомпилирован и встроен в интерпретатор Python, и потому не имеет файла *.py.

Пакет: любая папка, которая содержит файл init.py. Имя пакета — имя папки.

С версии Python 3.3 любая папка (даже без init.py) считается пакетом.

Объект: в Python почти всё является объектом — функции, классы, переменные и т. д.

Пример структуры директорий

Обратите внимание, что в корневой папке test/ нет файла __init__.py .

Что делает import

При импорте модуля Python выполняет весь код в нём. При импорте пакета Python выполняет код в файле пакета init.py, если такой имеется. Все объекты, определённые в модуле или init.py, становятся доступны импортирующему.

Встроенные функции Python: какие нужно знать и на какие не стоит тратить время

Основы import и sys.path

Вот как оператор import производит поиск нужного модуля или пакета согласно документации Python:

При импорте модуля spam интерпретатор сначала ищёт встроенный модуль с таким именем. Если такого модуля нет, то идёт поиск файла spam.py в списке директорий, определённых в переменной sys.path. sys.path инициализируется из следующих мест:

  • директории, содержащей исходный скрипт (или текущей директории, если файл не указан);
  • директории по умолчанию, которая зависит от дистрибутива Python;
  • PYTHONPATH (список имён директорий; имеет синтаксис, аналогичный переменной окружения PATH).

Программы могут изменять переменную sys.path после её инициализации. Директория, содержащая запускаемый скрипт, помещается в начало поиска перед путём к стандартной библиотеке. Это значит, что скрипты в этой директории будут импортированы вместо модулей с такими же именами в стандартной библиотеке.

Технически документация не совсем полна. Интерпретатор будет искать не только файл (модуль) spam.py , но и папку (пакет) spam.

Обратите внимание, что Python сначала производит поиск среди встроенных модулей — тех, которые встроены непосредственно в интерпретатор. Список встроенных модулей зависит от дистрибутива Python, а найти этот список можно в sys.builtin_module_names (Python 2 и Python 3). Обычно в дистрибутивах есть модули sys (всегда включён в дистрибутив), math , itertools , time и прочие.

В отличие от встроенных модулей, которые при поиске проверяются первыми, остальные (не встроенные) модули стандартной библиотеки проверяются после директории запущенного скрипта. Это приводит к сбивающему с толку поведению: возможно «заменить» некоторые, но не все модули стандартной библиотеки. Допустим, модуль math является встроенным модулем, а random — нет. Таким образом, import math в start.py импортирует модуль из стандартной библиотеки, а не наш файл math.py из той же директории. В то же время, import random в start.py импортирует наш файл random.py .

Кроме того, импорты в Python регистрозависимы: import Spam и import spam — разные вещи.

Функцию pkgutil.iter_modules() (Python 2 и Python 3) можно использовать, чтобы получить список всех модулей, которые можно импортировать из заданного пути:

Чуть подробнее о sys.path

Чтобы увидеть содержимое sys.path , запустите этот код:

Документация Python описывает sys.path так:

Список строк, указывающих пути для поиска модулей. Инициализируется из переменной окружения PYTHONPATH и директории по умолчанию, которая зависит от дистрибутива Python.

При запуске программы после инициализации первым элементом этого списка, path[0] , будет директория, содержащая скрипт, который был использован для вызова интерпретатора Python. Если директория скрипта недоступна (например, если интерпретатор был вызван в интерактивном режиме или скрипт считывается из стандартного ввода), то path[0] является пустой строкой. Из-за этого Python сначала ищет модули в текущей директории. Обратите внимание, что директория скрипта вставляется перед путями, взятыми из PYTHONPATH .

Документация к интерфейсу командной строки Python добавляет информацию о запуске скриптов из командной строки. В частности, при запуске python <script>.py.

Если имя скрипта ссылается непосредственно на Python-файл, то директория, содержащая этот файл, добавляется в начало sys.path, а файл выполняется как модуль main.

Итак, повторим порядок, согласно которому Python ищет импортируемые модули:

  • Модули стандартной библиотеки (например, math, os).
  • Модули или пакеты, указанные в sys.path:

Если интерпретатор Python запущен в интерактивном режиме:

sys.path[0] — пустая строка ». Это значит, что Python будет искать в текущей рабочей директории, из которой вы запустили интерпретатор. В Unix-системах эту директорию можно узнать с помощью команды pwd.

Если мы запускаем скрипт командой python <script>.py :

sys.path[0] — это путь к <script>.py .

Директории, указанные в переменной среды PYTHONPATH.

Директория по умолчанию, которая зависит от дистрибутива Python.

Обратите внимание, что при запуске скрипта для sys.path важна не директория, в которой вы находитесь, а путь к самому скрипту. Например, если в командной строке мы находимся в test/folder и запускаем команду python ./packA/subA/subA1.py , то sys.path будет включать в себя test/packA/subA/ , но не test/ .

Кроме того, sys.path общий для всех импортируемых модулей. Допустим, мы вызвали python start.py . Пусть start.py импортирует packA.a1 , а a1.py выводит на экран sys.path . В таком случае sys.path будет включать test/ (путь к start.py ), но не test/packA (путь к a1.py ). Это значит, что a1.py может вызвать import other , так как other.py находится в test/ .

Всё о __init__.py

У файла __init__.py есть две функции:

  • Превратить папку со скриптами в импортируемый пакет модулей (до Python 3.3).
  • Выполнить код инициализации пакета.

Превращение папки со скриптами в импортируемый пакет модулей

Чтобы импортировать модуль (или пакет) из директории, которая находится не в директории нашего скрипта (или не в директории, из которой мы запускаем интерактивный интерпретатор), этот модуль должен быть в пакете.

Как было сказано ранее, любая директория, содержащая файл __init__.py , является пакетом. Например, при работе с Python 2.7 start.py может импортировать пакет packA , но не packB , так как в директории test/packB/ нет файла __init__.py .

Это не относится к Python 3.3 и выше благодаря появлению неявных пакетов пространств имён. Проще говоря, в Python 3.3+ все папки считаются пакетами, поэтому пустые файлы __init__.py больше не нужны.

Допустим, packB — пакет пространства имён, так как в нём нет __init__.py . Если запустить интерактивную оболочку Python 3.6 в директории test/ , то мы увидим следующее:

Выполнение кода инициализации пакета

В момент, когда пакет или один из его модулей импортируется в первый раз, Python выполняет init.py в корне пакета, если такой файл существует. Все объекты и функции, определённые в __init__.py , считаются частью пространства имён пакета.

Рассмотрим следующий пример:

Вывод после запуска python start.py:

Примечание Если a1.py вызовет import a2, и мы запустим python a1.py, то test/packA/init.py не будет вызван, несмотря на то, что a2 вроде бы является частью пакета packA. Это связано с тем, что когда Python выполняет скрипт (в данном случае a1.py), содержащая его папка не считается пакетом.

Использование объектов из импортированного модуля или пакета

Есть 4 разных вида импортов:

  • import <пакет>
  • import <модуль>
  • from <пакет> import <модуль или подпакет или объект>
  • from <модуль> import <объект>

Пусть X — имя того, что идёт после import:

Если X — имя модуля или пакета, то для того, чтобы использовать объекты, определённые в X, придётся писать X.объект.

Если X — имя переменной, то её можно использовать напрямую.

Если X — имя функции, то её можно вызвать с помощью X().

Опционально после любого выражения import X можно добавить as Y . Это переименует X в Y в пределах скрипта. Учтите, что имя X с этого момента становится недействительным. Частым примером такой конструкции является import numpy as np .

Аргументом для import может быть как одно имя, так и их список. Каждое из имён можно переименовать с помощью as . Например, следующее выражение будет действительно в start.py : import packA as pA, packA.a1, packA.subA.sa1 as sa1 .

Пример: нужно в start.py импортировать функцию helloWorld() из sa1.py .

Решение 1: from packA.subA.sa1 import helloWorld . Мы можем вызвать функцию напрямую по имени: x = helloWorld() .

Решение 2: from packA.subA import sa1 или то же самое import packA.subA.sa1 as sa1 . Для использования функции нам нужно добавить перед её именем имя модуля: x = sa1.helloWorld(). Иногда такой подход предпочтительнее первого, так как становится ясно, из какого модуля взялась та или иная функция.

Решение 3: import packA.subA.sa1 . Для использования функции перед её именем нужно добавить полный путь: x = packA.subA.sa1.helloWorld() .

Используем dir() для исследования содержимого импортированного модуля

После импортирования модуля можно использовать функцию dir() для получения списка доступных в модуле имён. Допустим, мы импортируем sa1 . Если в sa1.py есть функция helloWorld() , то dir(sa1) будет включать helloWorld :

Импортирование пакета по сути равноценно импортированию его __init__.py . Вот как Python на самом деле видит пакет:

После импорта становятся доступны только те объекты, что определены в __init__.py пакета. Поскольку в packB нет такого файла, от import packB (в Python 3.3.+) будет мало толку, так как никакие объекты из этого пакета не становятся доступны. Последующий вызов модуля packB.b1 приведёт к ошибке, так как он ещё не был импортирован.

Абсолютный и относительный импорт

При абсолютном импорте используется полный путь (от начала корневой папки проекта) к желаемому модулю.

При относительном импорте используется относительный путь (начиная с пути текущего модуля) к желаемому модулю. Есть два типа относительных импортов:

При явном импорте используется формат from .<модуль/пакет> import X, где символы точки . показывают, на сколько директорий «вверх» нужно подняться. Одна точка . показывает текущую директорию, две точки .. — на одну директорию выше и т. д.

Неявный относительный импорт пишется так, как если бы текущая директория была частью sys.path. Такой тип импортов поддерживается только в Python 2.

В документации Python об относительных импортах в Python 3 написано следующее:

Единственный приемлемый синтаксис для относительных импортов — from .[модуль] import [имя]. Все импорты, которые начинаются не с точки ., считаются абсолютными.

В качестве примера допустим, что мы запускаем start.py , который импортирует a1 , который импортирует other , a2 и sa1 . Тогда импорты в a1.py будут выглядеть следующим образом:

Явные относительные импорты:

Неявные относительные импорты (не поддерживаются в Python 3):

Учтите, что в относительных импортах с помощью точек . можно дойти только до директории, содержащей запущенный из командной строки скрипт (не включительно). Таким образом, from .. import other не сработает в a1.py. В результате мы получим ошибку ValueError: attempted relative import beyond top-level package.

Как правило, абсолютные импорты предпочтительнее относительных. Они позволяют избежать путаницы между явными и неявными импортами. Кроме того, любой скрипт с явными относительными импортами нельзя запустить напрямую:

Имейте в виду, что относительные импорты основаны на имени текущего модуля. Так как имя главного модуля всегда «main«, модули, которые должны использоваться как главный модуль приложения, должны всегда использовать абсолютные импорты.

Читать:
Циклическое перенаправление на странице что делать

Похожие статьи