Не совсем. Хотя это правда, что глобальные объекты копируются неглубоко, на самом деле вы видите область видимости глобальных объектов (с использованием ключевого слова global
) и то, как это фактически работает на уровне модуля в Python. Вы можете наблюдать это, вставив pdb.set_trace()
внутри функции f
сразу после присвоение (X = 2
).
$ python -m doctest foo.py
> /tmp/foo.py(18)f()
-> return X
(Pdb) bt
/usr/lib/python2.7/runpy.py(162)_run_module_as_main()
-> "__main__", fname, loader, pkg_name)
/usr/lib/python2.7/runpy.py(72)_run_code()
-> exec code in run_globals
/usr/lib/python2.7/doctest.py(2817)<module>()
-> sys.exit(_test())
/usr/lib/python2.7/doctest.py(2808)_test()
-> failures, _ = testmod(m)
/usr/lib/python2.7/doctest.py(1911)testmod()
-> runner.run(test)
/usr/lib/python2.7/doctest.py(1454)run()
-> return self.__run(test, compileflags, out)
/usr/lib/python2.7/doctest.py(1315)__run()
-> compileflags, 1) in test.globs
<doctest foo.f[1]>(1)<module>()
-> f()
> /tmp/foo.py(18)f()
-> return X
(Pdb) pp X
2
Да, значение действительно 2
в пределах f
, но давайте взглянем на его глобальные переменные. Давайте посмотрим, как они сравниваются в текущем кадре и кадре выше.
(Pdb) id(globals())
140653053803048 # remember this number, and we go up a frame
(Pdb) u
> <doctest foo.f[1]>(1)<module>()
-> f()
(Pdb) id(globals())
140653053878632 # the "shallow" clone
(Pdb) X
1
(Pdb) c
Ага, вы можете видеть, что на самом деле это НЕ одно и то же, и что X
действительно 1
и не был изменен, потому что глобальные объекты находятся внутри модуля <doctest doc.f>
, созданного doctest по этой причине. Давай продолжим.
(Pdb) id(globals())
140653053803048 # hey look, is the SAME number we remember
(Pdb) u
> <doctest foo.g[0]>(1)<module>()
-> g()
(Pdb) id(globals())
140653053872960 # note how this is a different shallow clone
Итак, что вы на самом деле видели, так это то, что глобальные переменные в doctest не совпадают с глобальными переменными в вашем источнике (следовательно, g
вернет 2
, потому что X
действительно был изменен в модуле здесь f
, но не в мелкой копии модуля doctest scope), хотя изначально он был скопирован из модуля, но изменения не отражаются обратно в базовый модуль, поскольку именно так работает ключевое слово global
- на уровне модуля, а не между модулями.
person
metatoaster
schedule
31.08.2016