Избежать global можно несколькими способами:
Есть несколько способов изменить поведение глобальной переменной без использования ключевого слова global. Каждый из этих способов имеет свои преимущества и недостатки, и выбор зависит от конкретного контекста задачи.
1. Использование изменяемого объекта:
Если глобальная переменная является изменяемым объектом (например, списком, словарем или экземпляром класса), то мы можем изменять содержимое этого объекта без переназначения самой переменной. Внутри функции мы получаем доступ к тому же объекту в памяти, что и в глобальной области видимости, поэтому изменения, внесенные в объект, будут видны и снаружи функции.
  global_list = []
  def modify_list(new_element):
    global_list.append(new_element)
  modify_list(10)
  print(global_list)  # Вывод: [10]
  В этом примере мы добавляем элемент в список global_list, не используя global. Функция напрямую изменяет объект, на который ссылается глобальная переменная.
2. Использование классов:
Можно создать класс, который будет хранить глобальные данные как атрибуты класса. Методы класса могут изменять эти атрибуты. Доступ к этим атрибутам можно получить через экземпляр класса.
  class GlobalState:
    value = 0
  def increment():
    GlobalState.value += 1
  increment()
  print(GlobalState.value) # Вывод: 1
  В данном случае, value является атрибутом класса GlobalState. Функция increment изменяет этот атрибут класса, что эквивалентно изменению глобального состояния.
3. Использование замыканий (Closures):
Хотя этот способ обычно используется для других целей, его можно адаптировать для косвенного изменения глобального состояния. Создаётся функция, которая возвращает другую функцию, захватывающую переменную из внешней области видимости (не глобальной, а области видимости внешней функции). Однако, если нужно именно *изменить* глобальную переменную, а не просто прочитать её, то этот метод обычно сложнее, чем другие.
  def create_incrementor():
    global global_value
    def increment():
      global global_value
      global_value += 1
      return global_value
    return increment
  global_value = 0
  increment = create_incrementor()
  print(increment()) # Вывод: 1
  print(global_value) # Вывод: 1
  4. Передача переменной как аргумент функции и возврат измененного значения:
В этом случае, функция принимает глобальную переменную как аргумент, производит с ней необходимые манипуляции и возвращает измененное значение, которое затем присваивается глобальной переменной.
  global_variable = 5
  def modify_variable(value):
    return value * 2
  global_variable = modify_variable(global_variable)
  print(global_variable) # Вывод: 10
  Этот метод делает поток данных более явным и улучшает читаемость кода, особенно в более крупных проектах. Этот способ является предпочтительным, когда нужно избежать прямого изменения глобального состояния внутри функции.
Важно помнить:  Хотя эти способы позволяют избежать прямого использования global, злоупотребление ими может сделать код сложным для понимания и отладки. Использование глобальных переменных (даже косвенно) следует минимизировать, а вместо этого стараться использовать локальные переменные и передавать данные между функциями явным образом.