Глобальные словари не нуждаются в ключевом слове global для их изменения?

Возможный дубликат:
Почему в этом случае ключевое слово global не требуется?

Интересно, почему я могу изменить глобальный словарь без global ключевого слова? Почему он является обязательным для других типов? Есть ли какая-то логика?

Например, код:

 #!/usr/bin/env python3 stringvar = "mod" dictvar = {'key1': 1, 'key2': 2} def foo(): dictvar['key1'] += 1 def bar(): stringvar = "bar" print(stringvar) print(dictvar) foo() print(dictvar) print(stringvar) bar() print(stringvar) 

Дает следующие результаты:

 me@pc:~/$ ./globalDict.py {'key2': 2, 'key1': 1} {'key2': 2, 'key1': 2} # Dictionary value has been changed mod bar mod 

где я бы ожидал:

 me@pc:~/$ ./globalDict.py {'key2': 2, 'key1': 1} {'key2': 2, 'key1': 1} # I didn't use global, so dictionary remains the same mod bar mod 

  • Создание цветовой панели из функции RGBA в matplotlib
  • Использование MySQL в фляге
  • Пользовательские классы CSS для ввода виджета SQLFORM в web2py
  • Создание Nграмм (Unigrams, Bigrams и т. Д.) Из большого корпуса .txt-файлов и их частоты
  • Правильный способ автоматического фильтрации запросов SQLAlchemy?
  • Почему вы должны блокировать потоки?
  • Отсутствует GOMP_parallel или GOMP_4.0 в (Docker) jupyter / all-spark-notebook: как R, так и Python
  • Вложенные действия try в python?
  • 2 Solutions collect form web for “Глобальные словари не нуждаются в ключевом слове global для их изменения?”

    Причина в том, что линия

     stringvar = "bar" 

    является неоднозначным, это может быть ссылка на глобальную переменную, или может быть создана новая локальная переменная, называемая stringvar . В этом случае Python по умолчанию предполагает, что он является локальной переменной, если только ключевое слово global уже не используется.

    Однако линия

     dictvar['key1'] += 1 

    Совершенно однозначно. Это может быть ссылка только на глобальную переменную dictvar , так как dictvar уже должен существовать, чтобы оператор не dictvar ошибку.

    Это не относится к словарям – то же самое верно для списков:

     listvar = ["hello", "world"] def listfoo(): listvar[0] = "goodbye" 

    или других видов объектов:

     class MyClass: foo = 1 myclassvar = MyClass() def myclassfoo(): myclassvar.foo = 2 

    Это правда, когда используется мутирующая операция, а не перевязка .

    Вы можете изменить любой изменяемый объект без использования global ключевого слова.

    Это возможно в Python, потому что global используется, когда вы хотите переназначить новые объекты на имена переменных, уже используемые в глобальной области видимости или для определения новых глобальных переменных.

    Но в случае измененных объектов вы не перенаправляете ничего, вы просто модифицируете их на месте, поэтому Python просто загружает их из глобальной области и модифицирует их.

    Как говорят документы :

    Было бы невозможно присвоить глобальную переменную без глобального.

     In [101]: dic = {} In [102]: lis = [] In [103]: def func(): dic['a'] = 'foo' lis.append('foo') # but fails for lis += ['something'] .....: In [104]: func() In [105]: dic, lis Out[105]: ({'a': 'foo'}, ['foo']) 

    dis.dis :

     In [121]: dis.dis(func) 2 0 LOAD_CONST 1 ('foo') 3 LOAD_GLOBAL 0 (dic) # the global object dic is loaded 6 LOAD_CONST 2 ('a') 9 STORE_SUBSCR # modify the same object 3 10 LOAD_GLOBAL 1 (lis) # the global object lis is loaded 13 LOAD_ATTR 2 (append) 16 LOAD_CONST 1 ('foo') 19 CALL_FUNCTION 1 22 POP_TOP 23 LOAD_CONST 0 (None) 26 RETURN_VALUE 
    Python - лучший язык программирования в мире.