Функции и генераторы
Повторение
Вспомним о последовательностях.
Функция range возвращает неизменяемую последовательность чисел в виде объекта range.
Из любой последовательности можно изготовит итерируемый объект.
Любой объект можно пройти поэлементно с помощью for
Из c можно изготовить итератор. Имя a связать с каждым из этих элементов. В случае возникновения исключения, просто заканчиваем цикл.
Вычислим последовательность enumerate.
Возвращаются пары: номер элемента, элемент. Рассмотрим итерируемую последовательность.
Она не индексируемая, так как последовательность, из которой мы делаем reversed может быть не индексируемой.
globals() и locals() совпадают, если мы работаем в командной строке.
Поговорим про функции
Зададим функцию. Очевидно, что функция возвратит 8. Если не писать return, то функция возвращает None.
Напишем так:
Ошибки нет! Пока мы не вызовем функцию и не начнем вычисления, нам все равно где c.
Замечание: целое к строке прибавить не можем.
Упростим функцию.
Объекты не проверяются. Это означает, что вместо чисел можно использовать любые объекты. Например, строки. Посмотрим на содержимое пространства имен. a,b,c находятся во временно созданном пространстве имен.
То пространство имен, которое достается по умолчанию, в случае вычисления функции fun оказывается другим.
А если так…
И еще так…
Если перед строкой fun(1,2) сделать print(dir(fun)), то увидим пространство имен самого объекта fun. Оно соответствует тому пространству имен, что вызывает dir(). Разберемся с тем, что происходит когда имена в глобальном и локальном пространстве имен совпадают.
В первой и второй строке глобальное пространство имен, третья строка – локальное. Если c объявить global, то она не заведется в локальном. Если имя в операторе связывания слева, то оно локальное, так как мы его создаем. Но бывают случаи, когда непонятно, какое имя локальное, а какое глобальное.
Синтаксическое сканирование производится и Python знает, что имя локальное, так как от него происходит связывание. Значит, функция просто не работающая. Это ограничивает нас от ситуации, если мы что-то перебиваем, т.е. нам не встретится ситуация стороннего эффекта.
Рассмотрим еще один пример, на котором убедимся, что функция – это полноценный объект. Мы можем передавать её другой функции, что бы она её вывела.
Еще один пример
Рассмотрим пример, в котором возникает неприятная история: "a" для fun локальная, а для fuun нет. Она лежит в промежутке. Мы не можем перебить a.
Конструкции функций, которые являются выражениями.
У lambda функции ограничена правая часть. Здесь можно написать только выражения. Но они полезны, когда не нужно значение.
Поговорим о запаковке и распаковке последовательности
Существует понятие множественное связывание. Рассмотрим пример: есть переменные, которые нужно поменять местами. Слева пишем нужное количество имен.
Так можно делать, если мы знаем количество имен при распаковке. Если мы напишем функцию
>>>def fun(a,b,c): return a+b+c print(fun(1,2+2,3+..))
Что происходит с объектами 1,2,3? Формируется кортеж, он передается в контейнер функций, там распаковывается, раскладывается по a,b,c и выполняется.
Вспомним о повторно входимых функциях
Повторно вводимая функция заводит пространство имен. Вместо return используется yield.
Функция возвращает генератор. Generator object это и есть итератор.