In ipython
I am using %run
to execute the following code from a file:
foo = 32
def test7():
global foo
print("foo before:", foo)
foo = 1
print("foo after:", foo)
My ipython
transcript goes as follows:
$ ipython
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) ...
In [1]: %run "a1.py"
In [2]: foo
Out[2]: 32
In [3]: test7()
foo before: 32
foo after: 33
In [4]: foo
Out[4]: 32
In [5]: test7()
foo before: 33
foo after: 34
In [6]: foo
Out[6]: 32
In [7]:
My question is: why does querying the value of foo
within ipython
always return 32 when the test7()
routine seems to be incrementing it?
And is there a way I can see the same value of foo
that the test7()
function is seeing?
CodePudding user response:
The reason why foo
is always 32 is because foo
variable is stored in an specific memory space and if you don't pass -i
as @Mark mentions it will return the value stored in that specific memory space:
In [1]: %run "a1.py"
In [2]: foo
Out[2]: 32
In [3]: id(foo)
Out[3]: 1543004777744
In [4]: id(32)
Out[4]: 1543004777744
In [5]: test7()
foo before: 32
foo after: 33
In [6]: id(foo)
Out[6]: 1543004777744
In [7]: id(33)
Out[7]: 1543004777776
You can notice 32
constant and foo
variable have the same ID
value
CodePudding user response:
You can pass %run
the -i
flag to "run the file in IPython’s namespace instead of an empty one."
In [1]: %run -i "a1.py"
In [2]: foo
Out[2]: 32
In [3]: test7()
foo before: 32
foo after: 33
In [4]: foo
Out[4]: 33
In [5]: test7()
foo before: 33
foo after: 34
In [6]: foo
Out[6]: 34
I find the docs a little confusing, but I think they are trying to explain the behavior with:
The file is executed in a namespace initially consisting only of
__name__=='__main__'
and sys.argv constructed as indicated. It thus sees its environment as if it were being run as a stand-alone program (except for sharing global objects such as previously imported modules). But after execution, the IPython interactive namespace gets updated with all variables defined in the program (except for__name__
andsys.argv
).
Also worth noting is this from the python docs:
Programmer’s note: global is a directive to the parser. It applies only to code parsed at the same time as the global statement. In particular, a global statement contained in a string or code object supplied to the built-in exec() function does not affect the code block containing the function call, and code contained in such a string is unaffected by global statements in the code containing the function call.