Книга: «Программирование на Python с помощью GitHub Copilot и ChatGPT.» |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2024-08-11 15:02 Привет, Хаброжители! В наши дни люди пишут компьютерные программы совсем не так, как раньше. Используя GitHub Copilot, можно простым языком описать, что должна делать программа, а искусственный интеллект тут же сгенерирует ее. Узнайте, как создавать и улучшать программы на Python с помощью ИИ, даже если прежде вы не написали ни строчки компьютерного кода. Сэкономьте время на рутинном программировании и воспользуйтесь услугами ИИ, способного мгновенно воплотить ваши идеи в жизнь. Заодно выучите Python! Проектирование функций В этой главе
Этот вопрос важен для использования Copilot, но выходит далеко за рамки этой книги. Люди тоже постоянно борются со сложностями. Если опытные инженеры-программисты пытаются написать код для решения слишком сложной задачи, не разбивая ее на мелкие, более просто решаемые части, то у них тоже часто возникают проблемы. Решением для людей стало использование функции, которая выполняет только одну задачу. Существуют различные правила, как написать такую функцию с точки зрения количества строк кода, но в основном речь в них идет о написании чего-то, что: 1) выполняет одну задачу; 2) не является настолько сложным, что это было бы трудно корректировать. Студенты, которые учились программировать по старинке, без Copilot, около месяца изучали синтаксис в коде длиной 5–10 строк, прежде чем мы начинали знакомить их с функциями. В этот момент вполне естественно сразу сказать им не писать в одной функции больше кода, чем они смогут протестировать и отладить. Поскольку вы учитесь работать с Copilot, а не с синтаксисом напрямую, наша задача в этой главе состоит в том, чтобы рассказать вам о функциях и о том, какие задачи разумно и неразумно решать, используя Copilot в рамках одной функции. Чтобы помочь вам получить представление о функциях, мы приведем несколько примеров. В них мы будем использовать центральный рабочий процесс взаимодействия с Copilot: цикл написания запросов, получения кода от Copilot и проверки его правильности. В функциях, создаваемых Copilot, вы начнете видеть основные инструменты программирования, такие как циклы, условия и списки, которые мы рассмотрим в следующих двух главах. ФУНКЦИИ Прежде чем вы сможете приступить к изучению нюансов написания функций, вам нужно получить некое представление об их назначении в ПО. Функции — это небольшие задачи, которые помогают решать более крупные задачи, которые, в свою очередь, помогают решать еще более крупные задачи, и т. д. Вероятно, вы уже интуитивно поняли, что большие задачи необходимо разбивать на более мелкие, и мы используем это в следующем примере. Если коротко, то ваша задача — найти все слова из списка. К сожалению, такое описание задачи само по себе бесполезно. В нем не говорится, какие шаги нужно выполнить, чтобы решить ее. Попробуйте прямо сейчас поработать над этой задачей пару минут. Как бы вы начали? Как бы вы разбили задачу на части, чтобы сделать ее более выполнимой? Вы можете сказать: «Хорошо, найти все слова — большая задача, но меньшая задача — найти первое слово (CAT). Сначала я поработаю над этим!» Это пример того, как можно взять большую задачу и разбить ее на более мелкие. Чтобы решить всю головоломку, вы можете повторить эту небольшую задачу для каждого слова, которое вам нужно найти. Как же найти отдельное слово, например CAT? Даже эту задачу можно разбить, чтобы облегчить ее решение. Например, можно разделить ее на четыре подзадачи: поиск CAT слева направо, поиск CAT справа налево, поиск CAT сверху вниз и поиск CAT снизу вверх. Мы не только ставим перед собой все более и более простые задачи, но и делим нашу работу на отдельные логические части. И что самое важное, это более простые задачи, код которых мы попросим Copilot написать и в конечном итоге соединить в наши полноценные программы. Решение большой задачи путем ее разделения на более мелкие называется декомпозицией. Это один из самых важных навыков в разработке программного обеспечения. Мы посвятили ему главу 7. Пока же вам важно понимать, когда задача слишком велика, чтобы просить Copilot выполнить ее. Просьба сделать новую видеоигру, которая представляет собой сочетание Wordscapes и Wordle, будет безуспешной. Однако вы можете дать Copilot указание написать функцию, которая позволяет решить более крупную задачу; например, у вас может быть часть кода, проверяющая, есть ли указанное игроком слово в списке допустимых слов. Copilot может хорошо выполнить данную часть, и это поможет ему приблизиться к решению более крупной задачи. Компоненты функции Происхождение названия «функция» восходит к математике, где функции определяют выход чего-либо на основе входных данных. Например, если , то мы можем сказать, что, когда x равно 6, f(x) будет 36. В программировании функции тоже имеют ожидаемый вывод для определенных входных данных, так что это название вполне подходит и для программирования. У функции может быть только один вывод; ключевое слово, которое следует искать при определении того, что она выводит, — это return. Все, что идет за return, представляет собой вывод. В этом коде будет возвращено либо num1, либо num2. Функции не обязаны что-либо возвращать (например, функция, которая выводит список на экран, не имеет причин возвращать некие данные), так что, если вы не видите оператор возврата, это не обязательно проблема, поскольку функция может делать что-то еще (взаимодействовать с пользователем), а не возвращать данные. Кроме того, функции должны либо возвращать что-то, либо не возвращать: они не могут возвращать что-то в одних случаях и ничего в других. Мы попросили Copilot сгенерировать эту функцию с помощью комментариев, однако на самом деле такой подход усложняет его работу. Сначала Copilot должен правильно составить заголовок, в том числе выяснить, сколько параметров вам нужно получить. Затем он должен верно создать рабочий код функции. Существует альтернативный способ: предложить Copilot написать код такой функции, который может помочь ему сгенерировать код наболее точно и нам лучше понять, что именно она должна сделать. Для этого нужно написать строки документации, и мы будем использовать их для написания функций на протяжении большей части книги. СТРОКИ ДОКУМЕНТАЦИИ ОБЪЯСНЯЮТ ПОВЕДЕНИЕ ФУНКЦИЙ Написав заголовок и строки документации, вы облегчите Copilot генерацию правильного кода. В заголовке вы сами определяете имя функции и указываете имена всех параметров, которые должны использоваться. После заголовка функции вы приводите строку документации, которая расскажет Copilot, что делает эта функция. Затем, как и раньше, Copilot сгенерирует код. Поскольку мы дали Copilot заголовок функции, он сможет учиться на нем, что уменьшит вероятность совершения ошибок. Вот как выглядел бы альтернативный подход при написании той же функции larger: Обратите внимание, что мы написали заголовок функции, а также строки документации, а Copilot предоставил тело функции. Использование функции Как использовать имеющуюся функцию? Вспомним аналогию с . Как дать функции значение 6 для x, чтобы она вернула 36? Посмотрим, как это сделать с помощью кода, используя функцию larger, которую мы только что написали.
общий формат вызова функции выглядит так:
Когда вы видите скобки сразу после имени, это всегда означает, что здесь есть вызов функции. Это будет важно для нашего рабочего взаимодействия с Copilot, особенно когда мы будем тестировать функции, чтобы убедиться, что они работают правильно. Нам также понадобится вызывать функции, чтобы выполнять работу, поскольку они сами ничего не сделают, пока мы их не вызовем. ПРЕИМУЩЕСТВА ФУНКЦИЙ Мы уже упоминали, что функции имеют решающее значение для декомпозиции задачи. Они играют важную роль в ПО и по ряду других причин.
Вы можете спросить: «Я понимаю, что эти преимущества важны для людей, но как они влияют на Copilot?» В целом мы считаем, что все принципы, применимые к людям, применимы и к Copilot, хотя иногда причины этого совсем иные. Copilot может не испытывать когнитивной нагрузки, но будет работать лучше, если мы попросим его решить задачи, аналогичные тем, которые уже решались людьми раньше. Поскольку люди пишут функции для решения задач, Copilot будет подражать им и тоже писать функции. После того как мы написали и протестировали функцию, вручную или с помощью Copilot, мы не захотим писать ее снова. Знать, как проверить работу программы, важно независимо от того, кто написал код: человек или Copilot. Он тоже может совершать ошибки при создании кода, поэтому мы хотим находить их быстро, как и в случае с кодом, написанным человеком. Даже если вы работаете только над собственным кодом и никогда никого не просите читать его, мы, как программисты, которым приходилось редактировать свой код, написанный много лет назад, должны сказать: очень важно, чтобы ваш код был читаемым, даже если единственный человек, читающий его, — это вы. РОЛИ ФУНКЦИЙ Функции играют в программировании самые разные роли. Если коротко, то программы — это функции, которые часто вызывают другие функции. Важно отметить, что все программы, в том числе написанные на Python, начинаются с одной функции (называемой main в таких языках, как Java, C и C++). Функция main в Python — это, по сути, первая строка кода, которая не находится внутри функции. Но если каждая программа начинается с одной функции, а мы только что сказали вам, что пытаться решить большую задачу с помощью одной функции — это ошибка, то как же это работает? Ну, main будет вызывать другие функции, которые, в свою очередь, будут вызывать другие и т. д. Код по-прежнему будет выполняться (в основном) последовательно в каждой функции, поэтому может начинаться с main, но затем переходить к другой функции и т. д.
На рис. 3.2 представлена схема того, как код из листинга 3.1 будет выполняться компьютером. Мы намеренно привели пример, содержащий множество вызовов функций, чтобы связать воедино то, что вы узнали только что. Опять же это не практический код; он приведен только в учебных целях. Давайте проследим за его выполнением. Возможно, будет проще обратиться к рис. 3.2, чем к листингу 3.1, но любой из вариантов подойдет. Рис. 3.2. Последовательность выполнения функции в нашем примере из листинга 3.1 Программа начнет выполнение с первой строки в коде Python, которая не является функцией (print(«Hi»)). Хотя в Python нет функции main как таковой, мы будем называть блок кода после функций main, чтобы облегчить объяснение. Код выполняется последовательно, если только не встречает команды, которые дают ему указание выполнить код в другом месте. Так, после выполнения print(«Hi») он перейдет к следующей строке, которая является вызовом функции funct1: funct1(). Вызов funct1 меняет место выполнения кода на начало этой функции, которое является оператором: print(«there»). Следующая строка funct1 вызывает funct2, поэтому программа выполнит первую строку funct2: print(«my»). Что интересно, по завершении работы funct2 больше нет строк кода для выполнения, поэтому программа автоматически возвращается к первой строке, следующей за вызовом funct2 в funct1. (Если вызов функции находится в середине другого оператора, то этот оператор возобновит выполнение, но в данном примере вызовы функций находятся каждый на отдельной строке.) Вам может быть интересно, почему код переходит на следующую строку после вызова funct2, а не возвращается к вызову funct2. Проблема в том, что если бы он вернулся к вызову funct2, то навсегда бы застрял в этом вызове. Как результат, функции всегда возвращаются к следующему фрагменту кода (в данном примере — к следующей строке) после их вызова. Продолжим пример: следующей выполненной строкой кода будет строка, которая выводит на экран friend. Очередная строка вызывает функцию funct3, которая выводит точку (.) и возвращается обратно к источнику вызова. Итак, мы вернулись в funct1, в строку print(""). Вывод на экран пустого фрагмента текста приводит к появлению новой строки. Теперь funct1 завершена, поэтому передает выполнение обратно в следующую строку main после ее вызова. Мы подозреваем, что вы уже поняли, о чем идет речь, поэтому немного ускоримся:
С помощью этого примера мы бы хотели также обсудить различные роли, которые играют функции. Задача вспомогательной функции — облегчить работу другой функции. В каком-то смысле каждая из функций, которая не является main, представляет собой вспомогательную. Одни функции просто вызывают группу других, не выполняя никакой собственной работы. В нашем примере таких нет. Однако если убрать три оператора print из funct1, она станет именно такой координирующей функцией. Другие функции могут вызывать вспомогательные, а затем выполнять некую работу. В нашем примере funct1 — как раз такая: она вызывает другие функции, но при этом и сама совершает некие действия. Есть группа функций, которые существуют сами по себе, не вызывая другие (за исключением, возможно, тех, которые уже поставляются с Python) ради помощи — мы будем называть их конечными, листовыми (leaf). Почему? Если представить все вызовы функций в виде большого дерева, то такие функции — листья, поскольку из них ничего не выходит. В нашем примере функции funct2, funct3 и funct4 являются конечными. В этой главе нас в первую очередь интересуют именно такие, но здесь и особенно в последующих главах вы увидите примеры и других видов функций. ЧТО ЯВЛЯЕТСЯ АДЕКВАТНОЙ ЗАДАЧЕЙ ДЛЯ ФУНКЦИИ Не существует четкого правила, что делает функцию хорошей, но есть некоторые интуитивные соображения и рекомендации, которыми мы можем поделиться. Однако не стоит заблуждаться: определение хороших функций — это навык, который требует времени и практики. Чтобы помочь вам в этом, в данном разделе мы изложим наши рекомендации и приведем несколько удачных и не очень примеров, чтобы помочь вам развить интуицию. Затем в разделе 3.6 мы приведем примеры того, как писать хорошие функции. Атрибуты хороших функций Вот несколько рекомендаций, которые, по нашему мнению, помогут вам понять, что делает функцию хорошей.
Примеры хороших (и плохих) конечных функций Вот примеры хороших функций:
ЦИКЛ ПРОЕКТИРОВАНИЯ ФУНКЦИЙ С ПОМОЩЬЮ COPILOT Цикл проектирования функций с помощью Copilot содержит следующие этапы (рис. 3.3).
Все это явно неправильно, но в следующей главе мы расскажем о том, как читать код, чтобы вы могли быстрее обнаружить неправильный более сложный код и поняли, где и как его исправить (это, возможно, даже важнее). В последующих главах мы будем расширять этот цикл и добавим в него эффективные методы отладки, а также продолжим практиковаться в улучшении запросов. Рис. 3.3. Общий цикл редактирования с помощью Copilot. Предполагается, что вы определяете подходящую функцию ПРИМЕРЫ СОЗДАНИЯ ХОРОШИХ ФУНКЦИЙ С ПОМОЩЬЮ COPILOT В этом разделе мы напишем несколько функций с помощью Copilot, чтобы вы могли увидеть цикл их проектирования, о котором мы говорили чуть раньше. Наша цель в этой главе не состоит в том, чтобы помочь читать код; тем не менее мы покажем программные средства (иногда называемые конструкциями) в решениях, которые очень часто встречаются в коде (например, операторы if, циклы), поэтому будем специально указывать на них, когда они нам попадутся. Затем в главе 4 мы более подробно расскажем о том, как читать этот код. Выбор акций для Дэна Дэн инвестирует в акции AAAPL. Он купил 10 акций по 15 долларов за штуку. Теперь каждая акция стоит $17. Дэн хотел бы узнать, сколько денег он заработал на этой сделке.
Теперь нам нужны строки документации. В них мы должны объяснить, для чего нужен каждый параметр, используя его название в одном предложении. Вдобавок следует указать, что должна сделать функция. Когда мы добавим строки документации, полный запрос для Copilot будет выглядеть так:
Набрав этот запрос, перейдите к следующей строке и нажмите клавишу Tab. Copilot заполнит код функции. Не беспокойтесь о том, что код будет с отступами: он и должен быть с ними, и если их нет, то это, по сути, ошибка! Вот что мы получили от Copilot:
Этот код кажется подходящим. В скобках он вычисляет разницу между текущей ценой и ценой покупки (знак – используется для вычитания), а затем умножает эту разницу на количество акций, которые у нас есть (символ * используется для умножения). Проверка подобного кода — полезный навык, и мы серьезно займемся им в следующей главе. Еще один полезный навык — тестирование функции. Чтобы протестировать функцию, мы вызываем ее, используя различные входные данные, и наблюдаем за выходом в каждом случае. Мы можем сделать это, попросив Copilot вызвать функцию, а затем запустив нашу программу, так же как ранее мы делали это с нашей функцией larger. Затем мы можем попросить Copilot изменить вызов функции, попросив его вызвать функцию с другими входными данными и снова запустить нашу программу, повторяя все это столько раз, сколько потребуется. Однако нам кажется более простым и удобным вызывать функцию самостоятельно из интерактивного окна. Таким образом, мы можем вызывать функцию сколько угодно раз, не задействуя Copilot и не загромождая нашу программу тем, что мы все равно удалим. Чтобы попробовать этот интерактивный подход, выделите весь код функции и затем нажмите Shift+Enter (вы можете получить доступ к аналогичному интерактивному сеансу, выделив текст и щелкнув правой кнопкой мыши, затем выбрать Run Selection/Line (Выполнить выделение/строку) в окне Python, но в данном случае мы будем исходить из того, что вы используете Shift+Enter). На рис. 3.4 показано, как будет выглядеть экран, если выделить текст функции и нажать Shift+Enter. Рис. 3.4. Запуск Python в интерактивном сеансе в терминале VS Code. Обратите внимание на символ >>> в нижней части терминала В нижней части появившегося окна вы увидите три знака «больше»: >>>. Это называется подсказкой, и здесь вы можете вводить код Python. (Эта подсказка не имеет ничего общего с тем запросом, который мы используем при взаимодействии с Copilot.) Вы сразу же увидите результат работы набранного кода, что удобно и быстро. Чтобы вызвать функцию money_made, нужно указать три аргумента, и они будут присвоены параметрам слева направо. То, что мы поставим первым, будет присвоено параметру num_shares, то, что вторым, — параметру purchase_share_price, а то, что третьим, — параметру current_share_price. Ну что, попробуем! В подсказке введите >>> money_made(10, 15, 17) и нажмите Enter (или Shift+Enter). Не набирайте >>>, так как эти символы уже есть; мы добавляем их, чтобы было понятно, где мы набираем текст. На рис. 3.5 приведен пример запуска функции в терминале в подсказке Python:
Рис. 3.5. Вызов функции money_made из подсказки Python в терминале VS Code Вы увидите результат:
Правильный ли он? Ну, мы купили 10 акций, и каждая из них подорожала на 2 доллара (с 15 до 17), так что мы заработали 20 долларов. Выглядит неплохо! Однако мы еще не закончили тестирование. Функцию следует проверять по-разному, а не одним способом. Один тестовый сценарий говорит лишь о том, что функция сработала с определенными входными параметрами, которые вы предоставили. Чем больше тестовых сценариев мы опробуем для проверки функции разными способами, тем больше будем уверены в том, что функция правильная. Как мы можем протестировать эту функцию по-другому? Мы ищем входные данные, которые каким-то образом относятся к другой категории. Одним из не очень хороших тестов сейчас было бы сказать: «Что, если наши акции вырастут с 15 до 18 долларов, а не с 15 до 17?» Это практически тот же тест, что и раньше, и есть шанс, что он сработает отлично. Хорошая идея — проверить, что произойдет, когда пакет акций начнет падать в цене. В этом случае мы ожидаем получить отрицательный результат. И похоже, наша функция отлично работает с этой категорией тестов. Вот наш вызов функции и возвращенный результат:
Какие еще тесты мы можем провести? Ну, иногда цена на акции вообще не меняется. В этом случае мы ожидаем 0. Проверим:
Выглядит хорошо! Тестирование — это сочетание науки и искусства. Сколько категорий можно протестировать? Действительно ли эти два вызова относятся к двум разным категориям? Не пропустили ли мы какие-нибудь категории? Вы улучшите свои способности к тестированию, практикуясь, и мы посвятим этому главу 6. На данный момент похоже, что наша функция money_made выполняет свою работу. Функция может использовать переменные (а не только свои параметры) в коде, и мы хотим показать вам пример этого сейчас, чтобы вы были готовы увидеть, как это делает Copilot. Эквивалентный способ написания кода для нашей функции money_made выглядит так:
Возможно, вам будет даже проще прочитать этот код: сначала он вычисляет разницу в цене акций, а затем умножает ее на их количество. Мы рекомендуем протестировать эту версию, чтобы убедиться в ее правильности. Пароль Лео Лео регистрируется на сайте новой социальной сети ProgrammerBook. Он хочет убедиться, что его пароль надежен.
В ответ на это Copilot написал:
Посмотрите на этот код. Оператор != — это оператор «не равно», а каждая строка, которая не считается надежным паролем, заключена в одинарные кавычки. Мы будем использовать их каждый раз, когда будем работать со строковым значением. Опять же о том, как читать код, мы поговорим в следующей главе, а пока надеемся, что код имеет ясный смысл: похоже, он проверяет, что паролем не являются слова password или qwerty, что соответствует нашему определению надежного пароля. Теперь убедимся, что эта функция действительно работает, сделав несколько тестовых вызовов. Начнем с проверки паролей, которые не являются надежными. Мы должны получить ответ False для каждого из них — и мы это сделаем!
Отлично! Попробуем ввести надежный пароль. Здесь мы должны увидеть True:
Отлично! Теперь мы видим, что функция иногда возвращает False, а иногда True, так что по крайней мере не всегда возвращает False. Попробуем еще раз:
Технически True — это правильно, но Leo — плохой пароль. Нам действительно следовало бы получше определить надежный пароль. Изменим наш запрос, чтобы дать более полное определение надежного пароля. Вот наш следующий запрос и то, что выдал Copilot:
То, что выражение for char in password (символ в пароле) встречается несколько раз, показывает, как Python рассматривает каждый символ пароля. Данный способ позволяет использовать так называемый цикл (это ключевая тема, которую мы будем изучать в главе 5). Конечно, вполне возможно, что вы получили от Copilot не тот же код, что и мы. Но, судя по коду, который получили мы, похоже, что первая часть ищет любой прописной символ, вторая — любую цифру, а третья — что-то, что не является isalnum. Возможно, isalnum означает «алфавитно-цифровой». Подразумевает ли это специальные символы и если да, то какие? Протестируем эту функцию и посмотрим, насколько хорошо мы справляемся с задачей:
Ой! Мы получили неправильный ответ на третий пароль. Он выглядит довольно надежным, но это не так, поскольку в нем отсутствует специальный символ. Наша функция вернула True, но это неверное значение: она должна была вернуть False. Код, который выдал Copilot, неправильный. Возможно, код, который вы получили, работает нормально, но нам не повезло, и важно знать, как определить (как мы сделали только что), когда код неверен, и затем исправить его. Сейчас не так важно знать, почему он неправильный, но если вам интересно, почему наш запрос мог привести к неправильному поведению, то это потому, что мы не указали, что подразумеваем под специальным символом, ведь в коде, который мы получили, пробелы считаются специальными символами. На данный момент у нас есть два варианта работы с неправильным кодом. Первый вариант — нажать Ctrl+Enter и просмотреть другие предложения, которые выдает Copilot. Возможно, одно из них будет связано со специальными символами, которые выглядят иначе, чем несработавшие? Действительно, на нашем компьютере мы видим такие варианты, в том числе и этот: Протестируйте эту функцию со строками типа Leo, N3w Y0rk J375 и N3w Y0rk J375$ — и увидите, что функция работает хорошо.Второй вариант — немного поработать над запросом, то есть настроить его так, чтобы повлиять на выдачу Copilot. В первоначальном запросе мы говорили о специальных символах. Оглядываясь назад, можно сказать, что наша речь была расплывчатой. Возможно, мы имели в виду что-то более конкретное, например пунктуацию. Если мы в запросе говорим конкретно о пунктуации, то взаимодействие с Copilot будет выглядеть так:
Выглядит хорошо! В последней строке говорится о пунктуации, что внушает надежду. Проверим:
Посмотрите на нижнюю часть сообщения об ошибке, 'string' не определена, так ведь? Мы сталкиваемся с проблемой, похожей на ту, которую видели в главе 2, когда говорили о модулях. Copilot хочет использовать модуль под названием string, но этот модуль должен быть импортирован, прежде чем мы сможем его задействовать. В Python существует множество модулей, но string хорошо известен. По мере того как вы будете работать с Copilot, вы узнаете, какие модули используются часто, чтобы понимать, как их импортировать. Вы также можете провести быстрый поиск в Интернете на тему «Является ли string модулем Python», и результаты подтвердят, что это так. Что нам нужно сделать, так это импортировать модуль. Обратите внимание, что эта ситуация несколько отличается от той, с которой мы сталкивались в главе 2. Там мы видели, что происходит, когда код из Copilot импортирует модули, которые у нас не установлены, и, чтобы решить проблему, нам пришлось установить пакет с ними. В данном случае код из Copilot использует модуль, который уже установлен вместе с Python, но он забыл его импортировать. Таким образом, нам не нужно устанавливать string; нам надо просто импортировать его. ИМПОРТИРОВАНИЕ МОДУЛЕЙ Добавим import string в начало нашего кода:
Теперь код работает хорошо:
Последнее слово — True — говорит о том, что это надежный пароль, поскольку к нему добавлен знак препинания $. Надеемся, теперь вы убедились в ценности тестирования! Иногда наши студенты не тестируют свой код. Они считают, что написанный ими код правильный, поскольку он имеет смысл для них. Между начинающими и опытными программистами есть интересное различие: новички часто полагают, что их код правильный, в то время как опытные программисты считают, что их код неправильный, до тех пор, пока тщательно не протестируют его и не докажут обратное. Помимо этого, мы обнаружили, что наши студенты иногда не справляются с тестами, поскольку им очень обидно узнать, что код неправильный. Но лучше узнать об этом сейчас, чем потом, когда другие люди будут использовать ваш код в серьезном приложении. Находить ошибки в процессе тестирования — это на самом деле хорошо. Более подробно с книгой можно ознакомиться на сайте издательства: » Оглавление » Отрывок По факту оплаты бумажной версии книги на e-mail высылается электронная книга. Для Хаброжителей скидка 25% по купону — Python Источник: habr.com Комментарии: |
|