Не понимаю область видимости с словарями

Есть такая функция в коде:

def on_group(_, callback_query):
    msg = callback_query.message
    print(group_names)
    group_id.clear()
    with open(groups_path, "r") as my_file:
        group_names = json.load(my_file)
    for i in group_names:
        group_id.append(group_names[i])

Group_names и group_id объявлены как словарь и список в начале кода. В строке 3 выдаёт ошибку:

Traceback (most recent call last):
  File "C:\Users\kolch\AppData\Local\Programs\Python\Python310\lib\site-packages\pyrogram\dispatcher.py", line 242, in handler_worker
    await self.loop.run_in_executor(
  File "C:\Users\kolch\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "c:\Users\kolch\Desktop\all\Prog\py\Group_filter\filter_main.py", line 132, in on_group
    print(group_names)
UnboundLocalError: local variable 'group_names' referenced before assignment

Проблема с видимостью переменных или что?


Ответы (1 шт):

Автор решения: Dmitry

вот так работать будет, но не является хорошей практикой

group_names = {}

def on_group():
    print(group_names)


on_group()

То же самое, но верное использование

def on_group(param):
    print(param)


group_names = {}
on_group(group_names)

Основной принцип: функция не должна работать с переменными вне зоны ее видимости и глобальными переменными. Все необходимые данные функция получает на вход, все что было изменено возвращается из функции через return

А вот так работать не будет

def on_group():
    print(group_names)


on_group()

UPD START

И вот так работать не будет

def on_group():
    print(group_names)
    group_names = {1:"name"}


group_names = {}
on_group()

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

Если же, вы не будете присваивать (полностью перезаписывать словарь), а просто будете его менять, добавляя или изменяя его, то все будет работать

def on_group():
    print(group_names)
    group_names[1] = "name"


group_names = {}
on_group()

UPD END

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

def on_group(_, callback_query):
    msg = callback_query.message
    group_id.clear()
    with open(groups_path, "r") as my_file:
        group_names = json.load(my_file)
    for i in group_names:
        group_id.append(group_names[i])
    return group_names


group_names = {}
group_names = on_group(_, query)
→ Ссылка