Изменить область действия функции в Python
Задавать вопрос
спросил
Изменено 2 года, 9 месяцев назад
Просмотрено 356 раз
Моя цель — изменить область действия функции на словарь, а не на место, где она определена, чтобы функция видела переменные в словаре.
Я обнаружил, что могу сделать следующее:
my_dict = {'x': 1, 'y': 2}
защита add_all():
х + у + г
# ссылка на функции в словаре
my_dict.update({'add_all': add_all})
# добавляем my_dict в __global__ функции
my_dict['add_all'].__globals__.update(my_dict)
г = 3
my_dict['add_all']() # видит x, y и z
№ 6
Это работает, теперь я пытаюсь сделать другую функцию, которая изменяет переменные в объемлющей области.
по определению update_x_y(x, y):
# Здесь нужно явно ссылаться на my_dict
my_dict.update({'x': x, 'y': y})
# Необходимо снова обновить __globals__ функции add_all()
add_all.__globals__.update(my_dict)
добавить все()
my_dict.update({'update_x_y': update_x_y})
my_dict['update_x_y'].__globals__.update(my_dict)
my_dict['update_x_y'](10, 20)
№ 33
Это тоже работает, но очень некрасиво и опасно.
Вопросы:
Похоже,
__globals__— это словарь, в котором функция будет оценивать; То, что я делаю с__globals__.update(), просто присваиваю ему новые значения, поэтому каждый раз, когда что-то меняется вmy_dict, мне приходится снова обновлять.- Есть ли способ заменить
__globals__наmy_dict, хотя итолько для чтения?
- Есть ли способ заменить
В функции
, который определен в глобальной области видимости.update_x_y()мне пришлось явно ссылаться наmy_dict
- Есть ли в функциях способ ссылаться на переменные во внешней области видимости?
-
нелокальныйнельзя использовать, так как охватывающая область должна быть замыканием
- питон
- сфера
- крышки
2
Мы можем использовать класс внедрения переменных для очистки кода
Вдохновлено
- Как внедрить переменную в область видимости с помощью декоратора
- Использование классов в качестве декораторов
Код
класс Inject_Variables:
""" Внедряет именованные переменные в область действия функции """
def __init__(я, **kwargs):
если кварги:
self.kwargs = кварги
защита __call__(я, f):
"""
__call__() вызывается только
один раз, как часть создания обернутой функции! Вы можете только дать
это единственный аргумент, который является объектом функции.
"""
@обертывания(ф)
def wrapper_f(*args, **kwargs):
f_globals = f.__globals__
save_values = f_globals.copy() # поверхностная копия
# Добавляем контекст создания объекта
если self.kwargs:
f_globals.update(self.kwargs)
# Добавить контекст вызова функции
если кварги:
f_globals.update(kwargs)
пытаться:
результат = f()
окончательно:
f_glabals = save_values # Отменить изменения
вернуть результат
вернуть завернутый_f
Варианты использования
def add_all(): вернуть х + у + г
Тест 1
my_dict = {'x': 1, 'y': 2}
г = 3
# Создать дополнение, которое будет использовать my_dict и z в глобальной области видимости
scoped_add = Inject_Variables(**my_dict)(add_all)
print('Используя глобальный z: ', scoped_add()) # используем значения my_dict
# Вывод: Использование глобального z: 6
Тест 2
print('Используя параметр вызова z: ', scoped_add(z=0))
# Вывод: Использование параметра вызова z: 3
Тест 3
# Обновить словарь
my_dict = {'x': 2, 'y': 3, 'z': 0}
scoped_add = Inject_Variables(**my_dict)(add_all) # новое добавление с заданной областью
print('Используя словарь z: ', scoped_add())
# Вывод: Использование обновленного словаря: 5
Тест 4
# Использование параметров имени
# Определяем новую область, используя именованные параметры
г = 300
scoped_add = Inject_Variables (x = 100, y = 200) (add_all)
print('Используя именованные параметры: ', scoped_add())
# Вывод: Использование именованных параметров: 600
Тест 5
z = 3
@Inject_Variables (х = 1, у = 2)
защита test_all():
вернуть х + у + г
print('Использование в декораторе: ', test_all())
# Вывод: Использование в декораторе: 6
2
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
С++.
Что означает «локальные переменные в самой внешней области действия функции не могут использовать то же имя, что и любой параметр»?спросил
Изменено 7 лет, 10 месяцев назад
Просмотрено 2к раз
Я читал учебник по C++, 5-е издание. В третьем абзаце списка функциональных параметров главы 6.1. Пишет « Более того, локальные переменные в самой внешней области действия функции не могут использовать то же имя, что и любой параметр «. Что это значит?
Я не являюсь носителем английского языка. Я не понимаю фактического значения «внешней области действия» функции.
- c++
- параметры
- область видимости
- локальные переменные
Внешней областью действия функции является блок, определяющий тело функции.
Вы можете поместить в него другие (внутренние) блоки и объявить переменные в тех, которые являются локальными для этого блока. Переменные во внутренних блоках могут иметь то же имя, что и во внешнем блоке, или параметры функции; они скрывают имена во внешней области. Переменные во внешнем блоке не могут иметь то же имя, что и параметр функции.
Для демонстрации:
void f(int a) // функция имеет параметр
{ // начало области видимости функции
интервал б; // OK: локальная переменная
{ // начало внутреннего блока
в а; // OK: скрывает параметр
интервал б; // OK: скрывает внешнюю переменную
} // конец внутреннего блока
в а; // Ошибка: не может иметь то же имя, что и параметр
}
3Это означает, что вы не можете делать такие вещи:
void foo (int x)
{
интервал х = 4; // в самой внешней области действия недопустимо
}
Однако вы можете сделать это:
void foo (int x)
{
{ // это вводит новую область видимости
интервал х = 4; // не в самой внешней области, допустимо
}
}
2
Это означает, что это неверно:
void f(int p)
{
инт р = 3;
}
тогда как это
void f(int p)
{
{
инт р = 3;
}
}
разрешено.
Это правило действует не только для параметров функций в определениях функций, но также для итераций и условных операторов, а также для обработчиков исключений
3.3.3 Область блока
2 Потенциальная область действия имени параметра функции (включая один появляющийся в лямбда-деклараторе) или предопределенной локальной функции переменная в определении функции (8.4) начинается в точке ее декларация. Если у функции есть функция-попробуй-заблокируй потенциал область действия параметра или локальной предопределенной переменной функции заканчивается в конце последнего связанного обработчика, в противном случае он заканчивается в конец самого внешнего блока определения функции. Параметр имя не должно быть переобъявлено в самом внешнем блоке функции определение, ни в самом внешнем блоке любого обработчика, связанного с функциональный пробный блок.
3 Имя, объявленное в объявлении исключения, является локальным по отношению к обработчик и не должен быть повторно объявлен в самом внешнем блоке обработчик.
4 Имена, объявленные в for-init-statement, for-range-declaration, и в условиях операторов if, while, for и switch локально для оператора if, while, for или switch (включая контролируемый оператор) и не должен быть повторно объявлен в последующем условие этого оператора, ни в самом внешнем блоке (или, для if оператор, любой из самых внешних блоков) управляемого оператора; см. 6.4.
Например, этот фрагмент кода недействителен
if( int x = SomeFunction() )
{
интервал х; // неверное объявление
//...
}
Представьте, что у вас есть функция ‘foo’, которая принимает целочисленный параметр ‘bar’.
int foo (внутренняя полоса)
{
инт бар = 0; // < недопустимо, это самая внешняя область видимости
если (бар == 10) {
инт бар = 5; // допустимо (хотя и нежелательно) это «затеняет» переданную «полосу»
обратная планка;
}
обратная планка;
}
Первое внутреннее объявление 'bar' недопустимо, поскольку переданный параметр также объявлен в том же контексте (хотя синтаксис не обязательно делает это очевидным).



