|
|||||||
PEP 8 - руководство по написанию кода на Python
Время создания: 29.07.2019 23:51
Раздел: Разные закладки - Python
Запись: xintrea/mytetra_db_adgaver_new/master/base/1533760905yairl3rfzc/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Этот документ описывает соглашение о том, как писать код для языка python, включая стандартную библиотеку, входящую в состав python. PEP 8 создан на основе рекомендаций Гуидо ван Россума с добавлениями от Барри. Если где-то возникал конфликт, мы выбирали стиль Гуидо. И, конечно, этот PEP может быть неполным (фактически, он, наверное, никогда не будет закончен). Ключевая идея Гуидо такова: код читается намного больше раз, чем пишется. Собственно, рекомендации о стиле написания кода направлены на то, чтобы улучшить читаемость кода и сделать его согласованным между большим числом проектов. В идеале, весь код будет написан в едином стиле, и любой сможет легко его прочесть. Это руководство о согласованности и единстве. Согласованность с этим руководством очень важна. Согласованность внутри одного проекта еще важнее. А согласованность внутри модуля или функции — самое важное. Но важно помнить, что иногда это руководство неприменимо, и понимать, когда можно отойти от рекомендаций. Когда вы сомневаетесь, просто посмотрите на другие примеры и решите, какой выглядит лучше. Две причины для того, чтобы нарушить данные правила:
Используйте 4 пробела на каждый уровень отступа. Продолжительные строки должны выравнивать обернутые элементы либо вертикально, используя неявную линию в скобках (круглых, квадратных или фигурных), либо с использованием висячего отступа. При использовании висячего отступа следует применять следующие соображения: на первой линии не должно быть аргументов, а остальные строки должны четко восприниматься как продолжение линии. Правильно: # Выровнено по открывающему разделителю foo = long_function_name(var_one, var_two, var_three, var_four) # Больше отступов включено для отличения его от остальных def long_function_name( var_one, var_two, var_three, var_four): print(var_one) Неправильно: # Аргументы на первой линии запрещены, если не используется вертикальное выравнивание foo = long_function_name(var_one, var_two, var_three, var_four) # Больше отступов требуется, для отличения его от остальных def long_function_name( var_one, var_two, var_three, var_four): print(var_one) Опционально: # Нет необходимости в большем количестве отступов. foo = long_function_name( var_one, var_two, var_three, var_four) Закрывающие круглые/квадратные/фигурные скобки в многострочных конструкциях могут находиться под первым непробельным символом последней строки списка, например: my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', ) либо быть под первым символом строки, начинающей многострочную конструкцию: my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', ) Пробелы - самый предпочтительный метод отступов. Табуляция должна использоваться только для поддержки кода, написанного с отступами с помощью табуляции. Python 3 запрещает смешивание табуляции и пробелов в отступах. Python 2 пытается преобразовать табуляцию в пробелы. Когда вы вызываете интерпретатор Python 2 в командной строке с параметром -t, он выдает предупреждения (warnings) при использовании смешанного стиля в отступах, а запустив интерпретатор с параметром -tt, вы получите в этих местах ошибки (errors). Эти параметры очень рекомендуются! Ограничьте длину строки максимум 79 символами. Для более длинных блоков текста с меньшими структурными ограничениями (строки документации или комментарии), длину строки следует ограничить 72 символами. Ограничение необходимой ширины окна редактора позволяет иметь несколько открытых файлов бок о бок, и хорошо работает при использовании инструментов анализа кода, которые предоставляют две версии в соседних столбцах. Некоторые команды предпочитают большую длину строки. Для кода, поддерживающегося исключительно или преимущественно этой группой, в которой могут прийти к согласию по этому вопросу, нормально увеличение длины строки с 80 до 100 символов (фактически увеличивая максимальную длину до 99 символов), при условии, что комментарии и строки документации все еще будут 72 символа. Стандартная библиотека Python консервативна и требует ограничения длины строки в 79 символов (а строк документации/комментариев в 72). Предпочтительный способ переноса длинных строк является использование подразумеваемых продолжений строк Python внутри круглых, квадратных и фигурных скобок. Длинные строки могут быть разбиты на несколько строк, обернутые в скобки. Это предпочтительнее использования обратной косой черты для продолжения строки. Обратная косая черта все еще может быть использована время от времени. Например, длинная конструкция with не может использовать неявные продолжения, так что обратная косая черта является приемлемой: with open('/path/to/some/file/you/want/to/read') as file_1, \ open('/path/to/some/file/being/written', 'w') as file_2: file_2.write(file_1.read()) Ещё один случай - assert. Сделайте правильные отступы для перенесённой строки. Предпочтительнее вставить перенос строки после логического оператора, но не перед ним. Например: class Rectangle(Blob): def __init__(self, width, height, color='black', emphasis=None, highlight=0): if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong' or highlight > 100): raise ValueError("sorry, you lose") if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) Blob.__init__(self, width, height, color, emphasis, highlight) Отделяйте функции верхнего уровня и определения классов двумя пустыми строками. Определения методов внутри класса разделяются одной пустой строкой. Дополнительные пустые строки возможно использовать для разделения различных групп похожих функций. Пустые строки могут быть опущены между несколькими связанными однострочниками (например, набор фиктивных реализаций). Используйте пустые строки в функциях, чтобы указать логические разделы. Python расценивает символ control+L как незначащий (whitespace), и вы можете использовать его, потому что многие редакторы обрабатывают его как разрыв страницы — таким образом логические части в файле будут на разных страницах. Однако, не все редакторы распознают control+L и могут на его месте отображать другой символ. Кодировка Python должна быть UTF-8 (ASCII в Python 2). Файлы в ASCII (Python 2) или UTF-8 (Python 3) не должны иметь объявления кодировки. В стандартной библиотеке, нестандартные кодировки должны использоваться только для целей тестирования, либо когда комментарий или строка документации требует упомянуть имя автора, содержащего не ASCII символы; в остальных случаях использование \x, \u, \U или \N - наиболее предпочтительный способ включить не ASCII символы в строковых литералах. Начиная с версии python 3.0 в стандартной библиотеке действует следующее соглашение: все идентификаторы обязаны содержать только ASCII символы, и означать английские слова везде, где это возможно (во многих случаях используются сокращения или неанглийские технические термины). Кроме того, строки и комментарии тоже должны содержать лишь ASCII символы. Исключения составляют: (а) test case, тестирующий не-ASCII особенности программы, и (б) имена авторов. Авторы, чьи имена основаны не на латинском алфавите, должны транслитерировать свои имена в латиницу. Проектам с открытым кодом для широкой аудитории также рекомендуется использовать это соглашение.
Правильно: import os import sys Неправильно: import sys, os В то же время, можно писать так: from subprocess import Popen, PIPE Импорты должны быть сгруппированы в следующем порядке: Вставляйте пустую строку между каждой группой импортов. Указывайте спецификации __all__ после импортов. import mypkg.sibling from mypkg import sibling from mypkg.sibling import example Тем не менее, явный относительный импорт является приемлемой альтернативой абсолютному импорту, особенно при работе со сложными пакетами, где использование абсолютного импорта было бы излишне подробным: from . import sibling from .sibling import example В стандартной библиотеке следует избегать сложной структуры пакетов и всегда использовать абсолютные импорты. Неявные относительно импорты никогда не должны быть использованы, и были удалены в Python 3. from myclass import MyClass from foo.bar.yourclass import YourClass Если такое написание вызывает конфликт имен, тогда пишите: import myclass import foo.bar.yourclass И используйте "myclass.MyClass" и "foo.bar.yourclass.YourClass". Пробелы в выражениях и инструкциях Избегайте использования пробелов в следующих ситуациях:
Правильно: spam(ham[1], {eggs: 2}) Неправильно: spam( ham[ 1 ], { eggs: 2 } ) Правильно: if x == 4: print(x, y); x, y = y, x Неправильно: if x == 4 : print(x , y) ; x , y = y , x Правильно: spam(1) Неправильно: spam (1) Правильно: dict['key'] = list[index] Неправильно: dict ['key'] = list [index] Правильно: x = 1 y = 2 long_variable = 3 Неправильно: x = 1 y = 2 long_variable = 3
Правильно: i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b) Неправильно: i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b) Правильно: def complex(real, imag=0.0): return magic(r=real, i=imag) Неправильно: def complex(real, imag = 0.0): return magic(r = real, i = imag) Правильно: if foo == 'blah': do_blah_thing() do_one() do_two() do_three() Неправильно: if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three() Точно неправильно: if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay() Вероятно, неправильно: if foo == 'blah': do_blah_thing() else: do_non_blah_thing() try: something() finally: cleanup() do_one(); do_two(); do_three(long, argument, list, like, this) if foo == 'blah': one(); two(); three() Комментарии, противоречащие коду, хуже, чем отсутствие комментариев. Всегда исправляйте комментарии, если меняете код! Комментарии должны являться законченными предложениями. Если комментарий — фраза или предложение, первое слово должно быть написано с большой буквы, если только это не имя переменной, которая начинается с маленькой буквы (никогда не изменяйте регистр переменной!). Если комментарий короткий, можно опустить точку в конце предложения. Блок комментариев обычно состоит из одного или более абзацев, составленных из полноценных предложений, поэтому каждое предложение должно оканчиваться точкой. Ставьте два пробела после точки в конце предложения. Программисты, которые не говорят на английском языке, пожалуйста, пишите комментарии на английском, если только вы не уверены на 120%, что ваш код никогда не будут читать люди, не знающие вашего родного языка. Блок комментариев обычно объясняет код (весь, или только некоторую часть), идущий после блока, и должен иметь тот же отступ, что и сам код. Каждая строчка такого блока должна начинаться с символа # и одного пробела после него (если только сам текст комментария не имеет отступа). Абзацы внутри блока комментариев разделяются строкой, состоящей из одного символа #. Старайтесь реже использовать подобные комментарии. Такой комментарий находится в той же строке, что и инструкция. "Встрочные" комментарии должны отделяться по крайней мере двумя пробелами от инструкции. Они должны начинаться с символа # и одного пробела. Комментарии в строке с кодом не нужны и только отвлекают от чтения, если они объясняют очевидное. Не пишите вот так: x = x + 1 # Increment x Впрочем, такие комментарии иногда полезны: x = x + 1 # Компенсация границы
"""Return a foobang Optional plotz says to frobnicate the bizbaz first. """ Если вам нужно использовать Subversion, CVS или RCS в ваших исходных кодах, делайте вот так: __version__ = "$Revision: 1a40d4eaa00b $" # $Source$ Вставляйте эти строки после документации модуля перед любым другим кодом и отделяйте их пустыми строками по одной до и после. Соглашения по именованию переменных в python немного туманны, поэтому их список никогда не будет полным — тем не менее, ниже мы приводим список рекомендаций, действующих на данный момент. Новые модули и пакеты должны быть написаны согласно этим стандартам, но если в какой-либо уже существующей библиотеке эти правила нарушаются, предпочтительнее писать в едином с ней стиле. Имена, которые видны пользователю как часть общественного API должны следовать конвенциям, которые отражают использование, а не реализацию. Существует много разных стилей. Поможем вам распознать, какой стиль именования используется, независимо от того, для чего он используется. Обычно различают следующие стили:
Ещё существует стиль, в котором имена, принадлежащие одной логической группе, имеют один короткий префикс. Этот стиль редко используется в python, но мы упоминаем его для полноты. Например, функция os.stat() возвращает кортеж, имена в котором традиционно имеют вид st_mode, st_size, st_mtime и так далее. (Так сделано, чтобы подчеркнуть соответствие этих полей структуре системных вызовов POSIX, что помогает знакомым с ней программистам). В библиотеке X11 используется префикс Х для всех public-функций. В python этот стиль считается излишним, потому что перед полями и именами методов стоит имя объекта, а перед именами функций стоит имя модуля. В дополнение к этому, используются следующие специальные формы записи имен с добавлением символа подчеркивания в начало или конец имени:
Tkinter.Toplevel(master, class_='ClassName') Предписания: соглашения по именованию Имена, которых следует избегать Никогда не используйте символы l (маленькая латинская буква «эль»), O (заглавная латинская буква «о») или I (заглавная латинская буква «ай») как однобуквенные идентификаторы. В некоторых шрифтах эти символы неотличимы от цифры один и нуля. Если очень нужно l, пишите вместо неё заглавную L. Модули должны иметь короткие имена, состоящие из маленьких букв. Можно использовать символы подчеркивания, если это улучшает читабельность. То же самое относится и к именам пакетов, однако в именах пакетов не рекомендуется использовать символ подчёркивания. Так как имена модулей отображаются в имена файлов, а некоторые файловые системы являются нечувствительными к регистру символов и обрезают длинные имена, очень важно использовать достаточно короткие имена модулей — это не проблема в Unix, но, возможно, код окажется непереносимым в старые версии Windows, Mac, или DOS. Когда модуль расширения, написанный на С или C++, имеет сопутствующий python-модуль (содержащий интерфейс высокого уровня), С/С++ модуль начинается с символа подчеркивания, например, _socket. Имена классов должны обычно следовать соглашению CapWords. Вместо этого могут использоваться соглашения для именования функций, если интерфейс документирован и используется в основном как функции. Обратите внимание, что существуют отдельные соглашения о встроенных именах: большинство встроенных имен - одно слово (либо два слитно написанных слова), а соглашение CapWords используется только для именования исключений и встроенных констант. Так как исключения являются классами, к исключениями применяется стиль именования классов. Однако вы можете добавить Error в конце имени (если, конечно, исключение действительно является ошибкой). Будем надеяться, что глобальные переменные используются только внутри одного модуля. Руководствуйтесь теми же соглашениями, что и для имен функций. Добавляйте в модули, которые написаны так, чтобы их использовали с помощью from M import *, механизм __all__, чтобы предотвратить экспортирование глобальных переменных. Или же, используйте старое соглашение, добавляя перед именами таких глобальных переменных один символ подчеркивания (которым вы можете обозначить те глобальные переменные, которые используются только внутри модуля). Имена функций должны состоять из маленьких букв, а слова разделяться символами подчеркивания — это необходимо, чтобы увеличить читабельность. Стиль mixedCase допускается в тех местах, где уже преобладает такой стиль, для сохранения обратной совместимости. Всегда используйте self в качестве первого аргумента метода экземпляра объекта. Всегда используйте cls в качестве первого аргумента метода класса. Если имя аргумента конфликтует с зарезервированным ключевым словом python, обычно лучше добавить в конец имени символ подчеркивания, чем исказить написание слова или использовать аббревиатуру. Таким образом, class_ лучше, чем clss. (Возможно, хорошим вариантом будет подобрать синоним). Имена методов и переменных экземпляров классов Используйте тот же стиль, что и для имен функций: имена должны состоять из маленьких букв, а слова разделяться символами подчеркивания. Используйте один символ подчёркивания перед именем для непубличных методов и атрибутов. Чтобы избежать конфликтов имен с подклассами, используйте два ведущих подчеркивания. Python искажает эти имена: если класс Foo имеет атрибут с именем __a, он не может быть доступен как Foo.__a. (Настойчивый пользователь все еще может получить доступ, вызвав Foo._Foo__a.) Вообще, два ведущих подчеркивания должны использоваться только для того, чтобы избежать конфликтов имен с атрибутами классов, предназначенных для наследования. Примечание: есть некоторые разногласия по поводу использования __ имена (см. ниже). Константы обычно объявляются на уровне модуля и записываются только заглавными буквами, а слова разделяются символами подчеркивания. Например: MAX_OVERFLOW, TOTAL. Обязательно решите, каким должен быть метод класса или экземпляра класса (далее - атрибут) — публичный или непубличный. Если вы сомневаетесь, выберите непубличный атрибут. Потом будет проще сделать его публичным, чем наоборот. Публичные атрибуты — это те, которые будут использовать другие программисты, и вы должны быть уверены в отсутствии обратной несовместимости. Непубличные атрибуты, в свою очередь, не предназначены для использования третьими лицами, поэтому вы можете не гарантировать, что не измените или не удалите их. Мы не используем термин "приватный атрибут", потому что на самом деле в python таких не бывает. Другой тип атрибутов классов принадлежит так называемому API подклассов (в других языках они часто называются protected). Некоторые классы проектируются так, чтобы от них наследовали другие классы, которые расширяют или модифицируют поведение базового класса. Когда вы проектируете такой класс, решите и явно укажите, какие атрибуты являются публичными, какие принадлежат API подклассов, а какие используются только базовым классом. Теперь сформулируем рекомендации:
Примечание 1: Свойства (properties) работают только в классах нового стиля (в Python 3 все классы являются таковыми). Примечание 2: Постарайтесь избавиться от побочных эффектов, связанным с функциональным поведением; впрочем, такие вещи, как кэширование, вполне допустимы. Примечание 3: Избегайте использования вычислительно затратных операций, потому что из-за записи с помощью атрибутов создается впечатление, что доступ происходит (относительно) быстро. Примечание 1: Будьте внимательны: если подкласс будет иметь то же имя класса и имя атрибута, то вновь возникнет конфликт имен. Примечание 2: Механизм изменения имен может затруднить отладку или работу с __getattr__(), однако он хорошо документирован и легко реализуется вручную. Примечание 3: Не всем нравится этот механизм, поэтому старайтесь достичь компромисса между необходимостью избежать конфликта имен и возможностью доступа к этим атрибутам.
Например, не полагайтесь на эффективную реализацию в CPython конкатенации строк в выражениях типа a+=b или a=a+b. Такие инструкции выполняются значительно медленнее в Jython. В критичных к времени выполнения частях программы используйте ''.join() — таким образом склеивание строк будет выполнено за линейное время независимо от реализации python. Для минимизации усилий можно воспользоваться декоратором functools.total_ordering() для реализации недостающих методов. PEP 207 указывает, что интерпретатор может поменять y > х на х < y, y >= х на х <= y, и может поменять местами аргументы х == y и х != y. Гарантируется, что операции sort() и min() используют оператор <, а max() использует оператор >. Однако, лучше всего осуществить все шесть операций, чтобы не возникало путаницы в других местах. Правильно: def f(x): return 2*x Неправильно: f = lambda x: 2*x Когда намеренно заменяется исключение (использование "raise X" в Python 2 или "raise X from None" в Python 3.3+), проследите, чтобы соответствующая информация передалась в новое исключение (такие, как сохранение имени атрибута при преобразовании KeyError в AttributeError или вложение текста исходного исключения в новом). Старая форма записи запрещена в python 3. Такое использование предпочтительнее, потому что из-за скобок не нужно использовать символы для продолжения перенесенных строк, если эти строки длинные или если используется форматирование. К примеру, пишите вот так: try: import platform_specific_module except ImportError: platform_specific_module = None Простое написание "except:" также перехватит и SystemExit, и KeyboardInterrupt, что породит проблемы, например, сложнее будет завершить программу нажатием control+C. Если вы действительно собираетесь перехватить все исключения, пишите "except Exception:". Хорошим правилом является ограничение использования "except:", кроме двух случаев: try: process_data() except Exception as exc: raise DataProcessingFailedError(str(exc)) Это единственный синтаксис, поддерживающийся в Python 3, который позволяет избежать проблем неоднозначности, связанных с более старым синтаксисом на основе запятой. Правильно: try: value = collection[key] except KeyError: return key_not_found(key) else: return handle_value(value) Неправильно: try: # Здесь много действий! return handle_value(collection[key]) except KeyError: # Здесь также перехватится KeyError, который может быть сгенерирован handle_value() return key_not_found(key) Правильно: with conn.begin_transaction(): do_stuff_in_transaction(conn) Неправильно: with conn: do_stuff_in_transaction(conn) Последний пример не дает никакой информации, указывающей на то, что __enter__ и __exit__ делают что-то кроме закрытия соединения после транзакции. Быть явным важно в данном случае. В Python 3 остались только строковые методы. startswith() и endswith() выглядят чище и порождают меньше ошибок. Например: Правильно: if foo.startswith('bar'): Неправильно: if foo[:3] == 'bar': Правильно: if isinstance(obj, int): Неправильно: if type(obj) is type(1): Когда вы проверяете, является ли объект строкой, обратите внимание на то, что строка может быть unicode-строкой. В python 2 у str и unicode есть общий базовый класс, поэтому вы можете написать: if isinstance(obj, basestring): Отметим, что в Python 3, unicode и basestring больше не существуют (есть только str) и bytes больше не является своего рода строкой (это последовательность целых чисел). Правильно: if not seq: if seq: Неправильно: if len(seq) if not len(seq) Правильно: if greeting: Неправильно: if greeting == True: Совсем неправильно: if greeting is True: |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|