I think it may be because the indentation of the if inside
if-else makes it not on the outermost point on the last line of the cell so IPython/Jupyter doesn't use the InteractiveShell to 'show' it using it's special handling of the last unindented object in a cell, see how last_expr
is the default for InteractiveShell.ast_node_interactivity
here. In the same way as this... Say you run the following in a cell:
a = 4
a
That's going to show 4
as Out
.
But if you do the following in the next cell, it isn't going to show 4
:
inside = True
if inside:
a
The fancy display handling that IPython / Jupyter applies to the item on the last line doesn't get applied because it's not the outermost item evaluated on that line and so doesn't get passed to IPython's fancy representational handling. (Or at least that is how I think about it. See Thomas K's explanation here about how it only shows the bare expression at the end of the cell when the expressions are in a for
loop and hence indented similar to in your if-else
.) And I think that mirrors what you were doing, maybe?
But this works:
from IPython.display import display
inside = True
if inside:
display(a)
You can do that to force applying the fancy handling it would apply if you just put a
in a cell and ran it.
Or if you first adjust the setting for `InteractiveShell.ast_node_interactivity you can get the following to work:
inside = True
if inside:
a
Before trying that in separate cell, you run either the following:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "last"
-OR-
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
(Because it needs to be run & applied before you run the cell you want to the new settings to be effective for, you cannot just add the code to adjust InteractiveShell.ast_node_interactivity
in the same cell where you are going to run if inside:
.)
OPTION A: adjust InteractiveShell.ast_node_interactivity
to try to fix what you are doing:
And so to make your original example code work, you have the option of first running the following as a cell itself prior to running your inside = True
block of code in your original post:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "last"
Alternative OPTION B: Applying the use if IPython's display to try to fix what you are doing:
So to make your version of the dataframe display class work, let's not shadow IPython's display
because we'll need it. So make this a cell:
class spec_display(object):
'''
Display HTML representation of multiple objects
'''
template = '''<div style="float: left; padding: 10px;">
<p style='font-family:"Courier New", Courier, monospace'>{0}</p>{1}
</div>'''
def __init__(self, *args):
self.args = args
def _repr_html_(self):
return '\n'.join(self.template.format(a, eval(a)._repr_html_()) for a in self.args)
def __repr__(self):
return '\n\n'.join(a + '\n' + repr(eval(a)) for a in self.args)
Then as a separate cell, this works like your original:
import pandas as pd
# Handy class for DataFrame viz
# Create a sample DataFrame with 3 rows and 5 columns
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9],
'D': [10, 11, 12],
'E': [13, 14, 15]
})
# Display the DataFrame
spec_display('df')
Except now in another cell, what you see not working can be made to work by explicitly invoking IPython's display
, just as we can use that to print multiple dataframes in one cell and add titles (I'll come back to that):
from IPython.display import display
inside = True
if inside:
display(spec_display('df'))
Finally, I mentioned above you can use IPython's display
to print multiple dataframes from code in one cell and add titles, all in one output cell. (I bring this up because I see among the comments of your code, "Display HTML representation of multiple objects".) Example of that:
import pandas as pd
df1 = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9],
'D': [10, 11, 12],
'E': [13, 14, 15]
})
df2 = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9],
'D': [10, 11, 12],
'E': [13, 14, 15]
})
from IPython.display import display, HTML
display(HTML('<b>Dataframe One:</b>'))
display(df1)
display(HTML('<b>Dataframe Two:</b>'))
display(df2)
We can tell IPython how to handle things and not rely on the special handling it usually just applies to the unindented final object on the last line.