others - 在Python,如何将变量名作为字符串?

我希望能够以字符串的形式获得变量的名称,但是,我不知道python是否具有强大的 introspection功能,就像这样:


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

我想要这样做,因为我有一系列的var,我想转变成一个字典,如:


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

但是我想要比这更自动的东西。

python有locals()vars()所以,我想有一种方法。

时间:

你想这样做?


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}

正如unwind所说,这不是你在Python中所做的事情 - 变量实际上是对象的名称映射。

但是,这里有一个尝试和执行的方法:


 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
 if id(v) == id(a):
 a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'

我想这么做有很多方法。


blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

这是一个hack,它不能在所有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}

注意这个hack很脆弱


make_dict(bar,
 foo)

(在2行上调用make_dict)将不起作用。

而不是尝试从值foobar生成:它将更多地生成字符串变量名和'bar'的::


dict([(name,locals()[name]) for name in ('foo','bar')])

我编写了一个小函数来对代码中的各种变量进行快速内联头检查,它列出了变量名,数据类型,大小和其他属性,所以,我可以快速捕捉到我所犯的任何错误,代码很简单:


def details(val):
 vn = val.__name__ # If such a thing existed
 vs = str(val)
 print("The Value of "+ str(vn) + " is " + vs)
 print("The data type of " + vn + " is " + str(type(val)))

因此,如果你有一些复杂的dictionary/list/tuple情况,那么让解释器返回你指定的变量名是非常有帮助,例如下面是一个奇怪的字典:


m = 'abracadabra'
mm=[] 
for n in m:
 mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

在python 3中,这很容易


myVariable = 5
for v in locals():
 if id(v) == id("myVariable"):
 print(v, locals()[v])

这将打印:

myVariable 5

可以扩展代码以排除类。


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}

大多数对象都没有__name__属性,(类,函数和模块; 是否有更多内置类型)?

除了print("my_var")之外,你还希望print(my_var.__name__)其他什么? 直接使用字符串可以?

你可以"slice"一个字典:


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)

...