从Python Shell,IPython控制台和脚本内部出现的下一个函数的不同行为

时间:2017-09-03 23:34:58

标签: python ipython next

我有一个定义了next方法的类。当我从命令行运行一个脚本来创建这个类的对象并运行以下循环来调用next时,不会打印next的返回值但是当我从Python控制台运行相同的行时,返回值已打印。

更具体地说,如果我们将以下脚本保存为tests.py

class Solution():
    def __next__(self):
        return 1

s = Solution()
for _ in range(5):
    next(s)

并运行python test.py,没有打印任何内容(我在Python 3.4和Windows机器上对此进行了测试)。

但是,如果我们在Python shell中执行以下操作,则会打印输出:

(python34) C:\>python
Python 3.4.5 |Anaconda custom (64-bit)| (default, Jul  5 2016, 14:53:07) [MSC 
v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class Solution():
...     def __next__(self):
...         return 1
...
>>> s = Solution()
>>> for _ in range(5):
...     next(s)
...
1
1
1 
1
1

在IPython控制台上也没有打印输出。

1 个答案:

答案 0 :(得分:1)

你可以看到here IPython一个接一个地运行ast节点而不是一次运行所有节点,你可以改变IPython运行节点的方式,但默认情况下它只会触发显示副作用的最后一个根节点AST。如果你有一个for循环,那么" next()"节点不是最后一个根节点," for"是,并且它不返回任何值(它不是表达式的语句)。这是故意不要压倒笔记本中的用户。

我的猜测是,这与Python REPL的语义不同,纯Python repl要么以交互方式运行 last 节点,要么 all ,我不记得了

您可以使用更简单的示例来检查Python repl的功能:您不需要Solution类,您可以使用任何表达式来执行此操作:

>>> for i in range(5):
...     i # try adding more expressions like i**2 on another line
...
0
1
2
3
4

你可以在IPython中使用标志获得相同的行为:

$ ipython --TerminalInteractiveShell.ast_node_interactivity=all
Python 3.6.1 | packaged by conda-forge | (default, May 23 2017, 14:31:56)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.0.dev -- An enhanced Interactive Python. Type '?' for help.

In [1]: for i in range(5):
   ...:     i
   ...:
Out[1]: 0
Out[1]: 1
Out[1]: 2
Out[1]: 3
Out[1]: 4

我个人喜欢last_expr_or_assign值,它使最后一个赋值返回指定的值:

$ ipython --TerminalInteractiveShell.ast_node_interactivity = last_expr_or_assign

Python 3.6.1 |由conda-forge打包| (默认,2017年5月23日,14:31:56) 输入' copyright',' credit'或者'许可证'欲获得更多信息 IPython 6.2.0.dev - 增强的交互式Python。输入'?'寻求帮助。

In [1]: a = 1 # No Out
   ...: b = 2 # Out will be 2. Useless here, 
   ...:       # but nice if you do `df = pd.load_csv(...)`
Out[1]: 2