34

Is there a way to know, during run-time, a variable's name (from the code)? Or do variable's names forgotten during compilation (byte-code or not)?

e.g.:

>>>  vari = 15
>>>  print vari.~~name~~()
'vari'

Note: I'm talking about plain data-type variables (int, str, list etc.)

Berry Tsakala
  • 15,313
  • 12
  • 57
  • 80
  • 8
    Don't you have to type the variable name to get the name of it? – Colin Burnett May 31 '09 at 20:57
  • 2
    Yeah, well, it's been 3 years ago, and i don't remember why this question made sense. But woa! it's extremely popular, so there's something about it. – Berry Tsakala Jan 21 '13 at 16:28
  • 1
    Here is a usage example: variables foo,bar,baz are there, I want to get a dictionary exactly as {'foo':foo,'bar':bar,'baz':baz}. Surely I can type out as what I just did, but not very succinct. `locals()`, in my opinion, pass too much information, not perfect. What I expect is a function like `magic_func([foo,bar,baz])` which returns the dictionary I want – ZZY Jun 05 '14 at 12:39
  • 1
    Possible duplicate of [Can I print original variable's name in Python?](https://stackoverflow.com/questions/544919/can-i-print-original-variables-name-in-python) – Ciro Santilli OurBigBook.com Jul 26 '19 at 19:38
  • 2
    Interesting trick added in Python 3.8, that answered my usage need related to your question: https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging – LoneCodeRanger Oct 13 '20 at 11:07

9 Answers9

34

Variable names don't get forgotten, you can access variables (and look which variables you have) by introspection, e.g.

>>> i = 1
>>> locals()["i"]
1

However, because there are no pointers in Python, there's no way to reference a variable without actually writing its name. So if you wanted to print a variable name and its value, you could go via locals() or a similar function. ([i] becomes [1] and there's no way to retrieve the information that the 1 actually came from i.)

Michael Kuhn
  • 8,302
  • 6
  • 26
  • 27
  • this solves my case. then i make reverse lookup on their values, and find their names. thanks. – Berry Tsakala May 31 '09 at 21:11
  • 6
    The hard part about this is that if you only have `i' then it is impossible to find it's name in `locals()`. Consider 'i=1; j=1;'. After this 'locals()["i"] is locals()["j"]'. If all that you have is `i' then looping through locals() will result in finding either `i' or `j' as the name. – D.Shawley Jun 01 '09 at 02:10
  • 2
    D. probably intended to say "If all that you have is `1` [...]" – akaihola Aug 19 '09 at 05:00
12

Variable names persist in the compiled code (that's how e.g. the dir built-in can work), but the mapping that's there goes from name to value, not vice versa. So if there are several variables all worth, for example, 23, there's no way to tell them from each other base only on the value 23 .

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
4

Here is a function I use to print the value of variables, it works for local as well as globals:

import sys
def print_var(var_name):
    calling_frame = sys._getframe().f_back
    var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None))
    print (var_name+':', str(var_val))

So the following code:

global_var = 123
def some_func():
    local_var = 456
    print_var("global_var")
    print_var("local_var")
    print_var("some_func")

some_func()

produces:

global_var: 123
local_var: 456
some_func: <function some_func at 0x10065b488>
Periodic Maintenance
  • 1,698
  • 4
  • 20
  • 32
  • This is what I was looking for. However, now I'm curious if this can be expanded to work for any expression given the context of when `print_var` is called. One use case would be to print both the name and value of a field of an object (e.g., `print_var('myobject.x')`) – anishpatel Oct 24 '15 at 18:04
  • That wasn't too hard actually: https://gist.github.com/anishpatel/e32f9cdc1df55692f418 – anishpatel Oct 24 '15 at 18:34
3

here a basic (maybe weird) function that shows the name of its argument... the idea is to analyze code and search for the calls to the function (added in the init method it could help to find the instance name, although with a more complex code analysis)

def display(var):
    import inspect, re
    callingframe = inspect.currentframe().f_back
    cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines
    m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE)
    print m.group(1), type(var), var

please note: getting multiple lines from the calling code helps in case the call was split as in the below example:

display(
        my_var
       )

but will produce unexpected result on this:

display(first_var)
display(second_var)

If you don't have control on the format of your project you can still improve the code to detect and manage different situations...

Overall I guess a static code analysis could produce a more reliable result, but I'm too lazy to check it now

user110954
  • 751
  • 8
  • 9
3

This will work for simple data types (str, int, float, list etc.)

def my_print(var_str) :
    print var_str+':', globals()[var_str]
bstpierre
  • 30,042
  • 15
  • 70
  • 103
Hadsbjerg
  • 39
  • 1
  • It just needs to be noted, that if you have, say `ix = 200`, then you call this function with `my_print("ix")`. – sdaau Dec 17 '13 at 00:10
3

Nice easy solution using f-string formatting, which is native to Python 3.6 and later:

vari = 15
vari_name = f"{vari=}".split("=")[0]
print(vari_name)

Produces:

vari
vmTim
  • 59
  • 2
2

You can do it, it's just not pretty.

import inspect, sys


def addVarToDict(d, variable):
    lineNumber = inspect.currentframe().f_back.f_lineno
    with open(sys.argv[0]) as f:
        lines = f.read().split("\n")

    line = lines[lineNumber-1]

    varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip()
    d[varName] = variable


d = {}

a=1

print d # {}
addVarToDict(d,a)
print d # {'a': 1}
will
  • 10,260
  • 6
  • 46
  • 69
1

I tried the following link from the post above with no success: Googling returned this one.

http://pythonic.pocoo.org/2009/5/30/finding-objects-names

Ben Blank
  • 54,908
  • 28
  • 127
  • 156
  • Except now that I've upvoted this one, it's not necessarily "the post above": we're talking about @piquadrat's answer. – ptomato Feb 10 '11 at 09:36
0

Just yesterday I saw a blog post with working code that does just this. Here's the link:

http://pyside.blogspot.com/2009/05/finding-objects-names.html

Benjamin Wohlwend
  • 30,958
  • 11
  • 90
  • 100
  • "Sorry, the page you were looking for in this blog does not exist." – Stuart Woodward Jun 26 '13 at 05:21
  • 2
    @StuartWoodward: archive.org has a copy: http://web.archive.org/web/20090624235438/http://pyside.blogspot.com/2009/05/finding-objects-names.html – Benjamin Wohlwend Jun 26 '13 at 08:28
  • It'll also only work in it's current form if it's used in the `main` python file, if it's imported it'll open the wrong file, so it'd need to be adapted. – will Oct 31 '13 at 22:39