Мы можем создать функцию, которая выводит числа Фибоначчи до некоторого предела:
>>> def fib(n): # вывести числа Фибоначчи меньшие (вплоть до) n ... """Выводит ряд Фибоначчи, ограниченный n.""" ... a, b = 0, 1 ... while b < n: ... print(b, end=' ') ... a, b = b, a+b ... print() ... >>> # Теперь вызовем определенную нами функцию: ... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 Зарезервированное слово def предваряет определение функции. За ним должны следовать имя функции и заключённый в скобки список формальных параметров. Выражения, формирующие тело функции, начинаются со следующей строки и должны иметь отступ.
Первым выражением в теле функции может быть строковой литерал - этот литерал является строкой документации функции, или док-строкой (docstring). (Больше информации о док-строках вы найдёте в разделе Строки документации) Существуют инструменты, которые используют док-строки для того, чтобы сгенерировать печатную или онлайн-документацию или чтобы позволить пользователю перемещаться по коду интерактивно; добавление строк документации в ваш код - это хорошая практика, постарайтесь к ней привыкнуть.
Исполнение функции приводит к созданию новой таблицы символов, использующейся для хранения локальных переменных функции. Если быть более точными, все присваивания переменных в функции сохраняют значение в локальной таблице символов; при обнаружении ссылки на переменную, в первую очередь просматривается локальная таблица символов, затем локальная таблица символов для окружающих функций, затем глобальная таблица символов и, наконец, таблица встроенных имён. Таким образом, глобальным переменным невозможно прямо присвоить значения внутри функций (если они конечно не упомянуты в операторе global) несмотря на то, что ссылки на них могут использоваться.
Фактические параметры при вызове функции помещаются в локальную таблицу символов вызванной функции; в результате аргументы передаются через вызов по значению (call by value) (где значение - это всегда ссылка (reference) на объект, а не значение его самого). Если одна функция вызывает другую - то для этого вызова создается новая локальная таблица символов.
При определении функции её имя также помещается в текущую таблицу символов. Тип значения, связанного с именем функции, распознается интерпретатором как функция, определённая пользователем (user-defined function). Само значение может быть присвоено другому имени, которое затем может также использоваться в качестве функции. Эта система работает в виде основного механизма переименования:
>>> fib
>>> f = fib >>> f(100) 1 1 2 3 5 8 13 21 34 55 89 Если вы использовали в работе другие языки программирования, вы можете возразить, что fib - это не функция, а процедура, поскольку не возвращает никакого значения. На самом деле, даже функции без ключевого слова return возвращают значение, хотя и более скучное. Такое значение именуется None (это встроенное имя). Вывод значения None обычно подавляется в интерактивном режиме интерпретатора, если оно оказывается единственным значением, которое нужно вывести. Вы можете проследить за этим процессом, если действительно хотите, используя функцию print():
>>> fib(0) >>> print(fib(0)) None Довольно легко написать функцию, которая возвращает список чисел из ряда Фибоначчи, вместо того, чтобы выводить их:
>>> def fib2(n): # вернуть числа Фибоначчи меньшие (вплоть до) n ... """Возвращает список чисел ряда Фибоначчи, ограниченный n.""" ... result = [] ... a, b = 0, 1 ... while b < n: ... result.append(b) # см. ниже ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # вызываем >>> f100 # выводим результат [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] И на этот раз пример демонстрирует некоторые новые возможности Python: Оператор return завершает выполнение функции, возвращая некоторое значение. Оператор return без аргумента возвращает None. Достижение конца функции также возвращает None.
Выражение result.append(b) вызывает метод append объекта-списка result. Метод - это функция, которая "принадлежит" объекту и указывается через выражение вида obj.methodname, где obj - некоторый объект (может быть выражением), а methodname - имя метода, присущий объекту данного типа. Различные типы определяют различные методы. Методы разных типов могут иметь одинаковые имена, не вызывая неопределённостей. (Позже в этом учебнике будет рассмотрено как определять собственные типы объектов и методы, используя классы.) Метод append(), показанный в примере, определён для объектов типа список. Он добавляет в конец списка новый элемент. В данном примере это действие эквивалентно выражению result = result + [b], но более эффективно.
Назад Вперед
8 8 8
| |