使用魔术命令 %% timeit -n1 -r1 导致 jupyter 不保留局部变量的值

woo*_*ody 5 python-3.x jupyter-notebook jupyter-lab

我刚刚注意到一些非常奇怪的事情。当我使用%%timeit -n1 -r1magic命令,在Jupyter lab中测量一段代码的执行时间时,python在执行完该块后,并没有保留局部变量的值!例如,如果我运行包含以下代码的代码块:

for i in range(10):
   for j in range(10):
       d = i - j
Run Code Online (Sandbox Code Playgroud)

然后print(d)在另一个块中运行,jupyter 将显示上次迭代中 d 的值。但是如果我运行这段代码:

%%timeit -n1 -r1
for in in range(10):
   for j in range(10):
       d = i - j
Run Code Online (Sandbox Code Playgroud)

然后运行print(d),juoyter 向我显示了一条错误消息:

NameError: name 'd' is not defined
Run Code Online (Sandbox Code Playgroud)

这种奇怪行为背后的解释是什么?

Bra*_*mon 1

IPython/Jupyter 获取单元中的代码块,并在一个函数中运行它,该函数的作用域对模块__main__的命名空间不可见。从这个答案来看,它似乎将单元格视为一个字符串:

\n\n
In [4]: get_ipython().magic(\'timeit 1 + 2\')                                                                                                                                                                        \n11.2 ns \xc2\xb1 0.167 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000000 loops each)\n\nIn [5]: %%timeit \n   ...: 1 + 2 \n   ...:  \n   ...:                                                                                                                                                                                                            \n11.1 ns \xc2\xb1 0.17 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

循环中的变量对于运行和计时循环的任何 IPython 函数都是已知的,但无法在该Timer实例方法之外访问。

\n\n

当您在单元格(或仅在普通 Python 交互式解释器)中运行for i in range(10)循环(不带)时,Python 处理 for 循环的方式是在循环的每次迭代中动态重新分配、和值。循环运行完毕后,它们仍将位于(这是Python shell 中的 dunder 属性)的命名空间中。%%timeitijd__main____name__

\n