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
There is no way to know the previous value of a variable without assigning to the object another variable. Only the presence of references keeps an object alive in memory. The garbage collector disposes of the object, when the reference count of the object reaches zero.
IPython allows you to go beyond the single underscore _ with double ( __ ) and triple underscore ( ___ ), returning results of the second- and third-to-last commands.
Python variables store values in a program. You can refer to the name of a variable to access its value. The value of a variable can be changed throughout your program. Variables are declared using this syntax: name = value.
There's a shortcut for the last returned object, _
.
In [1]: 1 + 3
Out[1]: 4
In [2]: _
Out[2]: 4
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With