Область определение функции это: § Область определения функции

Изменить область действия функции в 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++
  • параметры
  • область видимости
  • локальные переменные

0

Внешней областью действия функции является блок, определяющий тело функции. Вы можете поместить в него другие (внутренние) блоки и объявить переменные в тех, которые являются локальными для этого блока. Переменные во внутренних блоках могут иметь то же имя, что и во внешнем блоке, или параметры функции; они скрывают имена во внешней области. Переменные во внешнем блоке не могут иметь то же имя, что и параметр функции.

Для демонстрации:

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *