Issue
I have a class for which the next
method is defined. When I run a script from the command line which creates an object of this class and run the following loop to call next
, the return value of next is not printed but when I run the same lines from a Python console, the return values are printed.
More concretely, if we save the following script as tests.py
:
class Solution():
def __next__(self):
return 1
s = Solution()
for _ in range(5):
next(s)
And run python test.py
, nothing is printed (I tested this on Python 3.4 and a Windows machine).
However, if we do as follows in a Python shell, the output will be printed:
(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
On the IPython console also no output is printed.
Solution
You can see here that IPython runs the ast nodes one by one instead of all at once, you can change how IPython run nodes, but by default it will trigger display side effect only on the last root node of the AST. If you have a for loop, the "next()" node is not the last root node, the "for" is, and it return no value (it's a statement not an expression). This is deliberate not to overwhelm users in a notebook.
My guess is this is semantically different than what the Python REPL does, the pure Python repl either run run interactively the last node, or all, I do not remember.
You can check what the Python repl does with simpler examples: You do not need the Solution
class, you can do it with any expressions, which does work:
>>> for i in range(5):
... i # try adding more expressions like i**2 on another line
...
0
1
2
3
4
And you can get the same behavior in IPython with a flag:
$ 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
I personally love the last_expr_or_assign
value that make the last assignment return the assigned value:
$ ipython --TerminalInteractiveShell.ast_node_interactivity=last_expr_or_assign
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]: a = 1 # No Out
...: b = 2 # Out will be 2. Useless here,
...: # but nice if you do `df = pd.load_csv(...)`
Out[1]: 2
Answered By - Matt
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.