Вопрос-Ответ

Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?

Можно ли изменить переменную в python, которая находится во внешней (охватывающей), но не глобальной области видимости?

Рассмотрим этот пример:

def A():
b = 1
def B():
# I can access 'b' from here.
print(b)
# But can i modify 'b' here?
B()
A()

Для кода в B функции переменная b находится в неглобальной, охватывающей (внешней) области видимости. Как я могу изменить b изнутри B? Я получаю, UnboundLocalError если я попробую это напрямую, и использование global не устраняет проблему, поскольку b не является глобальным.


Python реализует лексическую, а не динамическую область видимости, как почти все современные языки. Описанные здесь методы не разрешат доступ к переменным вызывающего объекта - если только вызывающий объект также не является охватывающей функцией - потому что вызывающий объект не находится в области видимости. Подробнее об этой проблеме см. Как я могу получить доступ к переменным из вызывающего объекта, даже если это не охватывающая область (т. Е. Реализовать динамическое определение области видимости)?.

Переведено автоматически
Ответ 1

В Python 3 используйте nonlocal ключевое слово:


Оператор nonlocal заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области видимости, исключая глобальные. Это важно, потому что поведение по умолчанию для привязки заключается в том, чтобы сначала выполнить поиск в локальном пространстве имен. Инструкция позволяет инкапсулированному коду повторно связывать переменные за пределами локальной области видимости, помимо глобальной (модульной) области видимости.


def foo():
a = 1
def bar():
nonlocal a
a = 2
bar()
print(a) # Output: 2

В Python 2 используйте изменяемый объект (например, список или dict) и изменяйте значение вместо переназначения переменной:

def foo():
a = []
def bar():
a.append(1)
bar()
bar()
print a

foo()

Выводит:

[1, 1]
Ответ 2

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

def outer_fn():
class FnScope:
b = 5
c = 6
def inner_fn():
FnScope.b += 1
FnScope.c += FnScope.b
inner_fn()
inner_fn()
inner_fn()

Это дает следующий интерактивный вывод:

>>> outer_fn()
8 27
>>> fs = FnScope()
NameError: name 'FnScope' is not defined
Ответ 3

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

def A():
b = [1]
def B():
b[0] = 2
B()
print(b[0])

# The output is '2'

Редактировать: Я предполагаю, что это, вероятно, было верно до Python 3. Похоже, nonlocal это ваш ответ.

Ответ 4

Нет, вы не можете, по крайней мере, таким образом.

Потому что "операция set" создаст новое имя в текущей области видимости, которое охватывает внешнюю.

2023-09-09 07:30 python