Pep python что это
Перейти к содержимому

Pep python что это

  • автор:

Как писать питонический код: три рекомендации и три книги

Новички в Python часто спрашивают, как писать питонический код. Проблема — расплывчатое определение слова «питонический». Подробным материалом, в котором вы найдёте ответы на вопрос выше и три полезные книги, делимся к старту курса по Fullstack-разработке на Python.

Что значит «питонический»?

Python более 30 лет. За это время накоплен огромный опыт его применения в самых разных задачах. Этот опыт обобщался, и возникали лучшие практики, которые обычно называют «питоническим» кодом.

Философия Python раскрывается в The Zen of Python Тима Питерса, доступной в любом Python по команде import this в REPL:

>>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!

Начинающих в Python больше всего раздражает красота Zen of Python. В Zen передаётся дух того, что значит «питонический» — и без явных советов. Вот первый принцип дзена Python: «Красивое лучше, чем уродливое». Согласен на 100%! Но как сделать красивым мой некрасивый код? Что это вообще такое — «красивый код»?

Сколь бы ни раздражала эта неоднозначность, именно она делает Zen of Python таким же актуальным, как и в 1999 году, когда Тим Питерс написал этот набор руководящих принципов. Они помогают понять, как отличать питонический и непитонический код, и дают ментальную основу принятия собственных решений.

Каким же будет определение слова «питонический»? Лучшее найденное мной определение взято из ответа на вопрос «Что означает «питонический» В этом ответе питонический код описывается так:

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

Из этого делаем два ключевых вывода:

  1. Слово «питонический» связано скорее со стилем, чем с синтаксисом. Хотя идиомы Python часто имеют последствия за рамками чисто стилистического выбора, в том числе повышение производительности кода.
  2. То, что считается «питоническим», определяется сообществом Python.

Итак, у нас сложилось хотя бы какое-то представление о том, что имеют в виду программисты на Python, называя код «питоническим». Рассмотрим три конкретных и доступных способа написания более питонического кода.

1. Подружитесь с PEP8

PEP8 — это официальное руководство по стилю кода Python. PEP расшифровывается как Python Enhancement Proposal («Предложение по улучшению Python»). Это документы, предлагающие новые особенности языка. Они образуют официальную документацию особенности языка, принятие или отклонение которой обсуждается в сообществе Python. Следование PEP8 не сделает код абсолютно «питоническим», но способствует узнаваемости кода для многих Python-разработчиков.

В PEP8 решаются вопросы, связанные с символами пробелов. Например, использование четырёх пробелов для отступа вместо символа табуляции или максимальной длиной строки: согласно PEP8, это 79 символов, хотя данная рекомендация, вероятно, самая игнорируемая.

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

# Correct seconds_per_hour = 3600 # Incorrect secondsperhour = 3600 secondsPerHour = 3600

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

# Correct class SomeThing: pass # Incorrect class something: pass class some_thing: pass

Константы записывайте в верхнем регистре и с подчёркиваниями между словами: UPPER_CASE_WITH_UNDERSCORES:

# Correct PLANCK_CONSTANT = 6.62607015e-34 # Incorrect planck_constant = 6.6260715e-34 planckConstant = 6.6260715e-34

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

Запоминать все соглашения PEP8 не нужно: найти и устранить проблемы PEP8 в коде могут помочь такие инструменты, как flake8. Установите flake8 с помощью pip:

# Linux/macOS $ python3 -m pip install flake8 # Windows $ python -m pip install flake8

flake8 можно использовать как приложение командной строки для просмотра файла Python на предмет нарушений стиля. Допустим, есть файл myscript.py с таким кодом:

def add( x, y ): return x+y num1=1 num2=2 print( add(num1,num2) )

При запуске на этом коде flake8 сообщает, как и где именно нарушается стиль:

$ flake8 myscript.py myscript.py:1:9: E201 whitespace after '(' myscript.py:1:11: E231 missing whitespace after ',' myscript.py:1:13: E202 whitespace before ')' myscript.py:4:1: E305 expected 2 blank lines after class or function definition, found 1 myscript.py:4:5: E225 missing whitespace around operator myscript.py:5:5: E225 missing whitespace around operator myscript.py:6:7: E201 whitespace after '(' myscript.py:6:16: E231 missing whitespace after ',' myscript.py:6:22: E202 whitespace before ')'

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

Как читать вывод flake8

Для проверки качества кода с помощью flake8 вы даже можете настроить редакторы, например VS Code. Пока вы пишете код, он постоянно проверяется на нарушения PEP8. Когда обнаруживается проблема, во flake8 под частью кода с ошибкой появляется красная волнистая линия, найденные ошибки можно увидеть во вкладке встроенного терминала Problems:

Проверки flake8 в Visual Studio Code

flake8 — отличный инструмент для поиска связанных с нарушением PEP8 ошибок, но исправлять их придётся вручную. А значит, будет много работы. К счастью, весь процесс автоматизируемый. Автоматически форматировать код согласно PEP можно с помощью инструмента под названием Black.

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

Установите black c помощью pip:

# Linux/macOS $ python3 -m pip install black # Windows $ python -m pip install black

После установки командой black —check можно посмотреть, будут ли black изменять файл:

$ black --check myscript.py would reformat myscript.py Oh no! �� �� �� 1 file would be reformatted.

Чтобы увидеть разницу после изменений, используйте флаг —diff:

$ black --diff myscript.py --- myscript.py 2022-03-15 21:27:20.674809 +0000 +++ myscript.py 2022-03-15 21:28:27.357107 +0000 @@ -1,6 +1,7 @@ -def add( x, y ): - return x+y +def add(x, y): + return x + y -num1=1 -num2=2 -print( add(num1,num2) ) + +num1 = 1 +num2 = 2 +print(add(num1, num2)) would reformat myscript.py All done! ✨ �� ✨ 1 file would be reformatted.

Чтобы автоматически отформатировать файл, передайте его имя команде black:

$ black myscript.py reformatted myscript.py All done! ✨ �� ✨ 1 file reformatted. # Show the formatted file $ cat myscript.py def add(x, y): return x + y num1 = 1 num2 = 2 print(add(num1, num2))

Чтобы проверить совместимость с PEP8, снова запустите flake8 и посмотрите на вывод:

# No output from flake8 so everything is good! $ flake8 myscript.py

При работе с black следует иметь в виду, что максимальная длина строки по умолчанию в нём — это 88 символов. Это противоречит рекомендации PEP8 о 79 символах, поэтому при использовании black в отчёте flake8 вы увидете ошибки о длине строки.

Многие разработчики Python используют 88 знаков вместо 79, а некоторые — строки ещё длиннее. Можно настроить black на 79 символов, или flake8 — на строки большей длины.

Важно помнить, что PEP8 — это лишь набор рекомендаций, хотя многие программисты на Python относятся к ним серьёзно. PEP8 не применяется в обязательном порядке. Если в нём есть что-то, с чем вы категорически не согласны, вы вправе это игнорировать! Если же вы хотите строго придерживаться PEP8, инструменты типа flake8 и black сильно облегчат вам жизнь.

2. Избегайте циклов в стиле C

В таких языках, как C или C++, отслеживание индексной переменной при переборе массива — обычное дело. Поэтому программисты, которые перешли на Python из C или C++, при выводе элементов списка нередко пишут:

>>> names = ["JL", "Raffi", "Agnes", "Rios", "Elnor"] >>> # Using a `while` loop >>> i = 0 >>> while i < len(names): . print(names[i]) . i += 1 JL Raffi Agnes Rios Elnor >>> # Using a `for` loop >>> for i in range(len(names)): . print(names[i]) JL Raffi Agnes Rios Elnor

Вместо итерации можно перебрать все элементы списка сразу:

>>> for name in names: . print(name) JL Raffi Agnes Rios Elnor

Этим вторая рекомендация не ограничивается: она намного глубже простого перебора элементов списка. Такие идиомы Python, как списковые включения, встроенные функции (min(), max() и sum()) и методы объектов, может помочь вывести ваш код на новый уровень.

Отдавайте предпочтение списковым включениям, а не простым циклам for

Обработка элементов массива и сохранение результатов в новом — типичная задача программирования. Допустим, нужно преобразовать список чисел в список их квадратов. Избегая циклов в стиле C, можно написать:

>>> nums = [1, 2, 3, 4, 5] >>> squares = [] >>> for num in nums: . squares.append(num ** 2) . >>> squares [1, 4, 9, 16, 25]

Но более питонически применить списковое включение:

>>> squares = [num ** 2 for num in nums] # >> squares [1, 4, 9, 16, 25]

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

Вот так я обычно пишу списковые включения:

  1. Начинаю с создания литерала пустого списка:
    [].
  2. Первым в списковое включение помещаю то, что обычно идёт в метод .append()при создании списка с помощью цикла for:
    [num ** 2].
  3. И, наконец, помещаю в конец списка заголовок цикла for:
    [num ** 2 for num in nums].

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

Используйте встроенные функции, такие как min(), max() и sum()

Ещё одна типичная задача программирования — это поиск минимального или максимального значения в массиве чисел. Найти наименьшее число в списке можно с помощью for:

>>> nums = [10, 21, 7, -2, -5, 13] >>> min_value = nums[0] >>> for num in nums[1:]: . if num < min_value: . min_value = num . >>> min_value -5

Но более «питонически» применять встроенную функцию min():

>>> min(nums) -5

То же касается нахождения наибольшего значения в списке: вместо цикла применяется встроенная функция max():

>>> max(nums) 21

Чтобы найти сумму чисел списка, написать цикл for можно, но более питонически воспользоваться sum():

>>> # Not Pythonic: Use a `for` loop >>> sum_of_nums = 0 >>> for num in nums: . sum_of_nums += num . >>> sum_of_nums 44 >>> # Pythonic: Use `sum()` >>> sum(nums) 44

Также sum() полезна при подсчёте количества элементов списка, для которых выполняется некое условие. Например, вот цикл for для подсчёта числа начинающихся с буквы A строк списка:

>>> capitals = ["Atlanta", "Houston", "Denver", "Augusta"] >>> count_a_capitals = 0 >>> for capital in capitals: . if capital.startswith("A"): . count_a_capitals += 1 . >>> count_a_capitals 2

Функция sum() со списковым включением сокращает цикл for до одной строки:

>>> sum([capital.startswith("A") for capital in capitals]) 2

Красота! Но ещё более питонической эту строку сделает замена спискового включения на выражение-генератор. Убираем скобки списка:

>>> sum(capital.startswith("A") for capital in capitals) 2

Как именно работает код? И списковое включение, и выражение-генератор возвращают итерируемый объект со значением True, если строка в списке capitals начинается с буквы A, и False — если это не так:

>>> [capital.startswith("A") for capital in capitals] [True, False, False, True]

В Python True и False — это завуалированные целые числа. True равно 1, а False — 0:

>>> isinstance(True, int) True >>> True == 1 True >>> isinstance(False, int) True >>> False == 0 True

Когда в sum() передаётся списковое включение или выражение-генератор, значения True и False считаются 1 и 0 соответственно. Всего два значения True и два False, поэтому сумма равна 2.

Использование sum() для подсчёта числа удовлетворяющих какому-то условию элементов списка подчёркивает важность понятия «питонический». Я нахожу такое применение sum() очень питонически. Ведь с sum() используется несколько особенностей этого языка и создаётся, на мой взгляд, лаконичный и удобный для восприятия код. Но, возможно, не каждый разработчик на Python со мной согласится.

Можно было бы возразить, что в этом примере нарушается один из принципов Zen of Python: «Явное лучше неявного». Ведь не очевидно, что True и False — целые числа и что sum() вообще должна работать со списком значений True и False. Чтобы освоить это применение sum(), нужно глубоко понимать встроенные типы Python.

Узнать больше о True и False как целых числах, а также о других неожиданных фактах о числах в Python можно из статьи 3 Things You Might Not Know About Numbers in Python («3 факта о числах в Python, которых вы могли не знать»).

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

3. Используйте правильную структуру данных

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

Используйте словари для быстрого поиска

Вот CSV-файл clients.csv с данными по клиентам:

first_name,last_name,email,phone Manuel,Wilson,mwilson@example.net,757-942-0588 Stephanie,Gonzales,sellis@example.com,385-474-4769 Cory,Ali,coryali17@example.net,810-361-3885 Adam,Soto,adams23@example.com,724-603-5463

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

Используя объект DictReader из модуля csv, можно прочитать каждую строку файла как словарь:

>>> import csv >>> with open("clients.csv", "r") as csvfile: . clients = list(csv.DictReader(csvfile)) . >>> clients [, , , ]

clients — это список словарей. Поэтому, чтобы найти клиента по адресу почты, например sellis@example.com, нужно перебрать список и сравнить почту каждого клиента с целевой почтой, пока не будет найден нужный клиент:

>>> target = "sellis@example.com" >>> phone = None >>> for client in clients: . if client["email"] == target: . phone = client["phone"] . break . >>> print(phone) 385-474-4769

Но есть проблема: перебор списка клиентов неэффективен. Если в файле много клиентов, на поиск клиента с совпадающим адресом почты у программы может уйти много времени. А сколько теряется времени, если такие проверки проводятся часто!

Более питонически сопоставить клиентов с их почтами, а не хранить клиентов в списке. Для этого отлично подойдёт словарное включение:

>>> with open("clients.csv", "r") as csvfile: . # Use a `dict` comprehension instead of a `list` . clients = . >>> clients

Словарные включения очень похожи на списковые включения:

  1. Я начинаю с создания пустого словаря:
    <>.
  2. Затем помещаю туда разделённую двоеточием пару «ключ — значение»:
    .
  3. И пишу выражение с for, которое перебирает все строки в CSV:
    .

Вот это словарное включение, преобразованное в цикл for:

>>> clients = <> >>> with open("clients.csv", "r") as csvfile: . for row in csv.DictReader(csvfile): . clients[row["email"]] = row["phone"]

С этим словарём clients вы можете найти телефон клиента по его почте без циклов:

>>> target = "sellis@example.com" >>> clients[target] 385-474-4769

Этот код не только короче, но и намного эффективнее перебора списка циклом. Но есть проблема: если в clients нет клиента с искомой почтой, поднимается ошибка KeyError:

>>> clients["tsanchez@example.com"] Traceback (most recent call last): File "", line 1, in KeyError: 'tsanchez@example.com'

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

>>> target = "tsanchez@example.com" >>> try: . phone = clients[target] . except KeyError: . phone = None . >>> print(phone) None

Но более питонически применять метод словаря .get(). Если пара с ключом существует, этот метод возвращает значение пары, иначе возвращается None:

>>> clients.get("sellis@example.com") '385-474-4769'

Сравним решения выше:

import csv target = "sellis@example.com" phone = None # Un-Pythonic: loop over a list with open("clients.csv", "r") as csvfile: clients = list(csv.DictReader(csvfile)) for client in clients: if client["email"] == target: phone = client["phone"] break print(phone) # Pythonic: lookup in a dictionary with open("clients.csv", "r") as csvfile: clients = phone = clients.get(target) print(phone)

Питонический код короче, эффективнее и не менее удобен для восприятия.

Используйте операции над множествами

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

>>> nums = [1, 3, 2, 3, 1, 2, 3, 1, 2] >>> unique_nums = list(set(nums)) >>> unique_nums [1, 2, 3]

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

Вот придуманный, но реалистичный пример. У владельца магазина есть CSV-файл клиентов с адресами их почты. Снова возьмём файл clients.csv. Есть также CSV-файл заказов за последний месяц orders.csv, тоже с адресами почты:

date,email,items_ordered 2022/03/01,adams23@example.net,2 2022/03/04,sellis@example.com,3 2022/03/07,adams23@example.net,1

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

>>> import csv >>> # Create a list of all client emails >>> with open("clients.csv", "r") as clients_csv: . client_emails = [row["email"] for row in csv.DictReader(clients_csv)] . >>> # Create a list of emails from orders >>> with open("orders.csv") as orders_csv: . order_emails = [row["email"] for row in csv.DictReader(orders_csv)] . >>> # Use a list comprehension to filter the clients emails >>> coupon_emails = [email for email in clients_emails if email not in order_emails] >>> coupon_emails ["mwilson@example.net", "coryali17@example.net"]

Код нормальный и выглядит вполне питонически. Но что, если каждый месяц клиентов и заказов будут миллионы? Тогда при фильтрации почты и определении, каким клиентам отправлять купоны, потребуется перебор всего списка client_emails. А если в файлах client.csv и orders.csv есть повторяющиеся строки? Бывает и такое.

Более питонически считать адреса почты клиентов и заказов в множествах и отфильтровать множества почтовых адресов клиентов оператором разности множеств:

>>> import csv >>> # Create a set of all client emails using a set comprehension >>> with open("clients.csv", "r") as clients_csv: . client_emails = . >>> # Create a set of emails frp, orders using a set comprehension >>> with open("orders.csv", "r") as orders_csv: . order_emails = . >>> # Filter the client emails using set difference >>> coupon_emails = client_emails - order_emails >>> coupon_emails

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

Три книги, чтобы писать более питонический код

За один день писать чистый питонический код не научиться. Нужно изучить много примеров кода, пробовать писать собственный код и консультироваться с другими разработчиками Python. Чтобы облегчить вам задачу, я составил список из трёх книг, очень полезных для понимания питонического кода. Все они написаны для программистов уровня выше среднего или среднего.

Если вы новичок в Python (и тем более в программировании в целом), загляните в мою книгу Python Basics: A Practical Introduction to Python 3 («Основы Python: Практическое введение в Python 3»).

Python Tricks Дэна Бейдера

Короткая и приятная книга Дэна Бейдера Python Tricks: A Buffet of Awesome Python Features («Приёмы Python: набор потрясающих функций Python») — отличная отправная точка для начинающих и программистов, желающих больше узнать о том, как писать питонический код.

С Python Tricks вы изучите шаблоны написания чистого идиоматичного кода Python, лучшие практики для написания функций, эффективное применение функционала объектно-ориентированного программирования Python и многое другое.

Effective Python Бретта Слаткина

Effective Python («Эффективный Python») Бретта Слаткина — это первая книга, которую я прочитал после изучения синтаксиса Python. Она открыла мне глаза на возможности питонического кода.

В Effective Python содержится 90 способов улучшения кода Python. Одна только первая глава Python Thinking («Мыслить на Python») — это кладезь хитростей и приёмов, которые будут полезными даже для новичков, хотя остальная часть книги может быть для них трудной.

Fluent Python Лучано Рамальо

Если бы у меня была только одна книга о Python, это была бы книга Лучано Рамальо Fluent Python («Python. К вершинам мастерства»). Рамальо недавно обновил свою книгу до современного Python. Сейчас можно оформить предзаказ. Настоятельно рекомендую сделать это: первое издание устарело.

Полная практических примеров, чётко изложенная книга Fluent Python — отличное руководство для всех, кто хочет научиться писать питонический код. Но имейте в виду, что Fluent Python не предназначена для новичков. В предисловии к книге написано:

«Если вы только изучаете Python, эта книга будет трудной для вас».

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

Опытные программисты на Python извлекут из этой книги большую пользу.

А мы поможем вам прокачать скиллы или с самого начала освоить профессию в IT, актуальную в любое время:

  • Профессия Fullstack-разработчик на Python
  • Профессия Data Scientist

Краткий каталог курсов и профессий

Data Science и Machine Learning

  • Профессия Data Scientist
  • Профессия Data Analyst
  • Курс «Математика для Data Science»
  • Курс «Математика и Machine Learning для Data Science»
  • Курс по Data Engineering
  • Курс «Machine Learning и Deep Learning»
  • Курс по Machine Learning

Python, веб-разработка

  • Профессия Fullstack-разработчик на Python
  • Курс «Python для веб-разработки»
  • Профессия Frontend-разработчик
  • Профессия Веб-разработчик

Мобильная разработка

  • Профессия iOS-разработчик
  • Профессия Android-разработчик

Java и C#

  • Профессия Java-разработчик
  • Профессия QA-инженер на JAVA
  • Профессия C#-разработчик
  • Профессия Разработчик игр на Unity

От основ — в глубину

  • Курс «Алгоритмы и структуры данных»
  • Профессия C++ разработчик
  • Профессия Этичный хакер

А также

Стайлгайд PEP8

PEP8 – это стайлгайд написания кода на Питоне. Он является частью Питона. Его все соблюдают.

Он отвечает на вопросы в таком духе,

  • Табы или пробелы?
  • Какая максимальная длина строки?
  • Одинарные или двойные кавычки?
  • Где ставить пробелы, а где — нет?
  • Сколько ставить пустых строк?
  • Как импортировать?
  • Какой стиль именования сущностей?

Лучше прочитать оригинал документа PEP8 (если не осилишь – вот куцый перевод на русский). Особое внимание – к секции “A Foolish Consistency is the Hobgoblin of Little Minds”.

PEP 8 – закон. Его надо соблюдать. Если в вашей программе много нарушений PEP 8 – она выглядит неряшливо, по-дилетантски.

Помимо PEP 8 есть ещё pep8 . pep8 – это модуль, позволяющий проверять, соответствует ли код стандарту PEP 8. Сперва её надо установить ( pip install pep8 ), поле этого запустить, указав путь до файла или папки с кодом: pep8 ./2_wallie_how_are_you/wallie.py . Программа выдаст все нарушения PEP 8. Остаётся их только поправить.

Попробуйте бесплатные уроки по Python

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

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

Читай PEP 8 — пиши код как ван Россум

В борьбе за красивый и понятный код Python-сообществу нужны ориентиры: что такое хорошо и что такое плохо. Создатель языка Гвидо ван Россум (Guido van Rossum) и его соратник Барри Уорсо (Barry Warsaw) описали хороший стиль Py-кода в документе PEP 8.

Каждый уважающий себя питонист обязан знать этот стандарт. Читайте оригинал или перевод , главное — вдумчиво!

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

Зачем нужен PEP 8

Единый стиль оформления делает код понятным для самого программиста и его коллег с разным уровнем подготовки.

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

Гвидо ван Россум

PEP 8 затрагивает структуру и внешний вид кода:

  • выбор кодировки исходного кода;
  • группировку инструкций по импорту модулей;
  • максимальную длину строки кода — рекомендуется до 79 знаков, а для строк документации (docstring) — 72 знака;
  • использование отступов — табуляции и пробелов;
  • использование пустых строк для разбивки кода на блоки и выделения функций верхнего уровня;
  • использование комментариев;
  • именование переменных, констант, классов и экземпляров, функций, аргументов, модулей, пакетов;
  • выбор уровня доступности классов и методов (public, private, API-подклассы), а также порядка их наследования.

Пишете ли вы код в PyCharm, Notepad++ или другом редакторе, сохранять .py-файлы лучше в кодировке UTF-8. Для Python 3 она рекомендована официально, для Python 2 формально требуется кодировка ASCII, но она не поддерживает кириллицу, поэтому для приложений на русском разумно использовать ту же UTF-8. Если по какой-то причине вам очень нужна «альтернативная» кодировка исходника, обязательно укажите её в комментарии в первой строке файла:

 # coding: cp1251 print("Текст в кодировке Windows 1251.") input() 

Без этого комментария интерпретатор выдаст ошибку.

PEP 8: Питону важны отступы

Самое известное требование PEP 8 по оформлению Python-кода — отступы . С их помощью задают структуру условий, циклов, функций. Традиционно на один уровень отступа ставят четыре пробела . Например:

if sunny: print("The sun is shining!") else: pass 

Теоретически вы можете использовать иное число пробелов: 2, 8 и т.д. Главное, чтобы оно совпадало по всему коду — иначе интерпретатор будет ругаться. Но 4 — «золотой стандарт» сообщества: быстро ставить, привычно читать.

В чужом коде вам может встретиться другой вид отступа — табуляция. Его PEP 8 категорически не рекомендует, но с одной оговоркой. Если вы дорабатываете готовый проект, где отступы сделаны табуляцией, придерживайтесь принятого до вас стандарта. Если в коде разнобой, замените всё на пробелы.

Интересный факт: исследование 2017 года на Stack Overflow показало, что программисты, которые делают отступы пробелами, зарабатывают почти на 9% больше, чем любители Tab’а.

Когда пробелы в Python не ставят

  1. Сразу после открывающей скобки и перед закрывающей: ( x ) — так не надо.
  2. Перед скобками при вызове аргумента. Неправильно: arg (1). Правильно: arg(1).
  3. Перед скобками индекса и среза: dict[‘step’] = map[i].
  4. Между именем параметра/аргумента, знаком «=» и значением: min(a=10, b=input).

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

Лучше ставьте по одному пробелу по сторонам от знаков арифметических действий:

x = (y + 1) * (y — a)

Не рекомендуется записывать несколько команд в одну строку через точку с запятой. Вместо «act1(); act2(); act3()» — пишите:

act1() act2() act3()

В комментариях не забывайте ставить пробел после знака «#».

PEP 8 и имена объектов в Python

Если хотите назвать переменную одним символом, избегайте строчной латинской l («эль»), заглавной I («ай») и заглавной O — в некоторых шрифтах они неотличимы от цифр 1 и 0 соответственно. С заглавной L таких проблем нет.

Объекты разного типа должны отличаться и по формату записи имён. Так читатель быстрее понимает, что перед ним. Называйте:

  • Классы и исключения — LikeThis
  • Константы — LIKE_THIS
  • Переменные и аргументы — like_this
  • Функции и методы — тоже like_this, но допускается и likeThis, если вы дописываете старый или чужой код, где уже задан такой формат.

Если имя аргумента вашей функции совпадает с зарезервированным в Python словом, не искажайте написание, но ставьте подчёркивание в конце. Вот так: «input_».

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

Не используйте два знака равенства (==) для проверки булевых значений. Вместо этого используйте if или if not с именем объекта (например, переменной):

 if  i_have_apples: # делаем то if not key_obtained: # делаем это

Если нужно сравнить что-то со значением «None», вместо операторов сравнения используйте is/is not .

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

Другое важное о Python в PEP 8

  • В руководстве по стилю есть рекомендованный порядок импорта модулей: сначала грузите модули стандартной библиотеки, затем — из сторонних библиотек, в конце — ваши собственные модули.
  • При обработке исключений используйте синтаксис привязки имён, равно совместимый с Python 2 и 3:
try: something() except Exception as exc: raise AnotherDamnError(str(exc))
  • Старайтесь минимизировать количество кода в конструкциях try… except. Это поможет избежать трудных в обнаружении ошибок.
  • По возможности выбирайте синтаксис, который работает для всех реализаций Python: CPython, Jython, PyPy и других.

Автоматическая PEP проверка Python-кода

Пока вы создаете маленькие проекты, вычитывать код на ошибки и нарушения стиля не проблема. В работе над большими проектами выручат скрипты автоматической проверки кода . PyCharm проверяет написанное «на лету». А если нужно поработать без IDE? На GitHub есть целый раздел Python Code Quality Authority , где хранятся утилиты для повышения качества кода, в том числе для проверки стиля на соответствие PEP 8: flake8 , pycodestyle , pep8-naming . Когда будет нужно, вы сможете интегрировать Flake8 в свою среду разработки.

Осознанная необходимость

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

Если конкретный код при подгонке под стиль становится уродливым, «такой хоккей нам не нужен». Например, если разбивка на строки по 72 символа усложняет чтение, PEP 8 предлагает удлинить строку до 80 или даже 100 символов — в зависимости от того, что удобно вам и вашей команде разработки. Чёткие ограничения действуют только для публичных проектов-библиотек.
Дополнительное чтение: если вы вошли во вкус, добавьте в свой список ещё и статью « Пиши как настоящий Питонист: идиоматика Python» . Также советуем просмотреть вебинар о применении Python в реальном мире.

PEP 8

Python, подобно живому организму, развивается и приобретает новые возможности благодаря многочисленному международному сообществу согласно определенным правилам и стандартам PEP . PEP — Python Enhancement Proposal, предложения по развитию Python. Эти стандарты позволяют создавать унифицированную проектную документацию для новых утвержденных возможностей языка Python. Самый известный PEP имеет восьмой порядковый номер. PEP8 содержит перечень принципов написания красивого и лаконичного программного кода на языке Python.

Под названием каждого подраздела главы будет находиться по одному из 19 принципов философии Python (Zen of Python) . Попытайтесь «прочувствовать» то, что имел в виду автор. Также, если хочется, вместо русской адаптации этих постулатов, увидеть оригинальный текст Тима Петерса , можно запустив вот такую программу.

import this

Для чего придуман PEP8? ¶

(Читаемость имеет значение)

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

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

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

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

Если же вы более опытный Python-программист, тогда с помощи PEP8 можно с легкостью объединиться с другими программистами для работы над одной задачей. Хорошо читаемый код имеет в данном случае особую критичность. Люди, ранее не видевшие вас, но знакомые с вашим кодом, будут читать, понимая идею, которую вы хотели донести.

Негласная договоренность об именах ¶

(Явное лучше, чем неявное)

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

Не использовать одиночные буквы l, O, или I в качестве каких-либо имен из-за риска спутать их с 1 и 0, в зависимости от шрифта.

O = 2 # Это может выглядеть так, будто вы хотите приравнять 2 к нулю.

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

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

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

Помимо выбора правильных стилей именования в вашем коде, вы также должны тщательно выбирать сами имена. Ниже приведены несколько советов, как сделать это максимально эффективно.

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

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

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

Вы можете получить что-то вроде этого:

# Не рекомендуется
x = 'Иван Петров'
y, z = x.split()

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

# Рекомендуется
name = 'Иван Петров'
first_name, last_name = name.split()

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

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

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

Следующий пример еще более понятен:

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

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

Расположение кода ¶

(Красивое лучше, чем уродливое)

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

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

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

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

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

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

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

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

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

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

from mypkg import example1, \
example2, example3

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

Отступы ¶

(Должен быть один очевидный способ сделать это)

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

x = 2
if x > 6:
print('x больше, чем 6')

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

  1. Используйте четыре последовательных пробела для отступа;
  2. Отдавайте предпочтение пробелам, а не табуляции.

Пробелы против Табуляции ¶

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

Комментарии ¶

(Если реализацию трудно объяснить, это была плохая идея)

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

  1. Используйте длину комментариев при документации не более 72 символов;
  2. Не используйте сокращения, начинайте предложения с заглавной буквы;
  3. Не забывайте актуализировать комментарии, при изменении кода.

Пример простейшего комментария:

name = 'John Smith' # Student Name

Пробелы в выражениях и утверждениях ¶

(Разреженное лучше, чем плотное)

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

Окружите следующие бинарные операторы одним пробелом с каждой стороны:

  1. Операторы присвоения (=, +=, -= и т. п.)
  2. Сравнения (==, ! =, >,
  3. Логические (and, or, not)

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

Рекомендации программисту ¶

(Простое лучше сложного)

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

# Не рекомендуется
my_bool = 4 > 3
if my_bool == True:
return '4 больше 3'

Использование оператора эквивалентности здесь не имеет необходимости, my_bool может иметь только два значения, True или False. Поэтому достаточно написать так:

# Рекомендуется
if my_bool:
return '4 is bigger than 3'

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

Когда лучше проигнорировать PEP8 ¶

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

  1. Если соблюдение PEP8 нарушит совместимость с существующим программным обеспечением;
  2. Если код, сопутствующий тому, над чем вы работаете, несовместим с PEP8;
  3. Если код нужно оставить совместимым с неактуальными версиями Python.

Заключение ¶

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

Если же у вас имеется желание углубиться в изучение тонкостей PEP8, можно ознакомиться с полной англоязычной документацией или посетить информационный ресурс pep8.org , содержащий ту же информацию, в более структурированном виде. В этих документах вы найдете, не попавшие в эту «выжимку», рекомендации.

Хотите выучить Python на практике?

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *