Лутц М. - Изучаем Python (1077325), страница 83
Текст из файла (страница 83)
Глава 15. Основы функций гетв ге передает объект результата вызывающей программе. Когда функция вызывается, вызывающая программа приостанавливает свою работу, пока функция не завершит работу и не вернет управление. Функции, вычисляющие какое-либо значение, возвращают его с помощью инструкции гешга — возвращаемое значение становится результатом обращения к функции. Функции, известные как генераторы, для передачи возвращаемого значения могут также использовать инструкцию уае1О и сохранять свое состояние так, чтобы работа функции могла быть возобновлена позднее, — это еще одна из сложных тем, которые будут рассматриваться позже.
Аргументы передаются посредством присваивания (в виде ссылок на объекты). В языке Ру()юп аргументы передаются функциям посредством выполнения операции присваивания (что, как мы уже знаем, означает — в виде ссылок на объекты). Как будет показано далее, модель, принятая в языке Ру()гоп, в действительности не эквивалентна правилам передачи аргументов по ссылке в языке С или С++ — и вызывающая программа, и функция совместно используют ссылку на объект, но здесь нет никакого совмещения имен. Изменение имени аргумента также не изменяет имени в вызывающей программе, но модификация изменяемых объектов внутри функции может приводить к изменению объектов в вызывающей программе. ц1оба1 объявляет переменные, глобальные для модуля, без присваивания им значений.
По умолчанию все имена, присваивание которым производится внутри функций, являются локальными для этих функций и существуют только во время выполнения функций. Чтобы присвоить значение имени в объемлющем модуле, функция должна объявить его с помощью инструкции о1ооа1. Говоря в более широком смысле, поиск имен всегда производится в об.
ласти видимости — там, где хранятся переменные, — а операция присваивания связывает имена с областями видимости. Аргументы, возвращаемые значения и переменные не объявляются. Как и повсюду в языке Ру(Ьоп, на функции также не накладывается никаких ограничений по типу. Фактически никакие элементы функций не требуют предварительного объявления: вы можете передавать функции аргументы любых типов, возвращать из функции объект любого типа и т. д. Как следствие этого одна и та же функция может применяться к объектам различных типов — допустимыми считаются любые объекты, поддерживающие совместимые интерфейсы (методы и выражения), независимо от конкретного типа.
Если что-то из сказанного выше вам показалось непонятным, не волнуйтесь — в этой части книги мы исследуем все эти концепции на примерах программного кода. А теперь начнем изучение некоторых из этих идей и рассмотрим несколько примеров. 389 Создание функций Инструкция деФ Инструкция Сег создает объект функции и связывает его с именем. В общем виде инструкция имеет следующий формат: Ое( <паве>(агд1, агд2.... агдз): <а(а(еаепга> Как и все составные инструкции в языке Ру(Ьоп, инструкция сег состоит из строки заголовка и следующего за ней блока инструкций, обычно с отступами (или простая инструкция вслед за двоеточием).
Блок инструкций образует тело функции, т. е. программный код, который выполняется интерпретатором всякий раз, когда производится вызов функции. В строке заголовка инструкции оег определяются имя функции, с которым будет связан объект функции, и список из нуля или более аргументов (иногда их называют параметрами) в круглых скобках.
Имена аргументов в строке заголовка будут связаны с объектами, передаваемыми в функцию, в точке вызова. Тело функции часто содержит инструкцию ге(цгп: Ое( <паза>(агд1, агд2,... агди): ге(пгп <на1пе> Инструкция гегогп может располагаться в любом месте в теле функции — она завершает работу функции и передает результат вызывающей программе. Инструкция гегпгп содержит объектное выражение, которое дает результат функции. Инструкция гегцгп является необязательной — если она отсутствует, работа функции завершается, когда поток управления достигает конца тела функции.
С технической точки зрения, функция без инструкции гегзгп автоматически возвращает объект йопе, однако это значение обычно просто игнорируется. Функции могут также содержать инструкции у(е!С, которые используются для воспроизведения серии значений с течением времени, однако их рассмотрение мы отложим до главы 17, где обсуждаются расширенные темы, касающиеся функций. Инструкции деФ исполняются во время выполнения Инструкция Вег в языке Ру(Ьоп — это настоящая исполняемая инструкция: когда она исполняется, она создает новый объект функции и присваивает этот объект имени. (Не забывайте, все, что имеется в языке Руь)>оп, относится ко времени выполнения, здесь нет понятия времени компиляции.) Будучи инструкцией, Оег может появляться везде, где могут появляться инструкции, — даже внутри других инструкций. Например, даже при том, что инструкции сег обычно исполняются, когда выполняется импорт вмещающего их модуля, допускается вкладывать 390 Глава)5.
Основы функций определения функций внутрь инструкций (Г, что позволяет произво- дить выбор между альтернативами: тт тевт: Ьет Гипс(). № Определяет функцию таким способом е)зе Ьет гипс() № ипи такии способом гипс() № Вызов выбранное версии Чтобы понять этот фрагмент программного кода, обратите внимание, что инструкция Ье( напоминает инструкцию присваивания =: она просто выполняет присваивание во время выполнения.
В отличие от компилирующих языков, таких как С, функции в языке Рус)топ не должны быть полностью определены к моменту запуска программы. Другими словами, инструкции Ьет не интерпретируются, пока они не будут достигнуты и выполнены потоком выполнения, а программный код внутри инструкции Ье( не выполняется, пока функция не будет вызвана позднее. Так как определение функции происходит во время выполнения, имя функции не является однозначно определенным.
Важен только объ- ект, на который ссылается имя: № Связывание обьектв функции с ииенеи № Вызов функции отпегпаюе = типо отпегпаме() В этом фрагменте функция была связана с другим именем и вызвана уже с использованием нового имени. Как и все остальное в языке Ру- й)топ, функции — это обычные объекты; они явно записываются в па- мять во время выполнения программы.
Первый пример: определения и вызовы Определение Ниже приводится определение в интерактивной оболочке, которое определяет функцию с именем С(зев. Эта функция возвращает резуль- тат обработки двух аргументов: Кроме таких концепций времени выполнения (которые кажутся наиболее уникальными для программистов, имеющих опыт работы с традиционными компилирующими языками программирования) в использовании функций нет ничего сложного. Давайте напишем первый пример, в котором продемонстрируем основы.
Как видите, функции имеют две стороны: определение (инструкция Ьег, которая создает функцию) и вызов (выражение, которое предписывает интерпретатору выполнить тело функции). 391 Первый пример: определения и вызовы »> бег с(вез(х, у): № создать еумкцию и связать ее с имеиеи гесцгп х * у № Тело, выполмлемое при вызове буикции Когда интерпретатор достигает эту инструкцию Ое( и выполняет ее, он создает новый объект функции, в который упаковывает программный код функции и связывает объект с именем (свез.
Как правило, такие инструкции размещаются в файлах модулей и выполняются во время импортирования модулей, однако такую небольшую функцию можно определить и в интерактивной оболочке. Вызов После выполнения инструкции бе( вы сможете вызывать функцию в своей программе„добавляя круглые скобки после ее имени. В круг- лых скобках можно указать один или более аргументов, значения ко- торых будут присвоены именам, указанным в заголовке функции: № Аргументы в круглык скобках »> Савве(2, 4) б Данное выражение передает функции Сзпеб два аргумента.
Как уже упоминалось ранее, передача аргументов осуществляется за счет выполнения операции присваивания, таким образом, имени х в заголовке функции присваивается значение 2, а имени у — значение 4,после чего запускается тело функции. В данном случае тело функции составляет единственная инструкция тес ц гп, которая отправляет обратно результат выражения. Возвращаемый объект был выведен интерактивной оболочкой автоматически (как и в большинстве языков, 2 * 4 в языке РуСЬоп равно 8), однако, если бы результат потребовался бы нам позднее, мы могли бы присвоить его переменной.