我希望能够以字符串的形式获取变量的名称,但我不知道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(),所以我猜有一种方法。
大多数对象没有__name__属性。(类、函数和模块可以;还有其他内置类型吗?)
除了print("my_var"),你还期望print(my_var.__name__)有什么?你能直接使用字符串吗?
你可以"slice" a dict:
def dict_slice(D, keys, default=None):
return dict((k, D.get(k, default)) for k in keys)
print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})
另外:
throw = object() # sentinel
def dict_slice(D, keys, default=throw):
def get(k):
v = D.get(k, throw)
if v is not throw:
return v
if default is throw:
raise KeyError(k)
return default
return dict((k, get(k)) for k in keys)
这是一个黑客。它不能在所有Python实现发行版上工作(特别是那些没有traceback.extract_stack的发行版)。
import traceback
def make_dict(*expr):
(filename,line_number,function_name,text)=traceback.extract_stack()[-2]
begin=text.find('make_dict(')+len('make_dict(')
end=text.find(')',begin)
text=[name.strip() for name in text[begin:end].split(',')]
return dict(zip(text,expr))
bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}
注意,这个黑客是脆弱的:
make_dict(bar,
foo)
(在2行上调用make_dict)将无法工作。
与其尝试用foo和bar值生成dict,
从字符串变量名'foo'和'bar'中生成dict会更加python化:
dict([(name,locals()[name]) for name in ('foo','bar')])
虽然这可能是一个糟糕的想法,但它与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"