Как использовать замыкания вместо глобальной переменной?

Правильно ли я изменил код с глобальной переменной на замыкание? Прошу без nonlocal.

## Функция с глобальной переменной
def func_g():
    global name
    name = 'Владимир'
    return name

print(func_g())
print(name)

## Функция с замыканием
def func1():
    name2 = 'Владимир'
    def func2():
        return name2
    return func2

var = func1('Владимир')
print(var())

print(var.__closure__)

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

Автор решения: Pak Uula

Замыкания можно использовать для "скрытых" переменных, которые доступны через геттер и сеттер, но не напрямую. Код практически как у вас, с одним важным исключением. Значение нужно хранить не прямо в переменной, а внутри переменной-контейнера. Например, внутри списка из одного значения. Дело в том, что присвоить новый объект в переменную из замыкания нельзя. Зато можно вызывать методы объекта из замыкания, в частности изменяющие содержимое объекта.

В примере используется нотация type annotations из python3.12. Для более ранних версий можно просто удалить все аннотации, на функциональность это не влияет.

from typing import Callable as Func

def mk_hidden_var[T](init_val : T = None) -> tuple[Func[[],T],Func[[T], None]]:
    """
    Создает скрытую переменную с функциями получения и установки значения.

    Аргументы:
        init_val (T, опционально): Начальное значение переменной. По умолчанию None.
    Возвращает:
        tuple[Func[[], T], Func[[T], None]]: Кортеж, содержащий функции получения и установки значения.
          - getter() -> T: Функция для получения текущего значения переменной.
          - setter(val: T) -> None: Функция для установки нового значения переменной.
    """
    container : list[T] = [init_val]
    def getter()->T:
        return container[0]
    def setter(val : T) -> None:
        container[0] = val
    return getter, setter

name_get, name_set = mk_hidden_var('Vladimir')

print(name_get())
name_set('Boris')
print(name_get())
→ Ссылка