Вебинары Разобраться в IT Реферальная программа
Программирование Аналитика Дизайн Маркетинг Управление проектами
03 Авг 2024
9 мин
9847

PEP8 для Python — правила красивого кода

Рассказываем, что такое стандарты PEP8 для языка Python и как их применять.

Сообщество приняло набор стилевых рекомендаций PEP8, который Гвидо ван Россум, создатель языка, предложил еще в 2001 году. Как применять и когда отступать — рассказываем в этой статье.

Что такое стандарты PEP8 для языка Python

С предсказуемым кодом приятно работать: сразу понятно, где импортированные модули, константа здесь или переменная и в каком блоке текущая строка. Для предсказуемости важны стиль и оформление, особенно в Python, который многое прощает разработчику.

Требования PEP8 по оформлению Python-кода

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

Чтобы оставаться востребованным специалистом, разработчику на любом языке нужно постоянно развиваться и совершенствовать навыки. А вот основы можно узнать и отработать на курсе Skypro «Python-разработчик». Программу составили практикующие разработчики, они же ведут уроки и объясняют всё простым и доступным языком. Так что освоить профессию на уровне уверенного новичка и найти работу можно через несколько месяцев с начала обучения.

Структура кода

В Python внутренние блоки кода выделяются отступами, а не специальными разделителями. Размер отступа — четыре пробела, табуляция не используется:

if (expression_is_true):
do_this()
elif (other_expression_is_true):
do_that()
else:
do_something_else()

Для удобства настройте табуляцию в любимом редакторе на проставление четырех пробелов.

Аргументы функций переносятся на следующую строку и выравниваются, если строка слишком длинная:

def long_func (arg_one, arg_two,
arg_three, arg_four)

def extra_long_function_name (
arg_one, arg_two, arg_three,
arg_four):
do_something()

Некоторые редакторы при переносе строки добавляют спецсимвол, поэтому вместо стандартных 80 символов максимальная длина строки в PEP8 — 79. Комментарии и документация — 72 символа.

Максимальную длину строки разрешается увеличить до 99 символов, если стандартные 79 ухудшают читаемость кода.

Знаки операций ставятся после переноса строки:

total_users = (currently_online
+ offline_but_active
+ offline_inactive
- duplicate_accounts
- banned)

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

do_stuff()
do_similar_stuff()

do_different_stuff()

do_something_else_entirely()

Правила выбора имен

По правильно названной переменной или функции сразу понятно, зачем они нужны: в first_name лежит имя, а calculate_employee_salary() считает зарплату сотрудника.

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

# Правильно

first_name = ‘Ivan’
last_name = ‘Ivanov’

def plus_one (x):
return x + 1

# Неправильно

fnm = ‘Ivan’
lnm = ‘Ivanov’

# Plus 1? Phase 1? Point 1?
def p1 (x):
return x + 1

Придерживайтесь этих стилей именования:

Тип Рекомендация Примеры
Функция Одно или несколько слов в нижнем регистре, нижние подчеркивания для улучшения читаемости (snake case) function, add_one
Переменная Одна буква, слово или несколько слов в нижнем регистре, нижние подчеркивания для улучшения читаемости x, connection, first_name
Класс Одно или несколько слов с большой буквы без пробелов (camel case) Image, UserData
Метод Одно или несколько слов в нижнем регистре, нижние подчеркивания для улучшения читаемости draw(), get_user_data()
Константа Одна буква, слово или несколько слов в верхнем регистре, нижние подчеркивания для улучшения читаемости PI, MAX_CONNECTIONS
Модуль Короткое слово или слова в нижнем регистре, нижние подчеркивания для улучшения читаемости module.py, user_data.py
Пакет Короткое слово или слова в нижнем регистре без подчеркиваний package, userdata

Проверка истинности без знаков равенства

Условия с булевыми значениями проверяются без оператора эквивалентности (==):

# Правильно

if this_is_true:
do_something()

if not this_is_false:
do_something_else()

# Неправильно

if this_is_true == True:
do_something()

if this_is_false == False:
do_something_else()

Сравнение с None делается с помощью операторов is / is not:

if connection is None:
print_error_message()

if user is not None:
get_user_data()

Пустой массив, список, словарь или строка — это False. С содержимым — уже True:

first_name = ‘’

if not first_name:
do_something () # выполнится
colors = [‘red’]

if colors:
do_something_else() # выполнится

Использование комментариев

Хороший комментарий — полезный комментарий. Пользуйтесь простым и понятным языком и не забывайте обновлять их, если код меняется. Рекомендации PEP8:

  1. Пишите полные предложения с заглавной буквы, если это не название.
  2. Ставьте два пробела после точки в комментариях, кроме последнего предложения.
  3. Пишите на английском, если читатели не знают ваш язык.

Блочные комментарии объясняют следующий за ними участок кода. Выравнивайте их на том же уровне и начинайте каждую строку с # и пробела. Параграфы в блочных комментариях разделяются строкой с одной #:

# Returns a filled UserData object for the current user ID if user exists, None otherwise. Assumes database connection is already open
#
# TODO: very poor performance, rewrite it!

def get_user_data (db_connection, user_id)

Не злоупотребляйте комментариями на той же строке (внутренними). Они не должны объяснять очевидных вещей и затруднять чтение кода. Отделяйте их от текста как минимум двумя пробелами и начинайте с # и пробела:

# Правильно

first_name = ‘Ivan’ # test user, shouldn’t show up in prod

# Неправильно
first_name = ‘Ivan’ # first name

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

В многострочных комментариях “”” в конце переносится на новую строку:

“””Run the provided database request. Scalar only!
For everything else, use db_query().
“””

В однострочных комментариях открывающие и закрывающие “”” — на той же строке:

“””Flush buffer and close the file”””

Выражения и инструкции

Стандартная кодировка для Python 3 — UTF8. В Python 2 — ASCII, которая не поддерживает кириллицу. Пользуйтесь Windows 1251 или аналогами:

# coding: cp1251
print (“Текст кириллицей”)

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

import os
from math import pi, sin

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

# Правильно

if this_is_true
and that_is_true
and something_else_is_true:
do_stuff();
do_other_stuff();

# Допустимо
if file_position < 0: file_position = 0 # file system quirk # Неправильно if this and that and something_else: do_stuff(); do_other_stuff() 

Изучайте Python на онлайн-курсе от Skypro «Python-разработчик». Программа рассчитана на новичков без опыта программирования и технического образования. Курс проходит в формате записанных коротких видеолекций. Будет много проверочных заданий и мастер-классов. В конце каждой недели — живая встреча с экспертами в разработке для ответов на вопросы и разбора домашек.

Использование запятых

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

# Правильно

TEST_USERS = (‘ivanov_i’, )

TEST_ACCOUNT_IDS = [

‘123’,

‘456’,

]

# Неправильно

TEST_USERS = ‘ivanov_i’,

TEST_ACCOUNT_IDS = [‘123’, ‘456’, ]

Рекомендации по программированию

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

def sum(a: int, b: int) -> int:
return a + b

Для типов переменных вставляйте один пробел после двоеточия. Знак присваивания окружается пробелами с обеих сторон:

# Правильно

user_count: int

class UserData:
first_name: str = ‘replace_me’
login_and_password_hash: Tuple[str, str]

# Неправильно

user_count:int
user_count : int

class UserData:
first_name: str=’’

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

# type: ignore

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

Другие рекомендации, на которые стоит обратить внимание:

  1. Используйте стандартную библиотеку, а не конкретную имплементацию (PyPy, CPython и т. д.).
  2. Реализуйте все операторы (__eq__, __ne__, __lt__, __le__, __gt__, __ge__) для сравнения элементов, не доверяйте внешнему коду в использовании только одного или нескольких.
  3. Определяйте функции ключевым словом def, а не знаком равенства: равенство оставляйте для лямбд.
  4. Наследуйте исключения от Exception вместо BaseException: BaseException зарезервировано для исключений, ловить которые — плохая идея.
  5. Сохраняйте стек вызовов при обработке цепочки исключений.
  6. Обрабатывайте конкретное исключение: слишком широкое условие (или пустой оператор except) поймает больше, чем нужно.
  7. Минимизируйте количество кода в try-блоке: в длинных условиях легче потеряться или проглотить ошибку.
  8. Очищайте локальные ресурсы с помощью with или try/finally.
  9. Вызывайте методы в менеджерах контекста явно. Исключение — резерв или возврат ресурса.
  10. Возвращайте единообразные значения: либо везде пустой return, либо везде результат или None.
  11. Проверяйте префиксы и суффиксы строк с помощью .startswith() и .endswith().
  12. Сравнивайте типы объектов через isinstance().
  13. Избегайте строковых литералов с пробельными символами в конце: некоторые редакторы и модули их обрежут.

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

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

  1. Среды разработки, например PyCharm.
  2. Pylint — для статического анализа и проверки стиля.
  3. Flake8 — для проверки стиля.

Pylint, Flake8 и многое другое лежит в разделе Python Code Quality Authority на гитхабе.

Когда можно проигнорировать соблюдение стандартов

Когда соблюдение стандартов ухудшает код. Помните: единообразный код понятнее и лучше читается. Например, PEP8 не применяется, если проект не доступен публично и уже использует другой стиль — или разрабатывался под старые версии Python. Для публичных библиотек PEP8 обязателен.

В проектах без единого стиля — договоритесь с командой и берите PEP8.

На курсе Skypro «Python-разработчик» можно научиться не только основам языка и разработки на нём, но и командной работе. А результаты практических заданий положить в портфолио, чтобы найти работу сразу после или даже во время обучения.

Коротко о главном

  1. Пишите единообразный код: его приятнее читать и легче воспринимать. PEP8 — стилевой стандарт сообщества.
  2. Выравнивайте блоки кода и отделяйте логические секции пустыми строками.
  3. Выбирайте понятные и однозначные имена для объектов.
  4. Добавляйте полезные комментарии. Обновляйте их, когда код меняется.
  5. Обрабатывайте исключения с узкими и краткими условиями.
  6. Берите автоматические инструменты проверки.
  7. Игнорируйте стандарты, если их соблюдение ухудшит код.
Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей

Добавить комментарий