Если код работает, этого недостаточно.

Python становится все более популярным языком программирования, и это не случайно.

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

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

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

Обратите внимание, что в этой статье основное внимание уделяется стилю самого кода, а не фактическим алгоритмам.

Что я имею в виду под ужасным кодом Python

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

# First solution
for i in range(1,101):
    if i%3==0 and i%5==0: print('FizzBuzz')
    elif i%3==0: print('Fizz')
    elif i%5==0: print('Buzz')

и другое решение:

# Second solution
for n in range(1, 101):
    if n % 3 == 0 and n % 5 == 0:
        print('FizzBuzz')
    elif n % 3 == 0:
        print('Fizz')
    elif n % 5 == 0:
        print('Buzz')

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

Человек, написавший это, подумал, что пробел в выражениях if и в функции range совершенно не нужен. Это наполовину верно, интерпретатор Python пропустит эти пробелы, но наполовину неверно, ваш мозг может читать код гораздо более безупречно с пробелами в выражениях, чем без них.

Этот пример содержит только небольшую ошибку, поэтому позвольте мне привести пример с большей ошибкой:

# load and display an image with Matplotlib
from matplotlib import pyplot
from matplotlib import image
from matplotlib import pyplot
# load image as pixel array
data = image.imread('opera_house.jpg')
# summarize shape of the pixel array
print(data.dtype)
print(data.shape)
# display the array of pixels as an image
pyplot.imshow(data)
pyplot.show()

и более чистый, который делает то же самое, что и приведенный выше код:

from matplotlib import pyplot as plt
import matplotlib as mpl

# Load image as pixel array
img_data = mpl.image.imread('opera_house.jpg')
# Summarize image data
print(img_data.dtype)
print(img_data.shape)
# Display the image
plt.imshow(img_data)
plt.show()

Здесь я не просто добавил пробелы и несколько новых строк в этот скрипт, но также переименовал импорт и переменную data в более понятное имя переменной.

Почему мне нужно беспокоиться о пробелах, новых строках и именах некоторых переменных в маленьком скрипте?

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

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

Однажды меня попросили написать скрипт для преобразования таблиц Excel из макета A в B, оставив значения как есть. Это казалось легкой задачей, поэтому я просто начал писать код, не особо задумываясь. После нескольких часов написания я обнаружил, что решить эту проблему совсем не просто, учитывая тот факт, что было почти 8000 таблиц Excel, и мне нужно было следить за производительностью. Это было тяжело, я был единственным, кто над этим работал. Когда я узнал, что дедлайн приближается с каждой минутой, я начал писать ужасный код. Имена переменных стали бессмысленными, имена функций ничего не говорили об их процессе, и, что хуже всего, я пропустил комментарии. В двух словах: Код превратился в 1000 строк чистого ужаса. После того, как я написал и успешно использовал его незадолго до крайнего срока, я подумал, что все закончилось, мне не нужно его расширять, импортировать или встраивать куда-то еще. Я ошибся, они нашли другие таблицы excel, которые лишь немного отличались от версии A. Мне пришлось расширить его и использовать три раза после завершения первого кода.

Это был разочаровывающий опыт, который отнимал много времени. Я не хочу, чтобы вы впадали в мои ошибки.

Как бороться с ужасным кодом, который вам нужен

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

1. Форматирование и комментарии

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

2. Имена переменных

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

3. Функции

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

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

Как написать красивый код на Python

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

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

Используйте возможности Python

import this

Его вывод обязателен к прочтению разработчиками Python:

Дзен Python, Тим Питерс

Красивое лучше, чем уродливое.
Явное лучше, чем неявное.
Простое лучше, чем сложное.
Сложное лучше, чем сложное.
Плоское лучше, чем вложенное.
Разреженность лучше, чем плотность.
Удобочитаемость имеет значение.
Особые случаи не настолько особенные, чтобы нарушать правила.
Хотя практичность важнее чистоты.
Ошибки никогда не должны оставаться незамеченными.
Если явно не замалчивается.
Перед лицом двусмысленности откажитесь от искушения угадать.
Должен быть один — и желательно только один — очевидный способ сделать это.
Хотя этот способ может поначалу это может быть не очевидно, если только вы не голландец.
Лучше сейчас, чем никогда.
Хотя никогда лучше, чем *прямо* сейчас.
Если реализацию трудно объяснить, это плохая идея.
Если реализацию легко объяснить, это может быть хорошей идеей.
Пространства имен — это отличная идея — давайте сделаем больше таких!

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

Передача параметров

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

def foo(do_a, will_do_b, tune_a, tune_b, dont_do_c):
    """
    Some docstring
    """
    pass
# Here we don't know what parameters are
foo(True, True, 0, 10, True)

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

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

foo(do_a=True, will_do_b=True, tune_a=0, tune_b=10, dont_do_c=True)

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

Итераторы

Если вам дали задание:

Есть массив с именами, выведите каждое имя в нем с соответствующим порядковым номером.

Вы можете решить задачу следующим образом:

for i in range(len(names)):
    print(i)
    print(names[i])
    print()

Более питоническое решение:

for i, name in enumerate(names):
    print(i)
    print(name)
    print()

Подробнее об итераторах можно прочитать здесь.

Пилинт

Pylint — хороший способ измерить чистоту кода. Это очень просто.

У нас есть файл с именем test.py:

import math

def logn(a, n):
    return math.log(a) / math.log(n)
if __name__ == '__main__':
    print(logn(10, 10))

If I do

$ pylint test.py

я получил

************* Module test
test.py:1:0: C0111: Missing module docstring (missing-docstring)
test.py:4:0: C0103: Argument name "a" doesn't conform to snake_case naming style (invalid-name)
test.py:4:0: C0103: Argument name "n" doesn't conform to snake_case naming style (invalid-name)
test.py:4:0: C0111: Missing function docstring (missing-docstring)
-------------------------------------------------------------------
Your code has been rated at 2.00/10 (previous run: 10.00/10, -8.00)

Подробнее о пилинте можно прочитать здесь.

Вывод

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

Любая из размещенных здесь ссылок не является частью какой-либо рекламной программы. Он был опубликован с целью помочь читателю этой статьи писать более качественное программное обеспечение Python.

Мартин Кондор — разработчик программного обеспечения, работающий в Венгрии.