Подтвердить что ты не робот

Почему reset глобальное значение python не вступает в силу

Просто путайте о глобальном значении в Python, вот два фрагмента кода

#gl.py

import cli

a = 1    
print "gl 1: %d %d" % (id(a), a)


def reset():
    global a
    a = 7
    print "reset 1: %d %d" % (id(a), a)


if __name__ == '__main__':
    cli.handler(reset)
    print "gl 2: %d %d" % (id(a), a)

код cli

#cli.py

def handler(func):
    from gl import a
    print "cli 1: %d %d" % (id(a), a)
    func()
    print "cli 2: %d %d" % (id(a), a)

Результатом выполнения является

$ python gl.py
gl 1: 150847672 1
gl 1: 150847672 1
cli 1: 150847672 1
reset 1: 150847600 7
cli 2: 150847672 1    #Why value doesn't change
gl 2: 150847600 7

Здесь я не понимаю после выполнения функции reset(), результат глобального значения не изменяется в cli.py(cli 2: 150847672 1), но обратно to gl.py, глобальное значение действительно меняется!

4b9b3361

Ответ 1

Здесь отсутствуют две концепции.

  • Глобалы являются глобальными для модулей, а не через модули.

Refer: http://legacy.python.org/doc/essays/ppt/hp-training/sld036.htm

Обратитесь: http://docs.python.org/release/2.4/ref/global.html

  • Переменные импортируются как значения, а не по ссылке

Обратитесь: fooobar.com/questions/149589/...

Если вам нужно поделиться глобальными переменными через модули, обратитесь к Как мне поделиться глобальными переменными между модулями?

Ответ 2

Ваш модуль gl дважды импортируется в два разных пространства имен

попробуйте следующее:

import sys
print sys.modules['__main__'].a
print sys.modules['gl'].a

Ответ 3

Влияние, которое вы импортируете в cli, на самом деле является копией объекта модуля. если мы изменим ваш код следующим образом:

#gl.py

import cli
import sys

a = 1    
print "gl 1: %d %d" % (id(a), a)
print "gl id on import: {0}".format(id(sys.modules[__name__]))


def reset():
    global a
    a = 7
    print "gl id in reset: {0}".format(id(sys.modules[__name__]))
    print "reset 1: %d %d" % (id(a), a)

def printa():
    print "gl: %d %d" % (id(a), a)

if __name__ == '__main__':
    cli.handler(reset)
    print "gl id in main: {0}".format(id(sys.modules[__name__]))
    print "gl 2: %d %d" % (id(a), a)

и

#cli.py

def handler(func):
    #from gl import a
    import gl
    print "gl id in cli: {0}".format(id(gl))
    print "cli 1: %d %d" % (id(gl.a), gl.a)
    func()
    print "cli 2: %d %d" % (id(gl.a), gl.a)
        gl.reset()
        print "cli 3: %d %d" % (id(gl.a), gl.a)

Получаем:

gl 1: 19056568 1
gl id on import: 140075849968728
gl 1: 19056568 1
gl id on import: 20004096
gl id in cli: 20004096
cli 1: 19056568 1
gl id in reset: 140075849968728
reset 1: 19056424 7
cli 2: 19056568 1
gl id in reset: 20004096
reset 1: 19056424 7
cli 3: 19056424 7
gl id in main: 140075849968728
gl 2: 19056424 7

Итак, когда мы запускаем reset, мы меняем ссылку

a -> 19056568

to

a -> 19056424

но только в одной копии gl. Другой (тот, который находится в cli) держится на старой ссылке. Если мы запустим gl.reset() изнутри cli, ссылка на эту копию изменится, и мы получим ожидаемое изменение в cli.