Грунтовної відповіді щодо часу Python3 не було, тому я тут зробив відповідь. Більшість того, що описано тут, детально описано у розділі 4.2.2 Роздільна здатність імен документації Python 3.
Як передбачено в інших відповідях, існують 4 основні сфери, LEGB - для локальних, закритих, глобальних та вбудованих. Окрім них, існує особливий спектр, орган класу , який не містить вкладеної області для методів, визначених у класі; будь-які призначення в тілі класу роблять змінну звідти на зв'язаною в тілі класу.
Тим більше, жодного блокового твердження, окрім defіclass створює змінну область. У Python 2 розуміння списку не створює змінної області, однак у Python 3 змінна циклу в межах розуміння списку створюється в новій області.
Продемонструвати особливості корпусу класу
x = 0
class X(object):
y = x
x = x + 1 # x is now a variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, the global x
print(y) # -> NameError: global name 'y' is not defined
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
Таким чином, на відміну від функції функції, ви можете перепризначити змінну на те саме ім'я в тілі класу, щоб отримати змінну класу з тим самим іменем; подальший пошук цього імені вирішує замість змінної класу.
Одне з найбільших сюрпризів для багатьох новачків Python - це те, що forцикл не створює змінної області. У Python 2 розуміння списку також не створюють сфери застосування (в той час як генератори та диктують розуміння!) Натомість вони просочують значення у функції або глобальній області застосування:
>>> [ i for i in range(5) ]
>>> i
4
Зрозуміння можуть бути використані як хитрий (або жахливий, якщо ви хочете) спосіб внесення змінних змінних в лямбда-виразах у Python 2 - вираз лямбда створює змінну область, як і у defзаяві, але в межах лямбда жодні заяви не дозволені. Призначення, що є висловлюванням в Python, означає, що не допускаються призначення змінних у лямбда, але розуміння списку - це вираз ...
Така поведінка була зафіксована в Python 3 - ніякі вираження розуміння чи генератори не протікають змінними.
Глобальний справді означає область модуля; основним модулем пітона є __main__; всі імпортовані модулі доступні через sys.modulesзмінну; отримати доступ до __main__одного можна використовувати sys.modules['__main__'], або import __main__; цілком прийнятно отримати доступ та призначити там атрибути; вони відображатимуться як змінні у глобальній області основного модуля.
Якщо ім’я коли-небудь присвоюється в поточному діапазоні (крім сфери класу), воно вважатиметься приналежним до цього діапазону, інакше вважатиметься приналежним до будь-якого вкладеного області, що присвоює змінній (можливо, вона не буде призначена все ж, або зовсім не), або, нарешті, глобальний розмах. Якщо змінна вважається локальною, але вона ще не встановлена або була видалена, то читання значення змінної призведе до UnboundLocalError, що є підкласом NameError.
x = 5
def foobar():
print(x) # causes UnboundLocalError!
x += 1 # because assignment here makes x a local variable within the function
# call the function
foobar()
Область може заявити, що вона явно хоче змінити глобальну змінну (область модуля) за допомогою глобального ключового слова:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Це також можливо, навіть якщо воно було затінене в області застосування:
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sees the global value
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
У python 2 не існує простого способу змінити значення в області, що додається; зазвичай це моделюється за допомогою змінного значення, такого як список довжиною 1:
def make_closure():
value = [0]
def get_next_value():
value[0] += 1
return value[0]
return get_next_value
get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2
Однак у python 3 nonlocalна допомогу приходить:
def make_closure():
value = 0
def get_next_value():
nonlocal value
value += 1
return value
return get_next_value
get_next = make_closure() # identical behavior to the previous example.
nonlocalДокументація каже , що
Імена, перелічені в нелокальному твердженні, на відміну від перелічених у глобальній заяві, повинні посилатися на раніше існуючі прив'язки в обкладинці (область, у якій має бути створена нова прив'язка, не може бути визначена однозначно).
тобто nonlocalзавжди посилається на найпотужнішу зовнішню неглобальну область, де ім'я було пов'язане (тобто присвоєне, в тому числі використовується як forцільова змінна, у withпункті або як функціональний параметр).
Будь-яка змінна, яка не вважається локальною для поточного обсягу, або будь-яка охоплює область, є глобальною змінною. У глобальному словнику модуля знайдено глобальне ім'я; якщо його не знайдено, глобальний слід шукати з вбудованого модуля; назву модуля було змінено з python 2 на python 3; у python 2 це було, __builtin__а в python 3 зараз його називають builtins. Якщо ви призначите атрибут вбудованого модуля, його буде видно після цього будь-який модуль як читабельну глобальну змінну, якщо тільки цей модуль не затінює їх власною глобальною змінною з тим же ім'ям.
Читання вбудованого модуля також може бути корисним; припустимо, що ви хочете функцію друку в стилі python 3 в деяких частинах файлу, але інші частини файлу все ще використовують printоператор. У Python 2.6-2.7 ви можете отримати функцію Python 3 за printдопомогою:
import __builtin__
print3 = __builtin__.__dict__['print']
from __future__ import print_functionФактично не імпортує printфункції ніде в Python 2 - замість цього він просто відключає правил синтаксичного аналізу для printзатвердження в поточному модулі, обробки , printяк і будь-який інший ідентифікатор змінної, і , таким чином , дозволяючи printфункції розглядати в вбудованих команд.