Programming Python Research Utility Functions

Small Python Interactive Interface Trick

Not too long ago, I helped someone with some research work, and one of the research tools was also used from the Python interactive prompt.
The interface used was handy enough for development: intuitive, readable, short, and useful. Still, for interactive research it wasn’t handy enough.
To improve the script, I decided to use a trick I heard about a long time ago – using __repr__:

class NoParens(object):
    def __init__(self, obj):
        self.obj = obj
    def __call__(self, *args, **kwargs):
        return self.obj(*args, **kwargs)
    def __repr__(self):
        result = self.obj()
        return str(result)

And using it looks like this:

In [2]: import noparens
In [3]: def test():
   ...:     return 4**4
In [4]: t = noparens.NoParens(test)
In [5]: t
Out[5]: 256
In [6]: t,t,t
Out[6]: (256, 256, 256)

For research consoles that interact with other programs or devices, such as debuggers and sniffers I found this useful, and made work a bit less annoying.

9 replies on “Small Python Interactive Interface Trick”

Thanks :)
The best example would be a debugger:
Given a single_step() function, use s as a shorthand, and maybe r for run(), and p for print_state().
Given these, debugging with a Python interactive prompt gets a little bit easier. Especially when you can do:

Two reasons:
1. I didn’t know about it, thanks :)
2. Even if I had, I couldn’t have used it. I was using an embedded Python shell, that doesn’t work with IPython. Although integrating it is possible, that work wasn’t done.
That made using this shell even more painful, because I didn’t have all the fancy IPython features, such as tab-completion. That pain made this trick even more useful than it normally is.

Could work nicely as a decorator too:

def noparens(func):
class ReprFunc(object):
def __init__(self, f):
self.f = f
def __repr__(self):
return str(self.f())
def __call__(self, *args, **kwargs):
return self.f(*args, **kwargs)
return ReprFunc(func)


def foo():
return 6*3

>>> foo

Nice idea!
However, to do what you propose you don’t need to change the code of NoParens, you can already use it as is. Any callable object may be used as a decorator.

Is this your script’ purpose as I think? like below:

>>> def test():
… return 4**4

>>> t = test()
>>> t

No, it isn’t.
In your code snippet, t holds the result of a single call to test().
However, in the interactive prompt when you do
>>> x [enter]
x.__repr__() gets called.
So, in my version, each time you try to view t, you actually call NoParens.__repr__, and that means a new call to test. I believe this would be clearer if test() returned time.time():

In [2]: import noparens

In [3]: import time

In [4]: def test():
…: return time.time()

In [5]: t = noparens.NoParens(test)

In [6]: t
Out[6]: 1228124415.74

In [7]: t
Out[7]: 1228124416.37

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.