我希望能够以字符串的形式获取变量的名称,但我不知道Python是否有那么多的自省功能。喜欢的东西:

>>> print(my_var.__name__)
'my_var'

我想这样做是因为我有一堆变量,我想把它们转换成一个字典,比如:

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

但我想要更自动的。

Python有locals()和vars(),所以我猜有一种方法。


当前回答

我发现如果你已经有了一个特定的值列表,那么@S描述的方式。抽签是最好的;然而,下面描述的方法可以很好地在整个代码中添加所有的变量和类,而不需要提供变量名,尽管如果你想要指定它们。可以扩展代码以排除类。

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

输出:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

其他回答

在阅读这篇文章时,我看到了很多可怕的摩擦。给予很容易 一个糟糕的答案,然后让别人给出正确的答案。总之,这是我的发现。

来自:[effbot.org] (http://effbot.org/zone/python-objects.htm#names)

名称有点不同——它们不是对象的真正属性,对象本身也不知道它叫什么。

对象可以有任意数量的名称,也可以没有名称。

名称存在于名称空间中(例如模块名称空间、实例名称空间、函数的本地名称空间)。

注意:它说对象本身不知道它叫什么,所以这是线索。Python对象不是自引用的。然后它说,名称存在于名称空间中。我们在TCL/TK中有这个。所以也许我的回答会有所帮助(但它确实帮助了我)


    jj = 123
    print eval("'" + str(id(jj)) + "'")
    print dir()

166707048 ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj'] So there is 'jj' at the end of the list. Rewrite the code as: jj = 123 print eval("'" + str(id(jj)) + "'") for x in dir(): print id(eval(x)) 161922920 ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj'] 3077447796 136515736 3077408320 3077656800 136515736 161922920 This nasty bit of code id's the name of variable/object/whatever-you-pedantics-call-it. So, there it is. The memory address of 'jj' is the same when we look for it directly, as when we do the dictionary look up in global name space. I'm sure you can make a function to do this. Just remember which namespace your variable/object/wypci is in. QED.

它不会返回变量的名称,但您可以轻松地从全局变量创建字典。

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}

你真的想这么做吗?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

例子

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}

我上传了一个解决方案到pypi。它是一个模块,定义了c#的nameof函数的等价物。

它遍历被调用帧的字节码指令,获取传递给它的变量/属性的名称。这些名称可以在函数名后面的LOAD指令的.argrepr中找到。

虽然这可能是一个糟糕的想法,但它与rlotun的答案相同,但它会更经常地返回正确的结果。

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

你这样称呼它:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"