nachocab
nachocab

Reputation: 14374

How to get the value of the last assigned variable in iPython?

I am a total iPython newbie, but I was wondering if there is a way to get the value of the last assigned variable:

In [1]: long_variable_name = 333
In [2]: <some command/shortcut that returns 333>

In R we have .Last.value:

> long_variable_name = 333
> .Last.value
[1] 333

Upvotes: 15

Views: 7935

Answers (2)

jrd1
jrd1

Reputation: 10716

You can use IPython's In and Out variables which contain the commands/statements entered and the the corresponding output (if any) of those statements.

So, a naive approach would be to use those variables as the basis of defining a %last magic method.

However, since not all statements necessarily generate output, In and Out are not synchronous.

So, the approach I came up with was to parse In, and look for the occurrences of = and parse those lines for the output:

def last_assignment_value(self, parameter_s=''):
     ops = set('()')
     has_assign = [i for i,inpt in enumerate(In) if '=' in inpt] #find all line indices that have `=`
     has_assign.sort(reverse=True) #reverse sort, because the most recent assign will be at the end
     for idx in has_assign:
         inpt_line_tokens = [token for token in In[idx].split(' ') if token.strip() != ''] #
         indices = [inpt_line_tokens.index(token) for token in inpt_line_tokens if '=' in token and not any((c in ops) for c in token)]
         #Since assignment is an operator that occurs in the middle of two terms
         #a valid assignment occurs at index 1 (the 2nd term)
         if 1 in indices:
             return ' '.join(inpt_line_tokens[2:]) #this simply returns on the first match with the above criteria

And, lastly to make that your own custom command in IPython:

get_ipython().define_magic('last', last_assignment_value)

And, now you can call:

%last

And this will output the term assigned as a string (which may not be what you want).

However, there is a caveat to this: in that if you had entered incorrect input that involved assignment; e.g.: (a = 2), this method will pick it up. And, if your assignment involved variables: e.g. a = name, this method will return name and the not the value of name.

Given that limitation, you can then use the parser module to try and evaluate the expression like this (which can be appended to last_assignment_value in the last if statement):

import parser
def eval_expression(src):
    try:
        st = parser.expr(src)
        code = st.compile('obj.py')
        return eval(code)
    except SyntaxError:
        print 'Warning: there is a Syntax Error with the RHS of the last assignment! "%s"' % src
        return None

However, given the possible evils of eval, I've left that inclusion up to you.

But, to be perfectly honest, a truly wholesome method would involve a parsing of the statement to verify the validity of the found input, as well as the input before it and more.

REFERENCES: https://gist.github.com/fperez/2396341

Upvotes: 3

TankorSmash
TankorSmash

Reputation: 12747

There's a shortcut for the last returned object, _.

In [1]: 1 + 3
Out[1]: 4

In [2]: _
Out[2]: 4

Upvotes: 32

Related Questions