Главная страница
Навигация по странице:

  • Упражнения к четвертой части

  • Архитектура программы на языке Python

  • Как организована программа

  • Импортирование и атрибуты

  • Математический анализ. 3е издание


    Скачать 4.86 Mb.
    Название3е издание
    АнкорМатематический анализ
    Дата04.02.2022
    Размер4.86 Mb.
    Формат файлаpdf
    Имя файлаpython_01.pdf
    ТипДокументы
    #351981
    страница58 из 98
    1   ...   54   55   56   57   58   59   60   61   ...   98
    Закрепление пройденного
    Контрольные вопросы
    1. Чем отличаются генераторы списков в квадратных скобках и в круг
    лых скобках?
    2. Как связаны между собой генераторы и итераторы?
    3. Как узнать, является ли функция функциейгенератором?
    4. Для чего служит инструкция yield?
    5. Пусть имеются функция и кортеж аргументов, как можно было бы вызвать эту функцию?
    6. Как связаны между собой функция map и генераторы списков? В чем их сходства и различия?
    7. Как связаны между собой lambdaвыражение и инструкция def? В чем их сходства и различия?

    478
    Глава 17. Расширенные возможности функций
    Ответы
    1. Генераторы списков в квадратных скобках воспроизводят сразу весь список целиком. Когда генераторы списков заключаются в круглые скобки, они фактически превращаются в выражениягенераторы,
    которые имеют похожее назначение, но не воспроизводят список результатов целиком. Вместо этого выражениягенераторы возвра
    щают объектгенератор, который поставляет по одному значению при использовании в итерационном контексте.
    2. Генераторы – это объекты, поддерживающие итерационный прото
    кол – они обладают методом next, который выполняет переход к сле
    дующему элементу в последовательности результатов и возбуждает исключение по достижении конца последовательности. В языке Py
    thon существует возможность создавать функциигенераторы с по
    мощью инструкции def, выражениягенераторы в виде генераторов списков, заключенных в круглые скобки, и объектыгенераторы с помощью классов, которые определяют специальный метод
    __iter__
    (обсуждается далее в этой книге).
    3. Функциигенераторы имеют в своем теле инструкцию yield. Во всем остальном они ничем не отличаются от обычных функций.
    4. При наличии этой инструкции интерпретатор Python компилирует функцию как генератор – при вызове она возвращает объектгене
    ратор, который поддерживает итерационный протокол. Когда за
    пускается инструкция yield, она возвращает результат вызываю
    щей программе и приостанавливает работу функции, после этого в ответ на вызов метода next со стороны вызывающей программы функция возобновляет свою работу с позиции после последней вы
    полненной инструкции yield. Функциигенераторы также могут со
    держать инструкцию return, которая завершает работу генератора.
    5. Вызвать функцию можно с использованием applyподобного син
    таксиса: function(*argstuple). Кроме того, можно использовать встроенную функцию apply(function, args), но из будущих версий
    Python эта функция, скорее всего, будет исключена и потому такой способ нельзя считать универсальным.
    6. Вызов функции map напоминает генератор списков тем, что обе кон
    струкции создают новый список с результатами, применяя опера
    цию к каждому элементу последовательности или другого итерируе
    мого объекта, по одному за раз. Главное различие состоит в том, что map применяет к каждому элементу функцию, а генератор списков –
    произвольное выражение. Вследствие этого генераторы списков об
    ладают большей гибкостью – они могут применять функцию, как и map
    , а функция map требует, чтобы применяемое выражение было оформлено в виде функции. Кроме того, генераторы списков поддер
    живают расширенный синтаксис. Например, вложенные циклы for и условные операторы if, что делает их похожими на встроенную функцию filter.

    Закрепление пройденного
    479
    7. И lambdaвыражения, и инструкция def создают объекты функций для последующего вызова. Однако lambdaвыражения – это именно выражения, и поэтому они могут использоваться для вложения определений функций там, где инструкция def синтаксически не
    допустима. Нет таких случаев, когда нельзя было бы обойтись без lambda
    выражений, – всегда можно определить идентичную инст
    рукцию def и ссылаться на функцию по имени. Однако lambdaвыра
    жения удобно использовать для встраивания небольших фрагментов кода, которые в программе больше нигде не используются. Синтак
    сически lambda позволяет возвращать значение единственного выра
    жения; так как эта конструкция не поддерживает блоки инструк
    ций, она плохо подходит для создания больших функций.
    Упражнения к четвертой части
    В этих упражнениях вам будет предложено написать более сложные программы. Обязательно проверьте решения в разделе «Часть IV.
    Функции» в приложении B; оформляйте свои решения в виде файлов модулей. Если будет допущена ошибка, будет очень сложно повторно ввести эти упражнения с клавиатуры в интерактивной оболочке.
    1. Основы. В интерактивной оболочке интерпретатора Python напи
    шите функцию, которая выводит на экран единственный аргумент,
    и попробуйте вызвать ее несколько раз, передавая объекты различ
    ных типов: строки, целые числа, списки, словари. Затем попробуй
    те вызвать ее без аргументов. Что произошло? Что произойдет, если передать функции два аргумента?
    2. Аргументы. Напишите функцию с именем adder в файле модуля.
    Функция должна принимать два аргумента и возвращать их сумму
    (или конкатенацию). Затем добавьте в конец файла модуля вызовы функции adder с объектами различных типов (две строки, два спи
    ска, два числа с плавающей точкой) и запустите этот файл как сцена
    рий из командной строки операционной системы. Должны ли вы яв
    но производить вывод результатов, чтобы они появились на экране?
    3. Переменное число аргументов. Обобщите функцию adder из преды
    дущего упражнения, чтобы она вычисляла сумму произвольного числа аргументов, и измените вызовы функции так, чтобы ей пере
    давалось больше или меньше двух аргументов. Какой тип имеет возвращаемое значение суммы? (Подсказка: срез, такой как S[:0],
    возвращает пустую последовательность того же типа, что и S, а с по
    мощью встроенной функции type можно узнать тип объекта – смот
    рите примеры с функцией min в главе 16, где используется подобный прием.) Что произойдет, если функции передать аргументы разных типов? Что произойдет, если ей передать словари?
    4. Передача аргументов по ключу. Измените функцию adder из уп
    ражнения 2 так, чтобы она принимала и вычисляла сумму/конка
    тенацию трех аргументов: def adder(good, bad,ugly). После этого

    480
    Глава 17. Расширенные возможности функций определите значения по умолчанию для каждого из аргументов и поэкспериментируйте с функцией в интерактивной оболочке. По
    пробуйте передавать ей один, два, три и четыре аргумента. Попро
    буйте передавать аргументы по именам. Будет ли работать такой вызов: adder(ugly=1, good=2)? Почему? Наконец, обобщите новую версию функции adder так, чтобы принимала и вычисляла сумму/
    конкатенацию произвольного числа аргументов, передаваемых по ключу. Решение будет напоминать то, что было получено в упраж
    нении 3, с той лишь разницей, что вам придется выполнить обход словаря, а не кортежа. (Подсказка: метод dict.keys() возвращает список, который можно обойти с помощью цикла for или while.)
    5. Напишите функцию с именем copyDict(dict), которая копирует сло
    варь, получаемый в виде аргумента. Она должна возвращать новый словарь, содержащий все элементы аргумента. Используйте метод keys для выполнения итераций (или в Python 2.2, выполните обход ключей словаря без вызова метода keys). Копирование последова
    тельностей выполняется достаточно просто (выражение X[:] выпол
    няет поверхностное копирование); будет ли этот метод работать со словарями?
    6. Напишите функцию с именем addDict(dict1, dict2), которая вычис
    ляет объединение двух словарей. Она должна возвращать новый словарь, содержащий все элементы обоих аргументов (которые, как предполагается, являются словарями). Если один и тот же ключ присутствует в обоих аргументах, вы можете выбрать значение из любого словаря. Проверьте свою функцию, добавив программный код проверки в файл и запустив его как сценарий. Что произойдет,
    если вместо словарей передать списки? Как можно было бы обоб
    щить функцию, чтобы она обрабатывала и этот случай? (Подсказ
    ка: смотрите встроенную функцию type, использовавшуюся ранее.)
    Имеет ли значение порядок следования аргументов?
    7. Дополнительные примеры на сопоставление аргументов. Сначала определите следующие шесть функций (в интерактивной оболочке или в файле модуля, который затем можно будет импортировать):
    def f1(a, b): print a, b # Обычные аргументы
    def f2(a, *b): print a, b # Переменное число позиционных аргументов
    def f3(a, **b): print a, b # Переменное число аргументов по ключу
    def f4(a, *b, **c): print a, b, c # Смешанный режим
    def f5(a, b=2, c=3): print a, b, c # Аргументы со значениями по умолчанию
    def f6(a, b=2, *c): print a, b, c # Переменное число позиционных
    # аргументов и со значениями
    # по умолчанию
    Теперь протестируйте следующие вызовы в интерактивной оболочке и попробуйте объяснить полученные результаты – в некоторых слу

    Закрепление пройденного
    481
    чаях вам, возможно, придется вернуться к обсуждению алгоритмов сопоставления в главе 16. Как вы думаете, смешивание режимов со
    поставления вообще можно считать удачным выбором? Можете ли вы придумать ситуации, когда это могло бы оказаться полезным?
    >>> f1(1, 2)
    >>> f1(b=2, a=1)
    >>> f2(1, 2, 3)
    >>> f3(1, x=2, y=3)
    >>> f4(1, 2, 3, x=2, y=3)
    >>> f5(1)
    >>> f5(1, 4)
    >>> f6(1)
    >>> f6(1, 3, 4)
    8. Снова простые числа. Вспомните следующий фрагмент из главы 13,
    который определяет – является ли целое положительное число про
    стым:
    x = y / 2 # Для значений y > 1
    while x > 1:
    if y % x == 0: # Остаток print y, 'has factor', x break # Обойти блок else x = x1
    else: # Обычный выход print y, 'is prime'
    Оформите этот фрагмент в виде функции в файле модуля и добавьте несколько вызовов функции в конец этого файла. При этом замени
    те оператор / на // в первой строке, чтобы функция могла также об
    рабатывать числа с плавающей точкой и была неуязвима для ис
    тинной операции деления, которую, как планируется в Python 3.0,
    будет выполнять оператор / (описывается в главе 5). Что вы можете сказать об отрицательных значениях? Сумеете ли вы повысить ско
    рость работы этой функции? Вывод из вашего модуля должен вы
    глядеть примерно так, как показано ниже:
    13 is prime
    13.0 is prime
    15 has factor 5 15.0 has factor 5.0 9. Генераторы списков. Напишите программный код, который будет создавать новый список, содержащий квадратные корни всех чисел из следующего списка: [2, 4, 9, 16, 25]. Начните с реализации на основе цикла for, затем на основе функции map и, наконец, в виде ге
    нератора списков. Для вычислений используйте функцию sqrt из модуля math (т. е. выполните import math и вызов math.sqrt(x)). Ка
    кой из трех вариантов на ваш взгляд является лучшим?

    V
    Модули

    18
    Модули: общая картина
    Начиная с этой главы, мы приступаем к детальному изучению модуля в языке Python – самой крупной организационной программной еди
    ницы, которая вмещает в себя программный код и данные, готовые для многократного использования. Если говорить более точно, модули в языке Python обычно соответствуют файлам программ (или расшире
    ниям, написанным на других языках программирования, таких как C,
    Java или C#). Каждый файл – это отдельный модуль, и модули могут импортировать другие модули для доступа к именам, которые в них определены. Обработка модулей выполняется двумя инструкциями и одной встроенной функцией: import
    Позволяет клиентам (импортерам) получать модуль целиком from
    Позволяет клиентам получать определенные имена из модуля reload
    Обеспечивает возможность повторной загрузки модуля без останов
    ки интерпретатора Python
    В главе 3 были представлены основные принципы, касающиеся моду
    лей, и мы пользовались ими до сих пор. Часть V книги мы начнем с подробного описания базовых концепций, а затем перейдем к иссле
    дованию расширенных возможностей использования модулей. В этой первой главе вашему вниманию предлагается общий взгляд на роль мо
    дулей в структуре всей программы. В последующих главах мы начнем рассматривать программный код, который основан на этой теории.
    Попутно мы подробно рассмотрим сведения о модулях, которые до сих пор были опущены: вы узнаете об операции перезагрузки модулей, об атрибутах __name__ и __all__, об импорте пакетов и т. д. Поскольку мо

    486
    Глава 18. Модули: общая картина дули и классы – это всего лишь пространства имен, здесь мы также формализуем понятие пространства имен.
    Зачем нужны модули?
    В двух словах, модули обеспечивают простой способ организации ком
    понентов в систему автономных пакетов переменных, известных как
    пространства имен
    . Все имена, определяемые на верхнем уровне мо
    дуля, становятся атрибутами объекта импортируемого модуля. Как мы видели в предыдущей части, операция импорта предоставляет дос
    туп к именам в глобальной области видимости модуля. Таким обра
    зом, в процессе импортирования глобальная область видимости моду
    ля образует пространство имен атрибутов объекта модуля. В конечном счете модули позволяют связывать отдельные файлы в крупные про
    граммные системы.
    Если говорить более определенно, с точки зрения теории модули игра
    ют как минимум три роли:
    Повторное использование программного кода
    Как говорилось в главе 3, модули позволяют сохранять программ
    ный код в виде файлов. В отличие от программного кода, который вводится в интерактивной оболочке интерпретатора Python и исчеза
    ет безвозвратно после выхода из оболочки, программный код в фай
    лах модулей хранится постоянно – его можно повторно загружать и запускать столько раз, сколько потребуется. Можно добавить, что модули – это место, где определяются имена, известные как атри+
    буты
    , на которые может ссылаться множество внешних клиентов.
    Разделение системы пространств имен
    Модули в языке Python также являются самой высокоуровневой единицей организации программ. По существу, они – всего лишь пакеты имен. Модули позволяют изолировать имена в замкнутые пакеты, которые позволяют избежать конфликтов имен, – вы нико
    гда не увидите имя в другом файле, если не импортируете его. Фак
    тически, все, что находится в модуле – выполняемый программный код и создаваемые объекты, – всегда неявно включается в модули.
    Вследствие этого модули являются естественными инструментами группировки компонентов системы.
    Реализация служб или данных для совместного пользования
    С функциональной точки зрения модули могут также использовать
    ся для реализации компонентов, используемых системой, вследст
    вие чего требуется только одна копия такого компонента. Например,
    если необходим глобальный объект, который используется более чем одной функцией или модулем, можно написать его в виде моду
    ля, который затем может импортироваться множеством клиентов.

    Архитектура программы на языке Python
    487
    Однако, чтобы понять действительную роль модулей в системе Python,
    нам необходимо отступить на шаг назад и исследовать общую структу
    ру программы на языке Python.
    Архитектура программы на языке Python
    До сих пор в этой книге я избегал сложностей в описаниях программ на языке Python. Обычно программы состоят более чем из одного фай
    ла – любые программы, за исключением самых простых сценариев, со
    стоят из нескольких файлов. Даже если вам удастся поместить всю ло
    гику в один файл, вы почти наверняка будете использовать сторонние модули, которые уже кемто были написаны.
    В этом разделе дается введение в общую архитектуру программ на язы
    ке Python – способ, которым программа делится на коллекцию файлов с исходными текстами (то есть модулей) и увязывается в единое целое.
    Кроме того, мы попутно рассмотрим основные концепции модулей в языке Python, процедуру импортирования и атрибуты объектов.
    Как организована программа
    Как правило, программа на языке Python состоит из множества тек
    стовых файлов, содержащих инструкции. Программа организована как один главный файл, к которому могут подключаться дополнитель
    ные файлы, известные как модули.
    Главный файл определяет, как будет двигаться основной поток выпол
    нения программы, – это тот файл, который необходимо запустить,
    чтобы начать работу приложения. Файлы модулей – это библиотеки инструментальных средств, где содержатся компоненты, используе
    мые главным файлом (и, возможно, гдето еще). Главный файл ис
    пользует инструменты, определенные в файлах модулей, а модули ис
    пользуют инструменты, определенные в других модулях.
    Обычно файлы модулей ничего не делают, если попытаться запустить их отдельно, – в них определяются инструментальные средства, ис
    пользуемые в других файлах. Чтобы получить доступ к определенным в модуле инструментам, именующимся атрибутами модуля (имена переменных, связанные с такими объектами, как функции), в языке
    Python необходимо импортировать этот модуль. То есть мы импорти
    руем модули и получаем доступ к их атрибутам, что дает нам возмож
    ность использовать их функциональные возможности.
    Импортирование и атрибуты
    Давайте сделаем наше обсуждение более конкретным. На рис. 18.1
    схематически изображена структура программы на языке Python, со
    стоящей из трех файлов: a.py, b.py и c.py. Файл a.py является главным файлом программы – это простой текстовый файл, состоящий из инст

    488
    Глава 18. Модули: общая картина рукций, который при запуске выполняется от начала и до конца. Фай
    лы b.py и c.py – это модули, они также являются простыми текстовыми файлами, содержащими инструкции, но обычно они не запускаются как самостоятельные программы. Вместо этого они, как уже говори
    лось выше, обычно импортируются другими файлами, использующи
    ми инструментальные средства, определяемые в этих файлах.
    Например, предположим, что файл b.py на рис. 18.1 определяет функ
    цию с именем spam. Как мы уже знаем из четвертой части книги, чтобы определить функцию, которая затем сможет быть запущена за счет пе
    редачи ей нуля или более аргументов в круглых скобках, файл b.py
    должен содержать инструкцию def:
    def spam(text):
    print text, 'spam'
    Теперь предположим, что модуль a.py использует функцию spam. Для этого он мог бы содержать следующие инструкции:
    import b b.spam('gumby')
    В первой строке здесь располагается инструкция import, дающая фай
    лу a.py доступ ко всему, что определено на верхнем уровне в файле
    b.py
    . Вкратце это означает следующее: «загрузить файл b.py (если он еще не загружен) и предоставить доступ ко всем его атрибутам через имя модуля b». Инструкции import (и, как вы узнаете далее, from) за
    гружают и запускают другие файлы на этапе времени выполнения.
    1   ...   54   55   56   57   58   59   60   61   ...   98


    написать администратору сайта