Изменить область действия функции в 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' недопустимо, поскольку переданный параметр также объявлен в том же контексте (хотя синтаксис не обязательно делает это очевидным).