我希望能够以字符串的形式获取变量的名称,但我不知道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(),所以我猜有一种方法。
好吧,几天前我遇到了同样的需求,必须获得一个指向对象本身的变量名。
为什么这么有必要呢?
In short I was building a plug-in for Maya. The core plug-in was built using C++ but the GUI is drawn through Python(as its not processor intensive). Since I, as yet, don't know how to return multiple values from the plug-in except the default MStatus, therefore to update a dictionary in Python I had to pass the the name of the variable, pointing to the object implementing the GUI and which contained the dictionary itself, to the plug-in and then use the MGlobal::executePythonCommand() to update the dictionary from the global scope of Maya.
为了做到这一点,我所做的是:
import time
class foo(bar):
def __init__(self):
super(foo, self).__init__()
self.time = time.time() #almost guaranteed to be unique on a single computer
def name(self):
g = globals()
for x in g:
if isinstance(g[x], type(self)):
if g[x].time == self.time:
return x
#or you could:
#return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
#and return all keys pointing to object itself
我知道这不是一个完美的解决方案,在全局许多键可以指向同一个对象,例如:
a = foo()
b = a
b.name()
>>>b
or
>>>a
而且这种方法不是线程安全的。如果我错了,请指正。
至少这种方法解决了我的问题,它在全局作用域中获取指向对象本身的任何变量的名称,并将其作为参数传递给插件,供它在内部使用。
我在int(原始整数类)上尝试了这一点,但问题是这些原始类不会被绕过(请纠正使用的技术术语,如果它是错误的)。你可以重新实现int,然后执行int = foo,但a = 3永远不会是foo的对象,而是原语的对象。为了克服这个问题,你必须使用a = foo(3)来让a.name()工作。
它不会返回变量的名称,但您可以轻松地从全局变量创建字典。
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}
这是一个黑客。它不能在所有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')])