Область видимости python задачи

Область видимости и привязка переменной

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

x = 'Hi' def read_x(): print(x) # x is just referenced, therefore assumed global read_x() # prints Hi def read_y(): print(y) # here y is just referenced, therefore assumed global read_y() # NameError: global name 'y' is not defined def read_y(): y = 'Hey' # y appears in an assignment, therefore it's local print(y) # will find the local y read_y() # prints Hey def read_x_local_fail(): if False: x = 'Hey' # x appears in an assignment, therefore it's local print(x) # will look for the _local_ z, which is not assigned, and will not be found read_x_local_fail() # UnboundLocalError: local variable 'x' referenced before assignment 

Обычно, назначение внутри области действия будет скрывать любые внешние переменные с тем же именем:

x = 'Hi' def change_local_x(): x = 'Bye' print(x) change_local_x() # prints Bye print(x) # prints Hi 

Объявляя имя global означает , что, для остальной части сферы, любые присваивания имени будет происходить на верхнем уровне модуля:

x = 'Hi' def change_global_x(): global x x = 'Bye' print(x) change_global_x() # prints Bye print(x) # prints Bye 

global ключевое слово означает , что задания будут происходить на верхнем уровне модуля, а не на верхнем уровне программы. Другие модули все еще будут нуждаться в обычном точечном доступе к переменным внутри модуля.

Читайте также:  Android java access database

Подводя итог: для того , чтобы узнать , является ли переменным x является локальной для функции, вы должны прочитать всю функцию:

  1. если вы нашли global x , то x является глобальной переменной
  2. Если вы нашли nonlocal x , то x принадлежит к функции включения, и не является ни местным , ни глобальным
  3. Если вы нашли x = 5 или for x in range(3) или какой -либо другая привязка, то x является локальным переменным
  4. В противном случае x принадлежат некоторой области видимости (области видимости функции, глобальному охвату, или встроенным командам)

Локальные переменные

Если имя связывается внутри функции, то по умолчанию доступны только внутри функции:

def foo(): a = 5 print(a) # ok print(a) # NameError: name 'a' is not defined 

Конструкции потока управления не оказывают никакого влияния на объем (за исключением except ), но доступ к переменной , которая еще не была назначена ошибка:

def foo(): if True: a = 5 print(a) # ok b = 3 def bar(): if False: b = 5 print(b) # UnboundLocalError: local variable 'b' referenced before assignment 

Обычные связывающие операции задание, for петель и дополненные задания , таких как a += 5

Нелокальные переменные

Python 3 добавил новое ключевое слово под названием ** нелокальный **. Ключевое слово nonlocal добавляет переопределение области во внутреннюю область. Вы можете прочитать все об этом в [PEP 3104] [1]. Это лучше всего иллюстрируется парой примеров кода. Одним из наиболее распространенных примеров является создание функции, которая может увеличивать:

def counter(): num = 0 def incrementer(): num + = 1 return num return incrementer 

Если вы попытаетесь запустить этот код, вы получите ** UnboundLocalError * * потому что на переменную ** num ** ссылаются до того, как она назначена в самой внутренней функции. Давайте добавим нелокальный в смесь:

def counter(): num = 0 def incrementer(): nonlocal num num + = 1 return num return incrementer c = counter() c() # = 1 c() # = 2 c() # = 3

По сути, `nonlocal` позволит вам назначать переменные во внешней области, но не в глобальной области. Таким образом, вы не можете использовать `nonlocal` в нашей функции` counter`, потому что тогда он попытается назначить глобальную область видимости. Попробуйте, и вы быстро получите `SyntaxError`. Вместо этого вы должны использовать `nonlocal` во вложенной функции. (Обратите внимание, что представленная здесь функциональность лучше реализована с использованием генераторов.)

Обязательное вхождение

x = 5 x += 7 for x in iterable: pass 

Каждый из приведенных выше утверждений является обязательным явлением — x стал привязано к объекту , обозначенному 5 .Если это утверждение появляется внутри функции, то x будет функция локального по умолчанию. В разделе «Синтаксис» приведен список обязательных операторов.

Функции пропускают область видимости класса при поиске имен

Классы имеют локальную область видимости во время определения, но функции внутри класса не используют эту область при поиске имен. Поскольку лямбда-выражения являются функциями, а их понимание реализуется с использованием области действия функции, это может привести к неожиданному поведению.

a = 'global' class Fred: a = 'class' # class scope b = (a for i in range(10)) # function scope c = [a for i in range(10)] # function scope d = a # class scope e = lambda: a # function scope f = lambda a=a: a # default argument uses class scope @staticmethod # or @classmethod, or regular instance method def g(): # function scope return a print(Fred.a) # class print(next(Fred.b)) # global print(Fred.c[0]) # class in Python 2, global in Python 3 print(Fred.d) # class print(Fred.e()) # global print(Fred.f()) # class print(Fred.g()) # global 

Пользователи , не знакомые с тем, как эта сфера работы можно ожидать , b , c и e для печати class .

Из документации Пайтона на именования и связывания :

Область имен, определенных в блоке класса, ограничена блоком класса; он не распространяется на блоки кода методов — это включает в себя понимания и выражения генератора, поскольку они реализованы с использованием области действия функции. Это означает, что следующее не удастся:

class A: a = 42 b = list(a + i for i in range(10)) 

В этом примере используются ссылки из этого ответа по Martijn Питерс, который содержит более глубокий анализ этого поведения.

Команда del

Эта команда имеет несколько связанных, но различных форм.

del v

Если v является переменной, команда del v удаляет переменную из ее сферы. Например:

x = 5 print(x) # out: 5 del x print(x) # NameError: name 'f' is not defined 

Обратите внимание , что del является обязательным вхождение, что означает , что , если явно не указано иное ( с использованием nonlocal или global ), del v сделает v локальными по отношению к текущей области. Если вы собираетесь удалить v во внешней области видимости, использовать nonlocal v или global v в том же объеме , в del v убытках.

Во всех следующих случаях намерение команды является поведением по умолчанию, но не поддерживается языком. Класс может быть написан таким способом, который лишает законной силы это намерение.

del v.name

Эта команда запускает вызов v.__delattr__(name) .

Намерение состоит в том, чтобы сделать атрибут name отсутствует. Например:

class A: pass a = A() a.x = 7 print(a.x) # out: 7 del a.x print(a.x) # error: AttributeError: 'A' object has no attribute 'x' 

del v[item]

Эта команда запускает вызов v.__delitem__(item) .

Намерение состоит в том, что item не будет принадлежать в отображении реализуемого объекта v .Например:

x = del x['a'] print(x) # out: print(x['a']) # error: KeyError: 'a' 

del v[a:b]

Это на самом деле вызывает v.__delslice__(a, b) .

Намерение аналогично описанному выше, но с кусочками — диапазонами элементов вместо одного элемента. Например:

x = [0, 1, 2, 3, 4] del x[1:3] print(x) # out: [0, 3, 4] 

Смотрите также Garbage Collection # Команда дель .

Местный и глобальный охват

Каковы локальные и глобальные возможности?

Все variabes Python , которые доступны в какой — то момент в коде либо в локальной области видимости или в глобальном масштабе.

Объяснение состоит в том, что локальная область действия включает в себя все переменные, определенные в текущей функции, а глобальная область действия включает переменную d, определенную вне текущей функции.

foo = 1 # global def func(): bar = 2 # local print(foo) # prints variable foo from global scope print(bar) # prints variable bar from local scope 

Можно проверить, какие переменные находятся в какой области. Встроенные функции locals() и globals() возвращают целые области как словари.

foo = 1 def func(): bar = 2 print(globals().keys()) # prints all variable names in global scope print(locals().keys()) # prints all variable names in local scope 

Что происходит с конфликтами имен?

foo = 1 def func(): foo = 2 # creates a new variable foo in local scope, global foo is not affected print(foo) # prints 2 # global variable foo still exists, unchanged: print(globals()['foo']) # prints 1 print(locals()['foo']) # prints 2 

Для того, чтобы изменить глобальную переменную, используйте ключевое слово global :

foo = 1 def func(): global foo foo = 2 # this modifies the global foo, rather than creating a local variable 

Область действия определяется для всего тела функции!

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

foo = 1 def func(): # This function has a local variable foo, because it is defined down below. # So, foo is local from this point. Global foo is hidden. print(foo) # raises UnboundLocalError, because local foo is not yet initialized foo = 7 print(foo) 
foo = 1 def func(): # In this function, foo is a global variable from the begining foo = 7 # global foo is modified print(foo) # 7 print(globals()['foo']) # 7 global foo # this could be anywhere within the function print(foo) # 7 

Функции внутри функций

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

foo = 1 def f1(): bar = 1 def f2(): baz = 2 # here, foo is a global variable, baz is a local variable # bar is not in either scope print(locals().keys()) # ['baz'] print('bar' in locals()) # False print('bar' in globals()) # False def f3(): baz = 3 print(bar) # bar from f1 is referenced so it enters local scope of f3 (closure) print(locals().keys()) # ['bar', 'baz'] print('bar' in locals()) # True print('bar' in globals()) # False def f4(): bar = 4 # a new local bar which hides bar from local scope of f1 baz = 4 print(bar) print(locals().keys()) # ['bar', 'baz'] print('bar' in locals()) # True print('bar' in globals()) # False 

Global против nonlocal (Python 3 только)

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

global ключевое слово заявляет , что имя должно рассматриваться как глобальная переменная.

foo = 0 # global foo def f1(): foo = 1 # a new foo local in f1 def f2(): foo = 2 # a new foo local in f2 def f3(): foo = 3 # a new foo local in f3 print(foo) # 3 foo = 30 # modifies local foo in f3 only def f4(): global foo print(foo) # 0 foo = 100 # modifies global foo 

С другой стороны, nonlocal , доступный в Python 3, принимает локальную переменную из охватывающей области в локальную область текущей функции.

Из документации Python на nonlocal :

Нелокальный оператор заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области, исключая глобальные переменные.

def f1(): def f2(): foo = 2 # a new foo local in f2 def f3(): nonlocal foo # foo from f2, which is the nearest enclosing scope print(foo) # 2 foo = 20 # modifies foo from f2!

Источник

Оцените статью