Чистыйкод дляпродолжающи х
Скачать 7.85 Mb.
|
Встроенные комментарии размещаются в конце строки: while True: # Пока игрок не введет допустимый ход. Комментарии 219 Встроенные комментарии коротки, потому что они должны укладываться в огра- ничения длины строки, указанные в руководстве по стилю. Это означает, что они могут оказаться слишком короткими, чтобы содержать достаточную информацию. Если вы решите использовать встроенные комментарии, убедитесь в том, что ком- ментарий описывает только непосредственно предшествующую ему строку кода. Если вашему встроенному комментарию требуется больше места или он описывает другие строки кода, разместите его в отдельной строке. Встроенные комментарии чаще всего применяют — и это весьма уместно — для по- яснения смысла переменных или другой информации, относящейся к переменным. Такие встроенные комментарии записываются в команде присваивания, которая создает переменную: TOTAL_DISKS = 5 # Чем больше дисков, тем сложнее головоломка. Другое типичное применение встроенных комментариев — добавление информации о значениях переменных при их создании: month = 2 # Месяцы пронумерованы от 0 (январь) до 11 (декабрь). catWeight = 4.9 # Вес в килограммах. website = 'inventwithpython.com' # Префикс "https://" не включается. Во встроенных комментариях не следует указывать тип данных переменной, потому что он должен быть очевиден из команды присваивания; исключение составляет такая разновидность комментариев, как аннотации типов (см. подраздел «Обратное портирование аннотаций типов» далее в этой главе, с. 232). Пояснительные комментарии Как правило, комментарии должны сообщать, почему код был написан именно так, а не иначе, что он делает или как он это делает. Даже при использовании правиль- ного стиля кода и полезных соглашений об именах, о которых я рассказывал в гла- вах 3 и 4, реальный код не способен объяснить, какие задачи ставил программист. Если вы сами написали код, то через несколько недель можете забыть какие-то подробности. Поэтому лучше сегодня дать содержательные комментарии, чтобы завтра вам не пришлось проклинать вас вчерашнего. Например, ниже приведен бесполезный комментарий, который объясняет, что делает код. Вместо того чтобы пояснить задачу кода, он констатирует очевидное: >>> currentWeekWages *= 1.5 # Заработок за текущую неделю умножается на 1.5 Такой комментарий хуже бесполезного. Из кода и так очевидно, что переменная currentWeekWages умножается на 1.5 , и если полностью убрать комментарий, это только упростит ваш код. Следующий комментарий гораздо лучше: >>> currentWeekWages *= 1.5 # Включить в расчет полуторную ставку. 220 Глава 11.Комментарии, doc-строки и аннотации типов Этот комментарий объясняет смысл строки кода, а не пересказывает, как тот ра- ботает. Он предоставляет информацию, которую даже хорошо написанный код передать не сможет. Сводные комментарии Практическая польза комментариев не ограничивается пояснением намерений про- граммиста. Краткие комментарии, резюмирующие работу нескольких строк кода, позволяют читателю бегло просмотреть исходник и получить общее представление о том, что он делает. Программисты часто вставляют пустые строки, чтобы отделить «абзацы» кода друг от друга. Сводные комментарии обычно занимают одну строку в начале таких абзацев. В отличие от однострочных комментариев, поясняющих отдельные строки кода, сводные комментарии на более высоком уровне абстракции описывают, что делает код. Например, из следующих четырех строк кода можно понять, что они присваивают переменной playerTurn значение, обозначающее другого игрока. Но короткий одно- строчный комментарий избавит читателя от необходимости читать и обдумывать код, чтобы понять смысл происходящего: # Ход передается другому игроку: if playerTurn == PLAYER_X: playerTurn = PLAYER_O elif playerTurn == PLAYER_O: playerTurn = PLAYER_X Если вы включите эти сводные комментарии в свою программу, это значительно упростит ее чтение. Далее программист сможет внимательнее проанализировать те места, которые вызывают у него особый интерес. Сводные комментарии также препятствуют формированию ошибочных представлений о том, что делает код. Краткий сводный комментарий позволяет разработчику удостовериться, что он правильно понял, как работает код. Комментарии «полученный опыт» Когда я работал в компании, занимающейся разработкой программного обеспече- ния, однажды мне предложили адаптировать библиотеку построения графиков — требовалось, чтобы она в реальном времени обновляла миллионы точек данных на диаграмме. Используемая библиотека могла либо обновлять графики в реальном времени, либо поддерживать графики с миллионами точек данных, но не то и дру- гое одновременно. Я думал, что справлюсь с этой задачей за несколько дней. Через три недели я все еще был убежден, что до окончания работы рукой подать. Каждый день мне казалось, что решение совсем рядом, и на пятую неделю у меня появился рабочий прототип. Комментарии 221 За это время я много узнал о том, как работает библиотека, каковы ее возможности и ограничения. Поэтому я потратил несколько часов на то, чтобы оформить мои знания в комментарий длиной в страницу, который я включил в исходный код. Я был убежден, что каждый, кому потребуется внести изменения в работу про- граммы, столкнется с теми же (простыми на первый взгляд) проблемами, что и я, а написанная мной документация сэкономит им целые недели работы. Такие комментарии могут занимать несколько абзацев, из-за чего они кажутся неуместными в файлах с исходным кодом. Но содержащаяся в них информация бесценна для любого специалиста, который будет заниматься сопровождением программы. Не бойтесь включать в свой код длинные, подробные комментарии, которые объясняют, как он работает. Другие программисты могут не знать тонкости вашей реализации кода, они могут понять их неправильно или упустить их из виду. Если разработчика комментарии не интересуют, он с легкостью их пропустит, зато те, кому они нужны, будут благодарны. Как и в предыдущих случаях, этот вид комментариев не должен заменять докумен- тацию модуля или функции (для которой создаются doc-строки). Комментарии типа «полученный опыт» — не учебник и не сборник рецептов для пользователей програм- мы. Они предназначены для разработчиков, читающих исходный код. Так как мой комментарий относился к библиотеке с открытым кодом и мог пригодиться другим, я опубликовал его в ответе на общедоступном сайте https://stackoverflow.org, где он оказался доступен другим пользователям, оказавшимся в аналогичной ситуации. Комментарии об авторских правах и интеллектуальной собственности Некоторые компании-разработчики или проекты с открытым кодом используют политику включения сведений об авторских правах и интеллектуальной собствен- ности, а также текстов лицензий в начало каждого файла с исходным кодом. Такие аннотации должны содержать всего несколько строк и выглядеть примерно так: """Cat Herder 3.0 Copyright (C) 2021 Al Sweigart. All rights reserved. See license.txt for the full text.""" Если возможно, включите ссылку на внешний документ или веб-сайт с полным текстом лицензии (вместо того, чтобы включать всю длинную лицензию в начало каждого файла с исходным кодом). Прокручивать несколько лишних экранов текста каждый раз, когда вы открываете файл с исходным кодом, утомительно, а публика- ция текста полной лицензии не обеспечивает дополнительной юридической защиты. Профессиональные комментарии На моей первой работе в качестве программиста старший коллега, которого я очень уважал, отвел меня в сторону и объяснил, что поскольку мы иногда 222 Глава 11.Комментарии, doc-строки и аннотации типов предоставляем исходный код наших продуктов клиентам, очень важно выдер- живать профессиональный тон в комментариях. Как выяснилось, я написал «Какого черта?» в одном из комментариев, относящихся к особенно противной части кода. Я устыдился, немедленно извинился и отредактировал текст. С этого момента я пишу в комментариях (даже в персональных проектах) только про- фессиональные замечания. Возможно, вам захочется высказать свое раздражение или проявить остроумие в комментариях программы, но делать так не стоит. Вы не знаете, кто будет читать ваш код в будущем, а тональность текста легко интерпретируется неверно. Как я объяснял в разделе «Избегайте шуток, каламбуров и культурных отсылок», с. 91, лучше всего писать комментарии прямолинейно, четко и без юмора. Кодовые метки и комментарии TODO Программисты иногда оставляют короткие комментарии, напоминающие им о работе, которую еще предстоит сделать. Обычно их оформляют в виде кодовых меток — комментариев, которые предваряет метка, записанная в верхнем регистре (например, TODO ). В идеале для памяток лучше использовать средства управления проектами, а не зарывать их в исходном коде. Но в небольших персональных про- ектах, в которых такие инструменты не используются, встречающиеся время от времени метки TODO могут стать полезным напоминанием. Пример: _chargeIonFluxStream() # TODO: Выяснить, почему каждый вторник происходит сбой. Для таких напоминаний часто используются следующие метки: TODO — общее напоминание о работе, которую необходимо выполнить; FIXME — эта часть кода работает не полностью; HACK — эта часть кода работает (возможно, по минимуму), но ее можно улучшить; XXX — общее предупреждение, часто весьма серьезное. За метками, записанными в верхнем регистре, следует давать более конкретные описания задачи или проблемы. Позднее вы сможете провести поиск меток в ис- ходном коде и найти фрагмент, который необходимо доработать. С другой стороны, у таких напоминаний есть и недостаток: о них легко забыть, если только вы не читаете ту часть кода, где они находятся. Кодовые метки не заменяют формальной системы отслеживания ошибок или программ отправки отчетов об ошибках. Если вы используете кодовые метки в своей программе, я рекомендую предельно упростить их: используйте только TODO и откажитесь от остальных. Doc-строки 223 Магические комментарии и кодировка исходных файлов Возможно, вам встречались исходные файлы .py , в начале которых находились строки следующего вида: #!/usr/bin/env python3 ❶ # -*- coding: utf-8 -*- ❷ Магические комментарии в начале файла предоставляют информацию об интерпре- таторе или кодировке. Строка ❶ (о которой я упоминал в главе 2) сообщает вашей операционной системе, какой интерпретатор следует использовать для выполнения инструкций в файле. Второй магический комментарий в строке ❷ определяет кодировку. В данном случае строка определяет, что для этого исходного файла должна использоваться кодировка UTF-8. Включать эту строку почти всегда не обязательно, потому что большинство редакторов и IDE уже сохраняет файлы с исходным кодом в кодировке UTF-8, а все версии Python, начиная с Python 3.0, определяют UTF-8 как кодировку по умолчанию. Файлы в кодировке UTF-8 могут содержать любые символы, так что ничто не мешает вам включить в исходный файл .py английские, китайские или арабские символы. Если вам потребуется информация о Юникоде и кодировке строк, я рекомендую публикацию в блоге Неда Бэтчелдера (Ned Batchelder) «Pragmatic Unicode» по адресу https://nedbatchelder.com/text/unipain.html. Doc-строки Doc-строки представляют собой многострочные комментарии, расположенные либо в начале файла .py с исходным кодом модуля, либо непосредственно после коман- ды class или def . Они содержат документацию об определяемом модуле, классе, функции или методе. Средства автоматизированного генерирования документации используют их для генерирования внешних файлов с документацией — например, справочных файлов или веб-страниц. Doc-строки должны быть оформлены в виде многострочных комментариев в трой- ных кавычках (вместо однострочных комментариев, начинающихся с решетки # ). Doc-строки всегда используют утроенные двойные кавычки вместо утроенных одинарных кавычек. Например, ниже приведен фрагмент файла sessions.py из по- пулярного модуля requests : # -*- coding: utf-8 -*- ❶ """ ❷ requests.session 224 Глава 11.Комментарии, doc-строки и аннотации типов This module provides a Session object to manage and persist settings across requests (cookies, auth, proxies) """ import os import sys --snip— class Session(SessionRedirectMixin): """A Requests session. ❸ Provides cookie persistence, connection-pooling, and configuration. Basic Usage:: >>> import requests >>> s = requests.Session() >>> s.get('https://httpbin.org/get') --snip-- def get(self, url, **kwargs): r"""Sends a GET request. Returns :class:`Response` object. ❹ :param url: URL for the new :class:`Request` object. :param \*\*kwargs: Optional arguments that ``request`` takes. :rtype: requests.Response """ --snip-- Файл sessions.py содержит doc-строки для модуля ❷ , класса Session ❸ и метода get() класса Session ❹ . Обратите внимание: хотя doc-строка модуля должна быть первой строкой в модуле, она располагается после любых специальных комментариев — в частности, определения кодировки ❶ Позднее вы можете прочитать doc-строки модуля, класса, функции или метода, проверяя атрибут __doc__ соответствующего объекта. Так, в следующем примере проверяются doc-строки для получения дополнительной информации о модуле sessions, классе Session и методе get() : >>> from requests import sessions >>> sessions.__doc__ '\nrequests.session\n\n\nThis module provides a Session object to manage and persist settings across\nrequests (cookies, auth, proxies).\n' >>> sessions.Session.__doc__ "A Requests session.\n\n Provides cookie persistence, connection-pooling, and configuration.\n\n Basic Usage::\n\n >>> import requests\n --snip-- >>> sessions.Session.get.__doc__ 'Sends a GET request. Returns :class:`Response` object.\n\n :param url: URL for the new :class:`Request` object.\n :param \\*\\*kwargs: --snip-- Doc-строки 225 Средства автоматизированного документирования могут пользоваться doc- строками для предоставления информации, соответствующей контексту. Одно из таких средств — встроенная функция Python help() — выводит doc-строку пере- данного ей объекта в более удобочитаемом формате, чем у необработанной строки __doc__ . Данная возможность может оказаться полезной при экспериментах с ин- терактивной оболочкой, потому что вы можете немедленно получить информацию о любых модулях, классах и функциях, которые вы пытаетесь использовать: >>> from requests import sessions >>> help(sessions) Help on module requests.sessions in requests: NAME requests.sessions DESCRIPTION requests.session This module provides a Session object to manage and persist settings -- More -- Если doc-строка слишком велика, чтобы поместиться на экране, Python выводит подсказку -- More -- в нижней части окна. Нажмите ENTER, чтобы прокрутить текст к следующей строке, пробел для вывода следующей страницы или Q для прекращения просмотра doc-строки. В общем случае doc-строка должна содержать одну строку текста с обобщающим описанием модуля, класса или функции, за которым следует пустая строка и более подробная информация. Для функций и методов она может включать информацию об их параметрах, возвращаемом значении и побочных эффектах. Doc-строки пи- шутся для других программистов, а не для пользователей программы, поэтому они должны содержать техническую информацию, а не обучающие советы. У doc-строк также есть второе ключевое преимущество: они интегрируют доку- ментацию в исходный код. Когда документация пишется отдельно от кода, о ней часто вообще забывают. С другой стороны, когда doc-строки размещены в начале модулей, классов и функций, информацию легко просматривать и обновлять. Возможно, вы не сможете сразу писать doc-строки, если работа над кодом, ко- торый вы хотите описывать, еще не завершена. В таком случае включите в doc- строку комментарий TODO с напоминанием. Например, следующая вымышленная функция reverseCatPolarity() содержит плохую doc-строку, которая утверждает очевидное: def reverseCatPolarity(catId, catQuantumPhase, catVoltage): """Reverses the polarity of a cat. 226 Глава 11.Комментарии, doc-строки и аннотации типов TODO Finish this docstring.""" --snip-- ( """Меняет полярность у кота. TODO: Закончить эту doc-строку) Так как каждый класс, функция и метод должны содержать doc-строку, может по- явиться искушение написать минимальную документацию и двигаться дальше. Без комментария TODO слишком легко забыть о том, что doc-строку следует переписать. PEP 257 содержит дополнительную документацию о doc-строках по адресу https:// www.python.org/dev/peps/pep-0257/. Аннотации типов Во многих языках программирования используется статическая типизация; это означает, что программист должен объявить типы данных всех переменных, пара- метров и возвращаемых значений в исходном коде. Такая возможность позволяет интерпретатору или компилятору проверить правильность применения всех объ- ектов до запуска программы. В Python используется динамическая типизация: переменные, параметры и возвращаемые значения могут иметь любой тип данных и даже менять типы данных во время выполнения программы. На динамических языках обычно проще программировать, потому что они требуют меньше формаль- ных определений, но зато в них отсутствуют средства предотвращения ошибок, присущие статическим языкам. Когда вы пишете строку кода Python — например, round('forty two') , вы можете не понять, что строка передается функции, полу- чающей только аргументы int и float , пока программа не будет запущена и не про- изойдет ошибка. Языки со статической типизацией выдают ранние предупреждения при присваивании значения или передаче аргумента неправильного типа. Аннотации типов в Python предоставляют необязательные средства статической типизации. В следующем примере аннотации типов выделены жирным шрифтом: def describeNumber(number |