如何解决全局语句似乎不适用于 ipython3 Built-in magic commands %run
我有以下脚本
test.py:
a=1
def f() :
global a
a=2
当我在 ipython3 中运行这个脚本时,我得到以下结果:
In [1]: a
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-3f786850e387> in <module>
----> 1 a
NameError: name 'a' is not defined
In [2]: run test
In [3]: a
Out[3]: 1
In [4]: f()
In [5]: a
Out[5]: 1
既然我将a
声明为全局变量,为什么在运行函数f()
时它的值没有变为2?
解决方法
TLDR:run
模块的命名空间被复制到 IPython 命名空间,而不是共享。到 f()
运行时,命名空间不再同步。
当 IPython 通过 run
执行一个模块时,它会在一个新的命名空间中执行;完成后,这个命名空间的元素被复制到主 IPython 命名空间。
Built-in magic commands %run
[...]
该文件在最初仅由以下内容组成的命名空间中执行
__name__=='__main__'
和 sys.argv 按指示构造。它
因此将其环境视为独立运行
程序(除了共享全局对象,例如以前导入的
模块)。 但执行后,IPython 交互式命名空间得到
更新了程序中定义的所有变量(名称
和 sys.argv)。这允许非常方便地加载代码
交互式工作,同时给每个程序一个“干净的表”来运行。
[...]
在程序执行过程中,会执行a=1
和def f(): ...
。结果,a=1
和 f
都被复制回主命名空间。
值得注意的是,f
在完成之前不会被调用。手动调用 f()
时,其全局命名空间仍然是执行 test
的命名空间;只有 test
命名空间被 f()
修改。
In [2]: run test.py
In [3]: a
Out[3]: 1
In [4]: f()
In [5]: a
Out[5]: 1
使用“-i”参数:
In [6]: run -i test.py
In [7]: a
Out[7]: 1
In [8]: f()
In [9]: a
Out[9]: 2
来自run?
:
-i
run the file in IPython's namespace instead of an empty one. This
is useful if you are experimenting with code written in a text editor
which depends on variables defined interactively.
,
正如@MisterMiyagi 所指出的,解释是在run
命令的末尾复制了变量、函数和其他对象。因此,a
命名空间中的变量 test
与 a
命名空间中的变量 main
不同,尽管它们指向相同的对象。它是问题示例中的不可变变量;因此,在函数内部对其进行的任何更改都会导致 test
命名空间上的变量指向一个新对象。
然而,如果变量是可变的,并且如果这个对象发生了变化,但变量没有在函数内部重新定义,那么它的新值对于两个变量a
将是相同的:
test.py:
a=[1,2,3]
def f() :
global a
a+=[1]
ipython3 部分:
In [1]: run test
In [2]: a
Out[2]: [1,3]
In [3]: f()
In [4]: a
Out[4]: [1,3,1]
如果我在函数定义中用 a+=[1]
替换 a=a+[1]
,这会创建一个新对象 a+[1]
而不是更新 a
指向的对象,结果是>
In [4]: a
Out[4]: [1,3]
因为在运行 f()
之后,a
命名空间中的变量 test
将指向一个新对象,而不改变之前指向的对象。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。