Лутц М. - Изучаем Python (1077325), страница 103
Текст из файла (страница 103)
479 Закрепление пройденного 7. И 1заЬЬа-выражения, и инструкция Ье( создают объекты функций для последующего вызова. Однако 1авЬЬа-выражения — это именно выражения, и поэтому они могут использоваться для вложения определений функций там, где инструкция Ье( синтаксически недопустима. Нет таких случаев, когда нельзя было бы обойтись без 1ззЬса-выражений, — всегда можно определить идентичную инструкцию Ое( н ссылаться на функцию по имени. Однако 1зззсз-выражения удобно использовать для встраивания небольших фрагментов кода, которые в программе больше нигде не используются. Синтаксически 1авЬЬа позволяет возвращать значение единственного выражения; так как эта конструкция не поддерживает блоки инструкций, она плохо подходит для создания больших функций. Упражнения к четвертой части В этих упражнениях вам будет предложено написать более сложные программы. Обязательно проверьте решения в разделе «Часть 1Ъ'.
Функции«в приложении В; оформляйте свои решения в виде файлов модулей. Ксли будет допущена ошибка, будет очень сложно повторно ввести эти упражнения с клавиатуры в интерактивной оболочке. 1. Основы. В интерактивной оболочке интерпретатора Ру(поп напишите функцию, которая выводит на экран единственный аргумент, и попробуйте вызвать ее несколько раз, передавая объекты различных типов: строки, целые числа, списки, словари.
Затем попробуйте вызвать ее без аргументов. Что произошло? Что произойдет, если передать функции два аргумента? 2. Аргументы. Напишите функцию с именем аддек в файле модуля. Функция должна принимать два аргумента и возвращать их сумму (или конкатенацию). Затем добавьте в конец файла модуля вызовы функции аддег с объектами различных типов (две строки, два списка, два числа с плавающей точкой) и запустите этот файл как сценарий из командной строки операционной системы. Должны ли вы явно производить вывод результатов, чтобы они появились на экране? 3. Переменное число аргументов.
Обобщите функцию ассе« из предыдущего упражнения, чтобы она вычисляла сумму произвольного числа аргументов, и измените вызовы функции так, чтобы ей передавалось больше или меньше двух аргументов. Какой тип имеет возвращаемое значение суммы7 (Подсказка: срез, такой как 8(:0], возвращает пустую последовательность того же типа, что и Я, а с помощью встроенной функции 1уре можно узнать тип объекта — смотрите примеры с функцией а1п в главе 16, где используется подобный прием.) Что произойдет, если функции передать аргументы разных типов? Что произойдет, если ей передать словари? 4.
Передача аргументов ао ключу. Измените функцию зЬЬег из упражнения 2 так, чтобы она принимала и вычисляла сумму(конкатенацию трех аргументов: Ье( аздег(цссб, Ьас, сс1у). После этого Глава 17. Расширенные возможности функций определите значения по умолчанию для каждого из аргументов и поэкспериментируйте с функцией в интерактивной оболочке, Попробуйте передавать ей один, два, три и четыре аргумента. Попробуйте передавать аргументы по именам. Будет ли работать такой вызов: аббес(цс1у=1, особ=2)7 Почему7 Наконец, обобщите новую версию функции аббег так, чтобы принимала и вычисляла сумму/ конкатенацию произвольного числа аргументов, передаваемых по ключу. Решение будет напоминать то, что было получено в упражнении 3, с той лишь разницей, что вам придется выполнить обход словаря, ане кортежа.
(Подсказка: метод б!сс, Кеуз() возвращает список, который можно обойти с помощью цикла тот или шл11е.) б. Напишите функцию с именем ссруб)сс(б1с(), которая копирует словарь, получаемый в виде аргумента. Она должна возвращать новый словарь, содержащий все элементы аргумента. Используйте метод кеуз для выполнения итераций (или в РуЫзоп 2.2, выполните обход ключей словаря без вызова метода кеуа). Копирование последовательностей выполняется достаточно просто (выражение Х(: ) выполняет поверхностное копирование); будет ли этот метод работать со словарями7 6, Напишите функцию с именем абЖ)сс(61с(1, бзс12), которая вычисляет объединение двух словарей. Она должна возвращать новый словарь, содержащий все элементы обоих аргументов (которые, как предполагается, являются словарями).
Если один и тот же ключ присутствует в обоих аргументах, вы можете выбрать значение из любого словаря. Проверьте свою функцию, добавив программный код проверки в файл и запустив его как сценарий. Что произойдет, если вместо словарей передать списки7 Как можно было бы обобщить функцию, чтобы она обрабатывала и этот случай7 (Подсказка: смотрите встроенную функцию 1уре, использовавшуюся ранее.) Имеет ли значение порядок следования аргументов7 7, Дополнительные примеры на сопоставление аргументов.
Сначала определите следующие шесть функций (в интерактивной оболочке или в файле модуля, который затем можно будет импортировать): оег г1(а, ь): ргап1 а, ь в Обычные аргументы оег г2(а, .ь): ртпс а, ь в переменное ~исло позиционных аргументов оег гз(а, . ° ь); рг1пт а, ь в переменное число аргументов ло ключу Оет Гв(а, *Ь, ° с); ртпс а, Ь, с В Смешанный решим оег 15(а, ь=2, сГ3): рггп1 а, ь, с в яргументы со выведениями ло умолчанию Овт 16(а, Ь=2, *с); ргзпт а, Ь, с В Переменное число позиционных В аргументов и со значениями В ло умолчанию Теперь протестируйте следующие вызовы в интерактивной оболочке и попробуйте объяснить полученные результаты — в некоторых слу- 481 Закрепление пройденного чаях вам, возможно, придется вернуться к обсуждению алгоритмов сопоставления в главе 16.
Как вы думаете, смешивание режимов со- поставления вообще можно считать удачным выбором? Можете ли вы придумать ситуации, когда это могло бы оказаться полезным? »> 11(1, г) »> Гцб=г, в=1) »> гг(1, г, з) »> ГЗ(1, х=2, у=з) »> 14(1, 2, 3, х=2, у=з) »> Гб(1) »> Гб(1, 4) »> ГЕ(1) »> 15(1, З, 4) 8.
Снова простые числа. Вспомните следующий фрагмент из главы 13, который определяет — является ли целое положительное число простым: х= у/2 ий>1е х > 1: тт у й х == О: рг(лт у, 'Лвв Гвстсг', Ьгевй х = х-1 е1ве рылт у. '1в рг>ие' В Длл ЗначЕний у > 1 в Остаток х В Обойти блок е1вв й Обнчный внхсд Оформите этот фрагмент в виде функции в файле модуля и добавьте несколько вызовов функции в конец этого файла.
При этом замените оператор / на // в первой строке, чтобы функция могла также обрабатывать числа с плавающей точкой и была неуязвима для истинной операции деления, которую, как планируется в РуФЬоп 3.0, будет выполнять оператор / (описывается в главе б). Что вы можете сказать об отрицательных значениях? Сумеете ли вы повысить скорость работы этой функции? Вывод из вашего модуля должен выглядеть примерно так, как показано ниже: 13 1в ргтэе 13.0 зв рмве !5 Лвв Гаетсг 5 15. О Лвв (ветс г 5. О 9. Генераторы списков. Напишите программный код, который будет создавать новый список, содержащий квадратные корни всех чисел из следующего списка: (2, 4, 9, 15, 25]. Начните с реализации на основе цикла (ог, затем на основе функции вар и, наконец, в виде генератора списков.
Для вычислений используйте функцию всгт из модуля васо (т. е. выполните терог1 эа1Л и вызов езгй. взг1(х)). Какой из трех вариантов на ваш взгляд является лучшим? Модули: общая картина Начиная с этой главы, мы приступаем к детальному изучению модуля в языке Ру(поп — самой крупной организационной программной единицы, которая вмещает в себя программный код и данные, готовые для многократного использования. Если говорить более точно, модули в языке Ру1Ьоп обычно соответствуют файлам программ (или расширениям, написанным на других языках программирования, таких как С, Зача или СФ).
Каждый файл — это отдельный модуль, и модули могут импортировать другие модули для доступа к именам, которые в них определены. Обработка модулей выполняется двумя инструкциями и одной встроенной функцией: (врогг Позволяет клиентам (импортерам) получать модуль целиком 1гов Позволяет клиентам получать определенные имена из модуля ге1оас Обеспечивает возможность повторной загрузки модуля без остановки интерпретатора РуФЬоп В главе 3 были представлены основные принципы, касающиеся модулей, и мы пользовались ими до сих пор. Часть Ч книги мы начнем с подробного описания базовых концепций, а затем перейдем к исследованию расширенных возможностей использования модулей.
В этой первой главе вашему вниманию предлагается общий взгляд на роль модулей в структуре всей программы. В последующих главах мы начнем рассматривать программный код, который основан на этой теории. Попутно мы подробно рассмотрим сведения о модулях, которые до сих пор были опущены: вы узнаете об операции перезагрузки модулей, об атрибутах паве и а11, об импорте пакетов и т. д. Поскольку мо- 486 Глава 18. Модули; общая картина дули и классы — это всего лишь пространства имен, здесь мы также формализуем понятие пространства имен. Зачем нужны модули? В двух словах, модули обеспечивают простой способ организации компонентов в систему автономных пакетов переменных, известных как пространства имен.
Все имена, определяемые на верхнем уровне модуля, становятся атрибутами объекта импортируемого модуля. Как мы видели в предыдущей части, операция импорта предоставляет доступ к именам в глобальной области видимости модуля. Таким образом, в процессе импортирования глобальная область видимости модуля образует пространство имен атрибутов объекта модуля. В конечном счете модули позволяют связывать отдельные файлы в крупные программные системы. Если говорить более определенно, с точки зрения теории модули играют как минимум три роли: Повторное использование программного кода Как говорилось в главе 3, модули позволяют сохранять программный код в виде файлов.
В отличие от программного кода, который вводится в интерактивной оболочке интерпретатора Руь11оп и исчезает безвозвратно после выхода из оболочки, программный код в файлах модулей хранится постоянно — его можно повторно загружать и запускать столько раз, сколько потребуется. Можно добавить, что модули — это место, где определяются имена, известные как атрибутьс, на которые может ссылаться множество внешних клиентов.
Разделение системьг пространств имен Модули в языке Руьпоп также являются самой высокоуровневой единицей организации программ. По существу, они — всего лишь пакеты имен. Модули позволяют изолировать имена в замкнутые пакеты, которые позволяют избежать конфликтов имен, — вы никогда не увидите имя в другом файле, если не импортируете его. Фактически, все, что находится в модуле — выполняемый программный код и создаваемые объекты, — всегда неявно включаетея в модули. Вследствие етого модули являются естественными инструментами группировки компонентов системы.