rspears69
rspears69

Reputation: 435

iPython macros operations

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 "_".

Upvotes: 1

Views: 334

Answers (2)

syntonym
syntonym

Reputation: 7384

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.

Upvotes: 1

hpaulj
hpaulj

Reputation: 231355

When I try that I get

In [329]: it.value
Out[329]: '_\n'

The macro includes the '\n'. So a stand alone it behaves ok. But it can't be used in-line.

Upvotes: 0

Related Questions