Код не видит переменные Python

Пишу Телеграм бота на AIOGram и не понимаю почему получаю ошибку:

UnboundLocalError: local variable 'number_of_skins_with_rare_stickers' referenced before assignment

Вот код:

...
count_of_skins_passed = 0
time_of_passage_of_skins = 0
number_of_skins_with_rare_stickers = 0
number_of_skins_with_rare_floats = 0
number_of_skins_with_rare_patterns = 0
...
def posting(table_name):
    ...
    if rare_pattern != 0:
        number_of_skins_with_rare_patterns += 1
    else:
        pass
    ...

async def main(message: Message, as_html = True):
    ...
    with open(f'report.txt', 'w') as report_file:
        report_file.write(f'Результат парсинга от {datetime.datetime.now()}:')
        report_file.write(f'Количество пройденных скинов: {count_of_skins_passed}')
        report_file.write(f'Общее время: {time_of_passage_of_skins}')
        ...

Большую часть скрипта не добавлял, но думаю и так понятно основная структура. Переменные оглашены вне функций, в одной из функций они изменяются, а в другой - записываются в файл. Проверил через print(globals()) - все переменные там есть. Вопрос в том, почему скрипт их не видит.


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

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

Вам и правда стоит разобраться с тем, как работают области видмости. Когда вы пишите:

(Python 3.9)

l = []
def a(l: list[int]):
  l.append(1)
a(l) 
print(l) # [1]

В функцию a попадает ссылка на list. Мы обращаемся к методу по этой ссылке.

Когда пишем: (Python 3.9)

l = []
def a(l: list[int]):
  l = [1]
a(l)
print(l) # []

мы создаем НОВЫЙ list l в локальной области видимости функции a. Глобальная переменная l НЕ МЕНЯЕТСЯ !!!

Решение

Что бы это исправить вы можете создать некоторую струтуру

class Counter:
  def __init__(self):
     self.number_of_skins_with_rare_patterns = 0
  def register_rare_patern(smth):
    # do smth
    self.number_of_skins_with_rare_patterns += 1

Дальше:

counter = Counter()

И в функции post():

def posting(table_name, counter):
    ...
    if rare_pattern != 0:
        counter.register_rare_patern()
    else:
        pass
    ...

Другое, не очень правильное решение проблемы

В принципе вы можете явно указать что такая - то переменная - глобальная:

def post():
    global var

Однако такая реализация может таить в себе много подводных камней.

→ Ссылка