views:

179

answers:

4

Is it possible to get the original variable name of a variable passed to a function? E.g.

foobar = "foo"

def func(var):
    print var.origname

So that:

func(foobar)

Returns:

>>foobar

EDIT:

All I was trying to do was make a function like:

def log(soup):
    f = open(varname+'.html', 'w')
    print >>f, soup.prettify()
    f.close()

.. and have the function generate the filename from the name of the variable passed to it.

I suppose if it's not possible I'll just have to pass the variable and the variable's name as a string each time.

+4  A: 

You can't. It's evaluated before being passed to the function. All you can do is pass it as a string.

Max Shawabkeh
Is there then maybe a way to take a variable and save its name as a string?
Acorn
You could access the `locals()` and `globals()` dictionaries and look for variables that match the value, but that's really inelegant. Better to simply pass it manually: `log('myvar', myvar)`.
Max Shawabkeh
+2  A: 

If you want a Key Value Pair relationship, maybe using a Dictionary would be better?

...or if you're trying to create some auto-documentation from your code, perhaps something like Doxygen (http://www.stack.nl/~dimitri/doxygen/) could do the job for you?

Nick Cartwright
+6  A: 

EDIT: To make it clear, I don't recommend using this AT ALL, it will break, it's a mess, it won't help you in anyway, but it's doable for entertainment/education purposes.

You can hack around with the inspect module, I don't recommend that, but you can do it...

import inspect

def foo(a, f, b):
    frame = inspect.currentframe()
    frame = inspect.getouterframes(frame)[1]
    string = inspect.getframeinfo(frame[0]).code_context[0].strip()
    args = string[string.find('(') + 1:-1].split(',')

    names = []
    for i in args:
        if i.find('=') != -1:
            names.append(i.split('=')[1].strip())

        else:
            names.append(i)

    print names

def main():
    e = 1
    c = 2
    foo(e, 1000, b = c)

main()

Output:

['e', '1000', 'c']
Ivo Wetzel
+1: One of the hackiest pieces of code I've seen in a long time.
Max Shawabkeh
Being the hackiest code in a long time deserves a +1? I'd've flipped the sign there.
Devin Jeanpierre
As I said, I don't recommend using that, nor would I ever use such a hack. Using inspect is IMO always a sign that something is going horrible, horrible wrong. I just wanted to show that it's possible... but as we all know, you shouldn't do something JUST because it's possible.
Ivo Wetzel
@Devin: Using such code in a real application would deserve a -1. Writing it to show that something unusual can be achieved through an ingenious abuse of reflection is impressive, and certainly deserves a +1.
Max Shawabkeh
+2  A: 

Looks like Ivo beat me to inspect, but here's another implementation:

import inspect

def varName(var):
    lcls = inspect.stack()[2][0].f_locals
    for name in lcls:
        if id(var) == id(lcls[name]):
            return name
    return None

def foo(x=None):
    lcl='not me'
    return varName(x)

def bar():
    lcl = 'hi'
    return foo(lcl)

bar()
# 'lcl'

Of course, it can be fooled:

def baz():
    lcl = 'hi'
    x='hi'
    return foo(lcl)

baz()
# 'x'

Moral: don't do it.

outis