Что то ты с кодом ты напутал. Список может быть изменен из функции. Внутри функции python работает следующим образом.
1. Первым делом python смотрит есть ли ключевое слово global
2. Вторым есть ли ключевое слово nonlocal
3. Третьим в параметрах, если там имя есть то переменная становится локальной.
4. Если переменная упоминалась (но не было определена) то python смотрит на нелокальную область видимости.
5. Если переменная упоминалась (но не было определена) и не найдено в нелокальной области видимости то смотрит в модуле
6. Если и там не нашел то в встроенных пример max,min и т.д.
a = 1
b = 2
c = 3
def func():
print(a,b,c)
if __name__ == "__main__":
func()
Работает, как ожидается, а теперь маленькое изменение
a = 1
b = 2
c = 3
def func():
print(a,b,c)
c = 100
print(c)
if __name__ == "__main__":
func()
И все ошибка даже print(a,b,c) не выполнится. Потому что с находится в локальной области видимости функции python ее находит и также он находит ее упоминание (print(a,b,c)) до ее определения.
def func():
global c
print(a,b,c)
c = 100
print(c)
if __name__ == "__main__":
func()
Вся это проблема актуальна только для НЕ мутабельных типов например
a = [0]
b = [0]
c = [0]
def func():
print(a,b,c)
c.append(100)
print(c)
if __name__ == "__main__":
func()
Все работает как и ожидается. Ну и пару слов об использовании global. Я персонально не сторонник утверждения никогда не используй global Но безусловно данная конструкция актуальна для не локальной области видимости то есть вот так.
def func():
total = 0
def inner():
nonlocal total
total +=1
return total
return inner
if __name__ == "__main__":
add = func()
print(add())
print(add())
print(add())
Если убрать ключевое слово nonlocal то мы получим ошибку.