我已经读了如何获得一个函数名作为字符串?。

如何对变量做同样的事情呢?与函数相反,Python变量没有__name__属性。

换句话说,如果我有一个变量,比如:

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

我正在寻找一个函数/属性,例如retrieve_name(),以便从这个列表中创建一个DataFrame in Pandas,其中列名由实际字典的名称给出:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts] 

当前回答

iDilip的答案压缩版:

import inspect
def varname(x):
  return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]

hi = 123
print(varname(hi))

其他回答

当从变量值中查找变量名时, 你可能有几个变量等于相同的值, 例如var1 = 'hello'和var2 = 'hello'。

我的解决方案:

def find_var_name(val):

    dict_list = []
    global_dict = dict(globals())

    for k, v in global_dict.items():
        dict_list.append([k, v])
   
    return [item[0] for item in dict_list if item[1] == val]

var1 = 'hello'
var2 = 'hello'
find_var_name('hello')

输出

['var1', 'var2']

iDilip的答案压缩版:

import inspect
def varname(x):
  return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]

hi = 123
print(varname(hi))

你可以以kwargs的形式获取变量,并以字符串的形式返回:

var=2
def getVarName(**kwargs):
    return list(kwargs.keys())[0]

print (getVarName(var = var))

注:变量名必须等于自身。

在Python 3.8中,可以简单地使用f-string调试特性:

>>> foo = dict()
>>> f'{foo=}'.split('=')[0]
'foo' 

这种方法的一个缺点是,为了打印'foo',你必须自己添加f'{foo=}'。换句话说,你已经知道变量的名字了。换句话说,上面的代码片段与刚才完全相同

>>> 'foo'

即使变量值不指向名称,您也可以访问每个赋值变量及其值的列表,所以我很惊讶,只有一个人建议在那里循环查找您的var名称。

有人在回答中提到,你可能需要遍历堆栈并检查每个人的局部变量和全局变量来找到foo,但如果foo被赋值在你调用retrieve_name函数的作用域内,你可以使用inspect的当前帧来获取所有这些局部变量。

我的解释可能有点太啰嗦了(也许我应该用“foo”更少的单词),但下面是它在代码中的样子(注意,如果有多个变量赋给相同的值,你会得到两个变量名):

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))

如果你从另一个函数调用这个函数,就像这样:

def foo(bar):
    return retrieve_name(bar)

foo(baz)

如果你想要baz而不是bar,你只需要再往后退一步。这可以通过在caller_local_vars初始化中添加额外的.f_back来实现。

请看一个例子:ideone