PEP 8: нейминг и размещение кода

В предыдущей статье о PEP 8 мы узнали, что это за стандарт и в чем его важность. Также мы рассмотрели, каким образом можно привести код в соответствие с этим стандартом. В этой статье переходим к разбору конкретных рекомендаций по оформлению кода на Python. Мы рассмотрим, как выбирать имена, как делать вертикальные и горизонтальные отступы в коде, как переносить строки, где ставить закрывающие скобки.

Соглашения об именах

 «Явное лучше неявного», — Дзен Python.

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

Совет: никогда не используйте однобуквенные имена l, O или I, поскольку они могут быть ошибочно приняты за 1 и 0 при определённых шрифтах:

O = 2  # Выглядит так, будто вы пытаетесь присвоить нулю значение 2

Стили именования

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

ТипСоглашение о наименованииПримеры
ФункцияИспользуйте слово/слова в нижнем регистре. Отделяйте слова нижним подчёркиванием.function, my_function
ПеременнаяИспользуйте одну букву, слово или слова в нижнем регистре. Для удобства чтения разделяйте слова нижним подчеркиванием.x, var, my_variable
КлассКаждое слово начинайте с заглавной буквы. Не разделяйте слова подчеркиванием. Этот стиль называется Pascal Case.Model, MyClass
МетодИспользуйте слово/слова в нижнем регистре. Для удобства чтения разделяйте слова подчеркиванием.class_method, method
КонстантаИспользуйте одну букву, слово или слова в верхнем регистре. Для удобства чтения разделяйте слова подчеркиванием.CONSTANT, MY_CONSTANT, MY_LONG_CONSTANT
МодульИспользуйте короткое слово/слова в нижнем регистре. Для удобства чтения разделяйте слова подчеркиванием.module.py, my_module.py
ПакетИспользуйте короткие слова или слова в нижнем регистре. Не разделяйте слова подчеркиванием.package, mypackage

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

Стиль нейминга, безусловно, важен, но кроме того нужно тщательно выбирать сами имена. Ниже приведены несколько советов о том, как делать это максимально эффективно.

[python_ad_block]

Как выбирать имена

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

При именовании переменных у вас может возникнуть соблазн выбрать простые однобуквенные имена в нижнем регистре, например, x. Но если вы не используете x в качестве аргумента математической функции, непонятно, что он собой представляет. Представьте, что вы сохраняете имя человека в виде строки и хотите использовать срез, чтобы отформатировать его по-другому. У вас может получиться что-то вроде этого:

# Не рекомендуется
x = 'John Smith'
y, z = x.split()
print(z, y, sep=', ')
'Smith, John'

Это будет работать, но вам придётся разбираться, что собой представляют x, y и z. Это также может сбивать с толку ваших коллег. Более правильный выбор имен будет примерно таким:

# Рекомендуется
name = 'John Smith'
first_name, last_name = name.split()
print(last_name, first_name, sep=', ')
# 'Smith, John'

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

# Не рекомендуется
def db(x):
    return x * 2

На первый взгляд это могло показаться разумным выбором. db() легко может быть сокращением от double. Но представьте, что вы вернетесь к этому коду через несколько дней. Возможно, вы забыли, чего пытались достичь с помощью этой функции, и из-за этого будет сложно угадать, как вы ее сократили.

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

# Рекомендуется
def multiply_by_two(x):
    return x * 2

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

Размещение кода

 «Красивое лучше уродливого», — Дзен Python.

Расположение строк вашего кода играет огромную роль в его читабельности. В этом разделе вы узнаете, как добавлять отступы, чтобы улучшить читаемость кода. Вы также узнаете, как использовать ограничение в 79 символов в строке, рекомендованное в PEP 8.

Пустые строки

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

Окружайте функции и классы верхнего уровня двумя пустыми строками

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

class MyFirstClass:
    pass


class MySecondClass:
    pass


def top_level_function():
    return None

Разделяйте определения методов в классах одной пустой строкой

Внутри класса все функции связаны друг с другом. Рекомендуется оставлять между ними только одну строку:

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

Используйте пустые строки внутри функций, чтобы показать четкие шаги

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

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

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2

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

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

PEP 8 предлагает ограничение на длину строк в 79 символов. Такая длина позволяет открывать несколько файлов рядом друг с другом, а также избегать переноса строк.

Конечно, не все предложения возможно вместить в 79 или менее символов. В PEP 8 очерчивает способы написать длинное предложение, заняв несколько строк.

Если код заключен в круглые, квадратные или фигурные скобки, Python «поймет», что это одно предложение:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

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

from mypkg import example1, \
    example2, example3

Однако, если вы можете продолжить писать в одну строку, вам следует это сделать.

Если разрыв строки должен произойти около бинарных операторов, таких как + и *, он должен произойти перед оператором. Это правило происходит из математики. Математики согласны с тем, что прерывание перед бинарными операторами улучшает читаемость. Сравните следующие два примера.

Разрыв перед бинарным оператором:

# Рекомендуется
total = (first_variable
         + second_variable
         - third_variable)

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

Теперь давайте посмотрим на пример разрыва после бинарного оператора:

# Не рекомендуется
total = (first_variable +
         second_variable -
         third_variable)

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

Прерывание строки перед бинарными операторами дает более читаемый код, поэтому PEP 8 это поощряет.

Если вы переходите на новую строку после бинарного оператора, но делаете так последовательно во всем документе (проекте), это по-прежнему соответствует PEP 8. Но всё же рекомендуется первый вариант.

Отступы

 «Должен быть один – и желательно только один – очевидный способ сделать что-либо», — Дзен Python.

Отступы чрезвычайно важны в Python. Уровень отступа строк кода в Python определяет, как группируются операторы.

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

x = 3
if x > 5:
    print('x больше 5')

Оператор print с отступом сообщает Python, что он должен выполняться только в том случае, если if возвращает True. Тот же отступ применяется для указания Python, какой код выполнять при вызове функции или какой код принадлежит данному классу.

Ключевые правила отступов, изложенные в PEP 8, следующие:

  • Используйте 4 последовательных пробела для обозначения отступа.
  • Предпочитайте пробелы табуляции.

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

Как упоминалось выше, для отступа кода следует использовать пробелы вместо табуляции. Вы можете настроить параметры в текстовом редакторе таким образом, чтобы выводить 4 пробела вместо символа табуляции при нажатии клавиши Tab.

Если вы используете Python 2 и применяли сочетание табуляции и пробелов для отступа в коде, вы не увидите ошибок при попытке запустить этот код. Чтобы проверить согласованность, можно добавить флаг -t при запуске кода на Python 2 из командной строки. Если есть проблемы с использованием табуляции и пробелов, интерпретатор выдаст предупреждения:

$ python2 -t code.py
code.py: inconsistent use of tabs and spaces in indentation

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

$ python2 -tt code.py
  File "code.py", line 3
    print(i, j)
             ^
TabError: inconsistent use of tabs and spaces in indentation

Python 3 не позволяет смешивать табуляцию и пробелы. Поэтому, если вы используете Python 3, эти ошибки выдаются автоматически:

$ python3 code.py
  File "code.py", line 3
    print(i, j)
              ^
TabError: inconsistent use of tabs and spaces in indentation

При написании кода на Python для создания отступов можно использовать табуляцию, а можно и пробелы. Но если речь идет о Python 3, вы должны быть последовательны в своем выборе. В противном случае ваш код не запустится. PEP 8 рекомендует всегда использовать 4 последовательных пробела для обозначения отступа.

Отступ после разрывов строки

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

Первый из них — выровнять блок с отступом по открывающей скобке:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

Иногда может оказаться, что для выравнивания по открывающей скобке требуется всего 4 пробела. Это часто происходит в операторах if, которые охватывают несколько строк, поскольку if, пробел и открывающая скобка составляют 4 символа. В этом случае бывает сложно определить, где внутри оператора if начинается вложенный блок кода:

x = 5
if (x > 3 and
    x < 10):
    print(x)

В этом случае PEP 8 предоставляет две альтернативы для улучшения читаемости.

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

x = 5
if (x > 3 and
    x < 10):
    # Оба условия соблюдены
    print(x)

Во-вторых, можно сделать дополнительный отступ в продолжении строки:

x = 5
if (x > 3 and
        x < 10):
    print(x)

Альтернативный вариант отступа после разрыва строки – висячий отступ. Это типографский термин, означающий, что каждая строка, кроме первой в абзаце или цитате, имеет отступ. Вы можете использовать такой отступ для визуального представления продолжения строки кода. Вот пример:

var = function(
    arg_one, arg_two,
    arg_three, arg_four)

Замечание. Если вы используете висячий отступ, в первой строке не должно быть аргументов. Следующий пример не соответствует требованиям PEP 8:

# Не рекомендуется
var = function(arg_one, arg_two,
    arg_three, arg_four)

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

# Не рекомендуется
def function(
    arg_one, arg_two,
    arg_three, arg_four):
    return arg_one

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

def function(
        arg_one, arg_two,
        arg_three, arg_four):
    return arg_one

Когда вы пишете код, отвечающий требованиям PEP 8, ограничение в 79 символов вынуждает вас добавлять разрывы строк. Для лучшей читаемости нужно делать отступ в продолжении строки, чтобы показать, что это одна строка. Это можно сделать двумя способами. Первый — выровнять блок с отступом по открывающей скобке. Второй — использовать висячий отступ. Метод отступа после разрыва строки можно выбрать самостоятельно.

Куда поставить закрывающую скобку

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

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

list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
    ]

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

list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
]

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

Перевод части статьи How to Write Beautiful Python Code With PEP 8.

В следующей статье о PEP 8 мы разберем правила оформления комментариев, использование пробелов и выбор операторов и методов.