Области видимости и
вложенные функции
С появлением вложенных функций в области видимости поиск стал сложнее.
• При обращении к переменной (X) поиск имени X сначала производится в локальной области видимости (функции)затем в локальных областях видимости всех
лексически-объемлющих функций, изнутри наружу, затем в текущей глобальной области видимости (в модуле) и, наконец, во встроенной области видимости (модуль builtins). Поиск имен, объявленных в инструкции global, начинается сразу с глобальной (в модуле) области видимости.
• Операция присваивания (X = value) по умолчанию создает или изменяет имя
X в текущей локальной области видимости. Если имя X объявлено глобальным внутри функции, операция присваивания создает или изменяет имя X в области видимости объемлющего модуля. Если имя X объявлено нелокальным внутри функции, операция присваивания создает или изменяет имя X в ближайшей области видимости объемлющей функции.
Обратите внимание, что инструкция global отображает имена в область видимости объемлющего модуля. Когда имеются вложенные функции, можно получить значения переменных в объемлющих функциях, но чтобы их изменить, переменные должны быть указаны в объявлении nonlocal.
Примеры вложенных областей видимости:
X = 99 # Имя в глобальной области видимости: не используется
def f1():
X = 88 # Локальное имя в объемлющей функции
def f2():
print(X)# Обращение к переменной во вложенной функции
f2()
f1() # Выведет 88: локальная переменная в объемлющей функции
Объемлющая функция - функция которая содержит в себе вложенную функцию.
-----------------------------------------------------------------
def f1():
def f2():
print(X) # Сохраняет значение X в объемлющей области видимости
return f2 # Возвращает f2, но не вызывает ее
action = f1() # Создает и возвращает функцию
action() # Вызов этой функции: выведет 88
Функция которая создает и возвращает другую функцию. При вызове action фактически запускается функция, созданная во время выполнения функции f1. Функция f2 помнит переменную X в области видимости объемлющей функции f1, которая уже неактивна.
-----------------------------------------------------------------
Фабричные функции(замыкание):
Подразумевается объект функции, который сохраняет значения в объемлющих областях
видимости, даже когда эти области могут прекратить свое существование. Классы более подходящий объект, который сохраняет состояние, путем присваивания атрибуту значения.
Используются фабричные функции, когда необходимо создать обработчик событий в процессе выполнения.
>>> def maker(N):
... def action(X): # Создать и вернуть функцию
... return X ** N # Функция action запоминает значение N в объемлющей
... return action # области видимости
...
Здесь определяется внешняя функция, которая просто создает и возвращает
вложенную функцию, не вызывая ее. Если вызвать внешнюю функцию:
>>> f = maker(2) # Запишет 2 в N
>>> f
<function action at 0x014720B0>
она вернет ссылку на созданную ею вложенную функцию, созданную при выполнении вложенной инструкции def. Если теперь вызвать то, что было получено от внешней функции:
>>> f(3) # Запишет 3 в X, в N по-прежнему хранится число 2
9
>>> f(4) # 4 ** 2
16
Если снова вызвать внешнюю функцию, мы получим новую вложенную
функцию уже с другой информацией о состоянии.
>>> g = maker(3) # Функция g хранит число 3, а f – число 2
>>> g(3) # 3 ** 3
27
>>> f(3) # 3 ** 2
9
В результате вместо квадрата будет вычисляться куб аргумента, но ранее сохраненная функция по-прежнему будет возвращать квадрат аргумента.
Вообще классы, которые будут обсуждаться позднее, лучше подходят на роль «памяти», как в данном случае, потому что они обеспечивают явное сохранение информации.
взято из книги Марка Лутца!
ОтветитьУдалитьХоть бы источник указали