0
Обложка: Почему ваша функция не работает? Укажите область видимости в Python

Почему ваша функция не работает? Укажите область видимости в Python

Представим ситуацию. Вы написали функцию, инициализировали переменные где-то и собираетесь сделать тест вашего кода.

У вас все получилось, код запускается без ошибок, хотя, вот незадача, функция делает не то, что надо, а точнее — возвращает не желаемое вами значение. Ко всему этому, вы еще и не знаете, как это происходит. Переменные на месте, структура функции в порядке, в чем причина?

Возможно, вы неграмотно воспользовались областью видимости. Давайте рассмотрим пример:

#набор четных чисел
list_sqrt = [2,4,6,8,10]
#функция для преобразования числа в квадрат
def Sum():
  #однострочник, который возвращает число в квадрате
  list_sqrt = [i*i for i in list_sqrt]
  print(list_sqrt)
if __name__ == '__main__':
  Sum()
list_sqrt = [i*i for i in list_sqrt]
UnboundLocalError: local variable 'list_sqrt' referenced before assignment

Кратко о коде: есть список с числами, с помощью функции нужно, чтобы числа в этом же списке, были возведены в квадрат. Попробуем понять, что ощущает функция во время компилирования: «Хозяин, в строке 6 где происходит списковое включение, в цикле, временная переменная не понимает, по кому она проходит».

Можем сделать вывод, что временная переменная — i, совершает итерации, а точнее не совершает их вообще, по неопределенной последовательности. А с другого места в коде мы видим, что у нас есть нужная последовательность (строка 2). Тогда почему же функцая не делает то, что надо, а точнее вообще не делает? Все дело в области видимости.

В коде была определена глобальная последовательность и функция, которая использует локальную последовательность, т.е. та, которая должна использоваться и распостраняться в границах функции.

Кратко. В коде происходит попытка использования локальной последовательности в функции — как локальной. В чем и ошибка.

Как сделать ее локальной? Ведь без этого ей невозможно воспользоваться в функции? Одним словом — global.

Взглянем на следующий код:

#набор четных чисел
list_sqrt = [2,4,6,8,10]
#функция для преобразования числа в квадрат
def Sum():
  #определение последовательности как глобальной для функции
  global list_sqrt
  #однострочник, который возвращает число в квадрате
  list_sqrt = [i*i for i in list_sqrt]
  print(list_sqrt)

if __name__ == '__main__':
  Sum()

В строке 6 появился один новый элемент, а последовательность все та же. Теперь-то в коде список представляется как глобальный и входит за границы функции, и вывод таков:

[4, 16, 36, 64, 100]

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

Все просто. Список и вправду был и есть глобальный. Но все мы знаем, что функция — это отдельный блок кода, как база для избранных. А поскольку глобальность списка распостраняется на ровно такие же части (пустые) кода и не вторгаются в функции и классы, или же попросту отделенные блоки, это и не работает.

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

Итоги

Не забывайте о области видимости, зачастую именно из-за нее функции возвращают не то, что хотелось бы.

Здесь я не углублялся в данную тему и попросту рассказал всё своими словами. Вдобавок я оставляю ссылку на небольшую документацию по этой теме.

На этом — все. Если у вас есть своя тема, которую вы не понимаете, но хотите разобрать, пишите в комментариях, обсудим. Всем удачи и Джедай!