Getting the name of a variable as a string

2019-01-01 04:15发布

This thread discusses how to get the name of a function as a string in Python: How to get a function name as a string in Python?

How can I do the same for a variable? (note that Python variables do not have the attribute __name__, at least in Python 2.7.x)

In other words, if I have a variable such as:

foo = dict()
foo['bar'] = 2

I am looking for a function/attribute, e.g. retrieve_name:

retrieve_name(foo) 

that returns the string 'foo'

Update:

Since people are asking why I want to do this, here is an example. I would like to create a DataFrame in Pandas from this list, where the column names are given by the names of the actual dictionaries:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]

12条回答
初与友歌
2楼-- · 2019-01-01 04:35

I don't believe this is possible. Consider the following example:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664

The a and b point to the same object, but the object can't know what variables point to it.

查看更多
琉璃瓶的回忆
3楼-- · 2019-01-01 04:36
def name(**variables):
    return [x for x in variables]

It's used like this:

name(variable=variable)
查看更多
君临天下
4楼-- · 2019-01-01 04:38

Even if variable values don't point back to the name, you have access to the list of every assigned variable and its value, so I'm astounded that only one person suggested looping through there to look for your var name.

Someone mentioned on that answer that you might have to walk the stack and check everyone's locals and globals to find foo, but if foo is assigned in the scope where you're calling this retrieve_name function, you can use inspect's current frame to get you all of those local variables. My explanation might be a little bit too wordy (maybe I should've used a "foo" less words), but here's how it would look in code (Note that if there is more than one variable assigned to the same value, you will get both of those variable names):

import inspect

x,y,z = 1,2,3

def retrieve_name(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

print retrieve_name(y)
查看更多
零度萤火
5楼-- · 2019-01-01 04:39

The only objects in Python that have canonical names are modules, functions, and classes, and of course there is no guarantee that this canonical name has any meaning in any namespace after the function or class has been defined or the module imported. These names can also be modified after the objects are created so they may not always be particularly trustworthy.

What you want to do is not possible without recursively walking the tree of named objects; a name is a one-way reference to an object. A common or garden-variety Python object contains no references to its names. Imagine if every integer, every dict, every list, every Boolean needed to maintain a list of strings that represented names that referred to it! It would be an implementation nightmare, with little benefit to the programmer.

查看更多
与风俱净
6楼-- · 2019-01-01 04:40
>>> locals()['foo']
{}
>>> globals()['foo']
{}

if you wanted to write your own function, it could be done such that you could check for a variable defined in locals then check globals. If nothing is found you could compare on id() to see if the variable points to the same place in memory.

If you variable is in a class, you could use className.dict.keys() or vars(self) to see if your variable has been defined.

查看更多
步步皆殇っ
7楼-- · 2019-01-01 04:41

In Python, the def and class keywords will bind a specific name to the object they define (function or class). Similarly, modules are given a name by virtue of being called something specific in the filesystem. In all three cases, there's an obvious way to assign a "canonical" name to the object in question.

However, for other kinds of objects, such a canonical name may simply not exist. For example, consider the elements of a list. The elements in the list are not individually named, and it is entirely possible that the only way to refer to them in a program is by using list indices on the containing list. If such a list of objects was passed into your function, you could not possibly assign meaningful identifiers to the values.

Python doesn't save the name on the left hand side of an assignment into the assigned object because:

  1. It would require figuring out which name was "canonical" among multiple conflicting objects,
  2. It would make no sense for objects which are never assigned to an explicit variable name,
  3. It would be extremely inefficient,
  4. Literally no other language in existence does that.

So, for example, functions defined using lambda will always have the "name" <lambda>, rather than a specific function name.

The best approach would be simply to ask the caller to pass in an (optional) list of names. If typing the '...','...' is too cumbersome, you could accept e.g. a single string containing a comma-separated list of names (like namedtuple does).

查看更多
登录 后发表回答