在由IPython内核支持的Jupyter笔记本中重置下划线(_)

时间:2019-06-24 10:09:32

标签: python jupyter-notebook ipython

编辑:该问题已在GitHub中报告。我将问题留在这里,以防其他人发现问题(我无法)。


在Jupyter笔记本中工作时,为了方便起见,我经常使用_变量(它返回最新代码执行的输出)。但是,当_用作未使用的变量的占位符(Python中的典型用例)时,它将破坏第一个用例。

请注意,这在IPython控制台中可以正常工作。在下面,_在循环中被用作未使用的占位符后,再次保留了最新的返回值。

In [1]: 'value'
Out[1]: 'value'

In [2]: _
Out[2]: 'value'

In [3]: for _ in range(2):
   ...:     print('hello')
   ...:     
hello
hello

In [4]: _
Out[4]: 1

In [5]: 'value'
Out[5]: 'value'

In [6]: _
Out[6]: 'value'

但是,在Jupyter笔记本中运行相同的代码后,_将永远保持1(循环中的最后一个值),无论最新输出是什么。如果我尝试del _,那么_将不再是可访问的变量。

简而言之,Python中_变量的两种用法在Jupyter笔记本中发生冲突,但在IPython控制台中不是。这只是一个不便,但我很想知道如何解决它-或为什么会这样。


修改

$ python --version
Python 3.6.3 :: Anaconda, Inc.
$ ipython --version
6.5.0
$ jupyter notebook --version
5.6.0

2 个答案:

答案 0 :(得分:1)

适应IPython源代码 ../lib/site-packages/IPython/core/displayhook.py 197 update_user_ns

            update_unders = True
            for unders in ['_'*i for i in range(1,4)]:
                if not unders in self.shell.user_ns:
                    continue
                if getattr(self, unders) is not self.shell.user_ns.get(unders):
                    update_unders = False

            self.___ = self.__
            self.__ = self._
            self._ = result

要恢复下划线变量功能,只需在ipython repl中运行此代码

out_len=len(Out)
for index,n in enumerate(Out):
    if index==out_len-1:   _=Out[n]
    if index==out_len-2:  __=Out[n]
    if index==out_len-3: ___=Out[n]
    if index==out_len-4:____=Out[n]

答案 1 :(得分:0)

一种获取上次执行结果的安全方法(绕过下划线的特殊用法)是:

from IPython import get_ipython

ipython = get_ipython()

_ = ipython.last_execution_result.result

如果最后一次执行没有结果,则上面的代码会将下划线设置为None

因此,这不会(有必要)获得上一次执行结果为的结果

当下划线的特殊含义仍然完好无损时,它将是最后执行的结果(基本上跳过None值)。

要获得这种行为,需要付出更多的努力。

如果您的代码在全局上下文中执行(因此不在库中执行),则可以执行以下操作:

_ = Out.get(max(Out.keys(), default=0))

如果没有执行结果,则将下划线设置为None

如果您的代码在库中执行,并且您不想传递globals(),则可以执行以下操作:

out_hist = ipython.history_manager.output_hist  # ipython as set above

... out_hist.get(max(out_hist.keys(), default=0)) ...