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

如何对变量做同样的事情呢?与函数相反,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))

其他回答

>>> locals()['foo']
{}
>>> globals()['foo']
{}

如果你想写你自己的函数,你可以这样做,你可以检查一个局部变量定义,然后检查全局变量。如果没有找到,可以比较id(),看看变量是否指向内存中的相同位置。

如果你的变量在一个类中,你可以使用className.dict.keys()或vars(self)来查看你的变量是否已经被定义。

在Python中,def和class关键字将特定的名称绑定到它们定义的对象(函数或类)。类似地,模块通过在文件系统中调用某个特定的名称来命名。在这三种情况下,都有一种明显的方法可以将“规范”名称分配给有问题的对象。

然而,对于其他类型的对象,这样的规范名称可能根本不存在。例如,考虑列表中的元素。列表中的元素不是单独命名的,在程序中引用它们的唯一方法完全可能是在包含它们的列表上使用列表索引。如果将这样一个对象列表传递到函数中,则不可能为值分配有意义的标识符。

Python不会将赋值对象左边的名称保存到赋值对象中,因为:

这需要在多个冲突的对象中找出哪个名称是“规范的”, 对于那些从未赋值给显式变量名的对象来说,这是没有意义的, 这样效率会非常低, 实际上没有其他现存的语言能做到这一点。

例如,使用lambda定义的函数将始终具有"name" <lambda>,而不是特定的函数名。

最好的方法是简单地要求调用者传入一个(可选的)名称列表。如果输入“…”,“…”'太麻烦了,你可以接受一个包含逗号分隔的名字列表的字符串(像namedtuple那样)。

许多答案只返回一个变量名。但如果有多个变量具有相同的值,这就不能很好地工作。下面是Amr Sharaki的答案的一个变体,如果更多变量具有相同的值,则返回多个结果。

def getVariableNames(variable):
    results = []
    globalVariables=globals().copy()
    for globalVariable in globalVariables:
        if id(variable) == id(globalVariables[globalVariable]):
            results.append(globalVariable)
    return results

a = 1
b = 1
getVariableNames(a)
# ['a', 'b']

下面的方法将不会返回变量的名称,但如果变量在全局作用域可用,则使用此方法可以轻松创建数据帧。

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}

A = [0, 1]
B = [1, 2]
pd.DataFrame(G.A + G.B) # It will return a data frame with A and B columns

我认为在Python中很难做到这一点,因为一个简单的事实是,你永远不会不知道你正在使用的变量的名称。所以,在他的例子中,你可以这样做:

而不是:

list_of_dicts = [n_jobs, users, queues, priorities]

dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}