Поиск…


Синтаксис

  • глобальные a, b, c
  • нелокальный a, b
  • x = что-то # связывает x
  • (x, y) = что-то # связывает x и y
  • x + = что-то # связывает x. Аналогично для всех остальных "op ="
  • del x # binds x
  • для x в чем-то: # binds x
  • с чем-то как x: # binds x
  • кроме Exception как ex: # связывает ex внутренний блок

Глобальные переменные

В 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 ключевое слово означает, что назначения будут выполняться на верхнем уровне модуля, а не на верхнем уровне программы. Другие модули по-прежнему нуждаются в обычном пунктирном доступе к переменным в модуле.

Подводя итог: чтобы узнать, является ли переменная 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.x 3.0

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

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 будет функция локального по умолчанию. См. Раздел «Синтаксис» для списка операторов привязки.

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

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

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 .


От PEP 227 :

Имена в классе не доступны. Имена разрешаются в самой внутренней области приложения. Если определение класса происходит в цепочке вложенных областей, процесс разрешения пропускает определения классов.

Из документации Python по именованию и привязке :

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

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

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

Команда 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 = {'a': 1, 'b': 2}
del x['a']
print(x) #  out: {'b': 2}
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]

См. Также Сбор мусора # Команда del .

Локальная и глобальная область

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

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

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

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)

Аналогичным образом, oposite:

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 (см. Nonlocal Variables ), доступные в Python 3, берут локальную переменную из охватывающей области в локальную область текущей функции.

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

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

Python 3.x 3.0
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!


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow