3 ноября 2012 г.

nonlocal


Инструкция nonlocal

Данная инструкция, дает возможность изменять значение переменных внутри функций, которые как бы должны быть локальными, то есть использоваться только внутри функции.
Инструкция работает только когда мы вызываем ее внутри функции.

Пример правильного рабочего варианта:

def func():
    nonlocal name1, name2, ..

Данная инструкция существует только в версии Python 3.0.
-----------------------------------------------------------------

Инструкции  global  и nonlocal  несколько  ограничивают 
правила поиска:
  • global вынуждает интерпретатор начинать поиск имен с области объемлющего  модуля  и  позволяет  присваивать  переменным  новые  значения.  Область поиска простирается вплоть до встроенной области видимости, если искомое имя не будет найдено в модуле, при этом операция присваивания значений глобальным  именам всегда  будет  создавать  или изменять переменные в области видимости модуля.

  • nonlocal ограничивает область поиска областями видимости объемлющих 
функций она требует, чтобы перечисленные в инструкции имена уже существовали, и позволяет присваивать им новые значения. В область поиска не входят глобальная и встроенная области видимости.


Инструкция nonlocal в действии:

>>> def tester(start):
...     state = start # Обращение к нелокальным переменным 
...     def nested(label):         # действует как обычно
...         print(label, state)    # Извлекает значение state из области
...     return nested              # видимости объемлющей функции
...
>>> F = tester(0)
>>> F(‘spam’)
spam 0
>>> F(‘ham’)
ham 0

Функции tester, которая создает и возвращает вложенную функцию nested. Обращение к переменной state из вложенной функции отображается на локальную область видимости функции tester, с применением привычных правил поиска.
-----------------------------------------------------------------


nonlocal для изменения переменных:

>>> def tester(start):
...     state = start  # В каждом вызове сохраняется свое значение state
...     def nested(label):
...         nonlocal state      # Объект state находится 
...         print(label, state) # в объемлющей области видимости
...         state += 1 # Изменит значение переменной, объявленной как nonlocal
...     return nested
...
>>> F = tester(0)
>>> F(‘spam’)          # Будет увеличивать значение state при каждом вызове
spam 0
>>> F(‘ham’)
ham 1
>>> F(‘eggs’)
eggs 2

Переменную state, локальную для функции tester, объявляем в функции nested с помощью инструкции nonlocal, мы сможем изменять ее внутри функции nested.
-----------------------------------------------------------------

Граничные случаи:

Нельзя 
создавать  имена  в  объемлющей  области  видимости  с  помощью  инструкции.


>>> def tester(start):
...     def nested(label):
...         nonlocal state     # Нелокальные переменные должны существовать!
...         state = 0
...         print(label, state)
...     return nested
...
SyntaxError: no binding for nonlocal ‘state’ found

>>> def tester(start):
...     def nested(label):
...         global state       # Глобальные переменные могут отсутствовать
...         state = 0          # Создаст переменную в области видимости модуля
...         print(label, state)
...     return nested
...

>>> F = tester(0)
>>> F(‘abc’)
abc 0
>>> state
0
-----------------------------------------------------------------

Поиск нелокальных переменных не производится за пределами инструкций def ни в глобальной области видимости объемлющего модуля, ни во встроенной области видимости, даже если переменные с такими именами там существуют:
>>> spam = 99
>>> def tester():
...     def nested():
...         nonlocal spam  # Переменная должна быть внутри def, а не в модуле!
...         print(‘Current=’, spam)
...         spam += 1
...     return nested
...
SyntaxError: no binding for nonlocal ‘spam’ found
-----------------------------------------------------------------

Сохранение информации с помощью классов:
пока только пример кода  с комментариями, так как классы мы не изучали!
>>> class tester:      # Альтернативное решение на основе классов (Часть VI)
...     def __init__(self, start): # Конструктор объекта,
...         self.state = start     # сохранение информации в новом объекте
...     def nested(self, label):
...         print(label, self.state)   # Явное обращение к информации
...         self.state += 1            # Изменения всегда допустимы
...
>>> F = tester(0)      # Создаст экземпляр класса, вызовет __init__
>>> F.nested(‘spam’)   # Ссылка на F будет передана в аргументе self
spam 0
>>> F.nested(‘ham’)
ham 1
>>> G = tester(42)     # Каждый экземпляр получает свою копию информации
>>> G.nested(‘toast’)  # Изменения в одном объекте не сказываются на других
toast 42
>>> G.nested(‘bacon’)
bacon 43
>>> F.nested(‘eggs’)   # В объекте F сохранилась прежняя информация
eggs 2
>>> F.state            # Информация может быть получена за пределами класса
3

Комментариев нет:

Отправить комментарий