Issue
I am an engineer and I use a python REPL as an advanced calculator while working. I use the "previous output" feature of the REPL, which is _, often.
>>>45*0.344
15.48
>>>_*2
30.96
Something like that.
For some reason I find it kind of a chore to type the underscore though. I've used the Haskell REPL, which uses "it" as the previous output variable, which I find easier to type.
I learned that iPython lets you define macros that execute some code. So I popped open an iPython shell and defined a %macro called "it" that mimics the "_".
In [1]: _
Out[1]: ''
In [2]: %macro it 1
Macro `it` created. To execute, type its name (without quotes).
=== Macro contents: ===
_
I can call "it" like so:
In [1]: 4
Out[1]: 4
In [2]: it
Out[2]: 4
However, when I try to do something with "it" like it*4
, I get the error unsupported operand type(s) for *: 'Macro' and 'int'
.
I want "it" to be the type it's returning instead of the type Macro, so that I can use it just like I use "_".
Solution
Instead of going the macro route you could also change the code where _
gets assigned. sys.displayhook
does this and can be changed:
The display of these values can be customized by assigning another one-argument function to sys.displayhook.
So we can simply save in __builtins__.it
or whatever name you like:
import sys
ipython_displayhook = sys.displayhook
def mydisplayhook(value):
if value is not None:
__builtins__.it = value
return ipython_displayhook(value)
sys.displayhook = mydisplayhook
This works in the normal python shell, but somehow ipython prevents with tampering with sys.displayhook
. The code in ipython that handles the displayhook is in IPython.core.displayhook.DisplayHook
so we can monkey patch that:
import IPython.core.displayhook
__call__ = IPython.core.displayhook.DisplayHook.__call__
def mycall(self, value):
if value is not None:
__builtins__.it = value
__call__(self, value)
IPython.core.displayhook.DisplayHook.__call__ = mycall
This is a bit hacky. Things may break, but after testing this for 5 seconds it seems that it works.
You probably don't want to type that everytime you start ipython, but we can automate that. This answer says you can simply put a file into ~/.ipython/profile_default/startup/
which gets then executed everytime.
Answered By - syntonym
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.