Лутц М. - Изучаем Python (1077325), страница 85
Текст из файла (страница 85)
Второе: з случае с классами нам, возможно, пришлось бы использовать метод перегрузки операторов [тег илн более старый петттез, которые будут описаны з главе 24, чтобы обеспечить поддержку ожидаемого итерационного протокола. В этом случае мы можем определить, что означает понятие итерации для наших данных. 396 Глава 15. Основы функций Почти все имена в функции )пгегвесг являются локальными переменными: ° Переменная гев явно участвует в операции присваивания, поэтому она — локальная переменная.
° Аргументы передаются через операцию присваивания, поэтому вез1 и вес2 тоже локальные переменные. ° Цикл Гог присваивает элементы переменной, поэтому имя к также является локальным. Все эти локальные переменные появляются только в момент вызова функции и исчезают, когда функция возвращает управление — инструкция гегсгп, стоящая в конце функции 1пГегвесг, возвращает обэекгп результата, а имя гев исчезает. Однако, чтобы полностью исследовать понятие локальности, нам необходимо перейти к главе 16. В заключение В этой главе были представлены основные идеи, на которых основано определение функции, — синтаксис и принцип действия инструкций лег и ге1сго, выражений вызова функций, а также суть и преимущества полиморфизма в функциях языка Ру111оп.
Как было показано, инструкция сеà — это исполняемый программный код, который создает объект функции. Когда позднее производится вызов функции, передача объектов производится за счет выполнения операции присваивания (вспомните, в главе 6 говорилось, что присваивание в языке Ру1поп означает передачу ссылок на объекты, которые фактически реализованы в виде указателей), а вычисленные значения возвращаются обратно с помощью инструкции гесс гп.
В этой главе мы также приступили к изучению таких понятий, как локальные переменные и области видимости, но более подробно эти темы будут рассматриваться в главе 16. Сначала все-таки ответьте на контрольные вопросы. Закрепление пройденного Контрольные вопросы 1.
Какие преимущества несет использование функций? 2. В какой момент времени интерпретатор Рубанов создает функции? 3. Что возвращает функция, если в ней отсутствует инструкция геГсгп? 4. Когда выполняется программный код, вложенный в инструкцию определения функции? б. Почему нежелательно выполнять проверку типов объектов, передаваемых функции? 397 Закрепление пройденного Ответы 1. 2.
3. 5. Функции представляют собой основной способ избежать избыточности программного кода — выделение программного кода в виде функции означает, что в будущем нам потребуется изменить единственную копию действующего кода. Кроме того, функции — это основные блоки программного кода многократного пользования — заключение программного кода в функции превращает его в инструмент многократного пользования, который может вызываться различными программами. Наконец, функции позволяют разбить сложную систему на небольшие и легко управляемые части, каждая из которых может разрабатываться отдельно.
Функция создается, когда интерпретатор достигает инструкции ее( и выполняет ее; эта инструкция создает объект функции и связывает его с именем функции. Обычно это происходит, когда файл модуля, включающего функцию, импортируется другим модулем (вспомните, что во время импорта программный код файла выполняется от начала до конца, включая и инструкции се(), но это может происходить, когда инструкция бес вводится в интерактивной оболочке или во время выполнения вложенного блока другой инструкции, такой как 11. Когда поток управления достигает конца тела функции, не встретив на своем пути инструкцию гешгл, по умолчанию функция возвращает объект ноле. Такие функции обычно вызываются как инструкции выражений, так как присваивание объекта Иоле переменной в целом бессмысленно.
Тело функции (программный код, вложенный в инструкцию определения функции) выполняется, когда позднее производится вызов функции. Тело функции выполняется всякий раз, когда происходит вызов. Проверка типов объектов, передаваемых функции, — это надежный способ ограничить их гибкость, потому что в этом случае функция сможет работать только с объектами определенных типов. Без такой проверки функция наверняка сможет обрабатывать целую категорию типов объектов — любые объекты, поддерживающие интерфейс, ожидаемый функцией, смогут быть обработаны.
(Термин инлгергрейс означает набор методов и операций, которые используются функцией.) Области видимости и аргументы В главе 15 были описаны основы определения и вызова функций. Как мы видели, базовая модель функций в языке РуФоп достаточно проста в использовании. В этой главе будут представлены подробности, лежащие в основе областей видимости — мест, где определяются переменные и где выполняется их поиск, — и механизма передачи аргументов — способа передачи объектов в функции.
Правила видимости Теперь, когда вы готовы приступить к созданию своих собственных функций, нам необходимо более формально определить, что означают имена в языке Ру$поп. Всякий раз, когда в программе используется некоторое имя, интерпретатор создает, изменяет или отыскивает это имя в пространстве имен — в области, где находятся имена. Когда мы говорим о поиске значения имени применительно к программному коду, под термином область видимости подразумевается пространство имен: т.
е. место в программном коде, где имени было присвоено значение, определяет область видимости этого имени для программного кода. Практически все, что имеет отношение к именам, включая классификацию областей видимости, в языке РуСпоп связано с операциями присваивания. Как мы уже видели, имена появляются в тот момент, когда им впервые присваиваются некоторые значения, и прежде чем имена смогут быть использованы, им необходимо присвоить значения, Поскольку имена не объявляются заранее, интерпретатор Руь11оп по местоположению операции присваивания связывает имя с конкретным пространством имен. Другими словами, место, где выполняется при- 399 Правила видимости сваивание, определяет пространство имен, в котором будет находиться имя, а, следовательно, и область его видимости.
Помимо упаковки программного кода функции привносят в программы еще один слой пространства имен — по умолчанию все имена, значения которым присваиваются внутри функции, ассоциируются с пространством имен этой функции и никак иначе. Это означает, что: ° Имена, определяемые внутри инструкции беГ, видны только программному коду внутри инструкции Оет. К этим именам нельзя обратиться за пределами функции. ° Имена, определяемые внутри инструкции ОеГ„не вступают в конфликт с именами, находящимися за пределами инструкции ОеГ, даже если и там и там присутствуют одинаковые имена.
Имя Х, которому присвоено значение за пределами данной инструкции оеГ (например, в другой инструкции Оет или на верхнем уровне модуля) полностью отлично от имени Х, которому присвоено значение внутри инструкции Оет. В любом случае область видимости переменной (где она может использоваться) всегда определяется местом, где ей было присвоено значение, и никакого отношения не имеет к месту, откуда была вызвана функция. Если присваивание переменной выполняется внутри инструкции оеГ, переменная является локальной для этой функции; если присваивание производится за пределами инструкции беГ, она является глобальной для всего файла. Мы называем это лексической областью видимости, потому что области видимости переменных целиком определяются местоположением этих переменных в исходных текстах программы, а не местом, откуда вызываются функции.
Например, в следующем файле модуля инструкция присваивания Х = 99 создает глобальную переменную с именем Х (она видима из любого места в файле), а инструкция Х = 88 создает локальную переменную Х (она видима только внутри инструкции беГ): Х = 99 Оет Гипс(); Х = 88 Даже при том, что обе переменные имеют имя Х, области видимости делают их различными.
Таким образом, области видимости функций позволяют избежать конфликтов имен в программах и превращают функции в самостоятельные элементы программ. Основы видимости имен в языке Рутпоп До того как мы начали писать функции, весь программный код размещался на верхнем уровне модуля (например, он ие был вложен в инструкции аеГ), поэтому все имена, которые мы использовали, либо нахо- Глава 16.
Области видимости и аргументы дились на верхнем уровне в модуле, либо относились к предопределенным именам языка РусЬоп (например, орел).' Функции образуют вложенные пространства имен (области видимости), которые ограничивают доступ к используемым в них именам, благодаря чему имена внутри функций не вступают в конфликт с именами за их пределами (внутри модуля или внутри других функций). Повторю еще раз, функции образуют локальную область видимости, а модули — глобальную. Эти две области взаимосвязаны между собой следующим образом: ° Объемлющий модуль — это глобальная область видимости. Каждый модуль — это глобальная область видимости, т. е. пространство имен, в котором создаются переменные на верхнем уровне в файле модуля.
Глобальные переменные для внешнего мира становятся атрибутами объекта модуля, но внутри модуля могут использоваться как простые переменные. ° Глобальная область видимости охватывает единственный файл. Не надо заблуждаться насчет слова»глобальный» вЂ” имена на верхнем уровне файла являются глобальными только для программного кода в этом файле.
На самом деле в языке Ру»Поп не существует такого понятия, как всеобъемлющая глобальная для всех файлов область видимости. Имена всегда относятся к какому-нибудь модулю и всегда необходимо явно импортировать модуль, чтобы иметь возможность использовать имена, определяемые в нем. Когда вы слышите слово»глобальный», подразумевайте «модуль». ° Каждый вызов функции создает новую локальную область видимости. Всякий раз, когда вызывается функция, создается новая локальная область видимости — т. е.