如何在Python中获得一个string的variables名?
我希望能够以string的forms获取variables的名称,但是我不知道Python是否具有这种内省function。 就像是:
>>> 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()
,所以我想有一种方法。
你想要做这个吗?
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中做的事 – variables实际上是对象的名称映射。
不过 ,这里有一个方法来尝试做到这一点:
>>> a = 1 >>> for k, v in list(locals().iteritems()): if v is a: a_as_str = k >>> a_as_str a >>> type(a_as_str) 'str'
我想这样做很多。 这种攻击与rlotun的build议非常相似,但是它是一个单线,这对我很重要:
blah = 1 blah_name = [ k for k,v in locals().iteritems() if v is blah][0]
这在Python中是不可能的,它确实没有“variables”。 Python有名称,同一对象可以有多个名称。
这是一个黑客。 它不适用于所有的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)
(在两行中调用make_dict)将不起作用。
不要试图从foo
和bar
这两个值中生成dict,而是从stringvariables名称 'foo'
和'bar'
生成dict,这将是更多的pythonic:
dict([(name,locals()[name]) for name in ('foo','bar')])
我认为我的问题将有助于说明为什么这个问题是有用的,它可能会更深入地了解如何回答这个问题。 我写了一个小函数来对我的代码中的各种variables进行快速的内联头部检查。 基本上,它列出了variables名称,数据types,大小和其他属性,所以我可以很快地发现我犯的任何错误。 代码很简单:
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)))
所以如果你有一些复杂的字典/列表/元组的情况下,解释器返回你指定的variables名是相当有帮助的。 例如,这是一个奇怪的字典:
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
我发现如果你已经有了一个特定的值列表,那就是@S描述的方式。 洛特是最好的; 然而,下面描述的方式可以很好的获得所有的variables和类, 而不需要提供variables名,尽pipe你可以指定它们。 代码可以扩展到排除类。
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}
在读线时,我看到了很多的摩擦。 给出一个不好的答案很容易,然后让别人给出正确的答案。 无论如何,这是我发现的。
From:[effbot.org]( http://effbot.org/zone/python-objects.htm#names )
名称有点不同 – 它们不是对象的真正属性,而对象本身并不知道它的名称。
一个对象可以有任意数量的名字,或者根本没有名字。
名称存在于命名空间中(例如模块命名空间,实例命名空间,函数的本地命名空间)。
注意:它说对象本身不知道它叫什么 ,所以这是线索。 Python对象不是自引用的。 然后它说, 名字居住在命名空间 。 我们在TCL / TK有这个。 所以也许我的回答会有所帮助(但是它对我有帮助)
jj = 123 print eval(“'”+ str(id(jj))+“'”) 打印dir()
166707048 ['__builtins__','__doc__','__file__','__name__','__package__','jj']
所以列表末尾有'jj'。
重写代码为:
jj = 123 print eval(“'”+ str(id(jj))+“'”) for d in dir(): 打印编号(eval(x))
161922920 ['__builtins__','__doc__','__file__','__name__','__package__','jj'] 3077447796 136515736 3077408320 3077656800 136515736 161922920
这个令人讨厌的代码ID是variables/对象/无论你什么样的东西 – 调用它的名字。
所以,它是。 当我们直接查找时,'jj'的内存地址是一样的,就像我们在全局名字空间中做字典查找一样。 我相信你可以做一个function来做到这一点。 只要记住你的variables/对象/ wypci在哪个命名空间。
QED。
Python3。 使用inspect来捕获调用的本地名称空间,然后使用这里提出的想法。 正如已经指出的那样,可以返回多个答案。
def varname(var): import inspect frame = inspect.currentframe() var_id = id(var) for name in frame.f_back.f_locals.keys(): try: if id(eval(name)) == var_id: return(name) except: pass
我根据这个问题的答案写了一个整洁有用的函数。 我把它放在这里,以防它有用。
def what(obj, callingLocals=locals()): """ quick function to print name of input and value. If not for the default-Valued callingLocals, the function would always get the name as "obj", which is not what I want. """ for k, v in list(callingLocals.items()): if v is obj: name = k print(name,"=", obj)
用法:
>> a = 4 >> what(a) a = 4 >>|
仅供参考,以下是使用关键字的答案:
在函数的参数列表中使用**说明符收集参数; 这给你的关键字参数作为一个字典。
资源
解:
>>> def get_var_name(**kwargs): return kwargs.keys()[0]
用于:
>>> var = 'this is variable' >>> get_var_name(var=var) 'var'
原来的答案: https : //stackoverflow.com/a/19201952/2628312
大多数对象没有__name__属性。 (类,函数和模块,还有更多的内置types有吗?)
除了print("my_var")
之外,还有什么您期望的print(my_var.__name__)
print("my_var")
? 你能直接使用string吗?
你可以“切片”一个字典:
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)
好吧,几天前我遇到了同样的需求 , 不得不得到一个指向对象本身的variables名称 。
为什么这是必要的?
总之我正在为Maya构build一个插件。 核心插件是使用C ++构build的,但GUI是通过Python绘制的(因为它不是处理器密集型的)。 由于我还不知道如何从插件中return
多个值,除了默认的MStatus
,所以要更新Python中的字典,我必须传递variables的名称,指向实现GUI的对象并包含字典本身的插件,然后使用MGlobal::executePythonCommand()
从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
我知道这并不是在globals
的完美解决scheme,许多键可能指向相同的对象,例如:
a = foo() b = a b.name() >>>b or >>>a
而且这种方法不是线程安全的。 纠正我,如果我错了。
至less这种方法通过获取全局范围内指向对象本身的任何variables的名称来解决我的问题,并将其作为parameter passing给插件,供内部使用。
我在int
(原始的整数类)上试过这个,但问题是这些原始类不会被绕过(如果错误的话,请纠正使用的技术术语)。 你可以重新实现int
,然后做int = foo
但是a = 3
永远不会是foo
的对象,而是原始的。 为了克服,你必须a = foo(3)
让a.name()
工作。
随着Python 2.7和更新,也有字典理解,使其稍短。 如果可能的话,我会使用getattr,而不是eval(eval是邪恶的),就像在顶部的答案。 自我可以是任何具有你所看到的上下文的对象。 它可以是一个对象或locals = locals()等
{name: getattr(self, name) for name in ['some', 'vars', 'here]}
也许我正在试图这个,但..
str_l = next((k for k,v in locals().items() if id(l) == id(v))) >>> bar = True >>> foo = False >>> my_dict=dict(bar=bar, foo=foo) >>> next((k for k,v in locals().items() if id(bar) == id(v))) 'bar' >>> next((k for k,v in locals().items() if id(foo) == id(v))) 'foo' >>> next((k for k,v in locals().items() if id(my_dict) == id(v))) 'my_dict'
我正在研究类似的问题。 S.Lott说:“如果你有variables列表,”发现“他们的名字有什么意义? 我的答案只是看是否可以完成,如果由于某种原因,你想按typessortingvariables列表。 所以无论如何,在我的研究中,我遇到了这个线程,我的解决scheme有点扩展,并基于@rlotun解决scheme。 另一件事,@unutbu说:“这个想法有好处,但是请注意,如果两个variables名称引用相同的值(例如True),那么可能会返回一个无意的variables名称。 在这个练习中,这是真实的,所以我通过使用类似于这个的列表理解来处理每个可能性: isClass = [i for i in isClass if i != 'item']
。 没有它,“项目”会显示在每个列表中。
__metaclass__ = type from types import * class Class_1: pass class Class_2: pass list_1 = [1, 2, 3] list_2 = ['dog', 'cat', 'bird'] tuple_1 = ('one', 'two', 'three') tuple_2 = (1000, 2000, 3000) dict_1 = {'one': 1, 'two': 2, 'three': 3} dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'} x = 23 y = 29 pie = 3.14159 eee = 2.71828 house = 'single story' cabin = 'cozy' isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = [] mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin] print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes) for item in mixedDataTypes: try: # if isinstance(item, ClassType): # use this for old class types (before 3.0) if isinstance(item, type): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isClass.append(mapping_as_str) isClass = [i for i in isClass if i != 'item'] elif isinstance(item, ListType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isList.append(mapping_as_str) isList = [i for i in isList if i != 'item'] elif isinstance(item, TupleType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isTuple.append(mapping_as_str) isTuple = [i for i in isTuple if i != 'item'] elif isinstance(item, DictType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isDict.append(mapping_as_str) isDict = [i for i in isDict if i != 'item'] elif isinstance(item, IntType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isInt.append(mapping_as_str) isInt = [i for i in isInt if i != 'item'] elif isinstance(item, FloatType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isFloat.append(mapping_as_str) isFloat = [i for i in isFloat if i != 'item'] elif isinstance(item, StringType): for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k isString.append(mapping_as_str) isString = [i for i in isString if i != 'item'] else: for k, v in list(locals().iteritems()): if v is item: mapping_as_str = k other.append(mapping_as_str) other = [i for i in other if i != 'item'] except (TypeError, AttributeError), e: print e print '\n isClass:', len(isClass), isClass print ' isList:', len(isList), isList print ' isTuple:', len(isTuple), isTuple print ' isDict:', len(isDict), isDict print ' isInt:', len(isInt), isInt print ' isFloat:', len(isFloat), isFloat print 'isString:', len(isString), isString print ' other:', len(other), other # my output and the output I wanted ''' MIXED_DATA_TYPES total count: 14 isClass: 2 ['Class_1', 'Class_2'] isList: 2 ['list_1', 'list_2'] isTuple: 2 ['tuple_1', 'tuple_2'] isDict: 2 ['dict_1', 'dict_2'] isInt: 2 ['x', 'y'] isFloat: 2 ['pie', 'eee'] isString: 2 ['house', 'cabin'] other: 0 [] '''
import re import traceback pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)') def get_variable_name(x): return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1) a = 1 b = a c = b print get_variable_name(a) print get_variable_name(b) print get_variable_name(c)
在python3上,这个函数会得到堆栈中最外层的名字:
import inspect def retrieve_name(var): """ Gets the name of var. Does it from the out most frame inner-wards. :param var: variable to get name from. :return: string """ for fi in reversed(inspect.stack()): names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var] if len(names) > 0: return names[0]
它在代码的任何地方都很有用。 遍历翻转堆栈寻找第一场比赛。
你可以使用easydict
>>> from easydict import EasyDict as edict >>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}}) >>> d.foo 3 >>> d.bar.x 1 >>> d = edict(foo=3) >>> d.foo 3
另一个例子:
>>> d = EasyDict(log=False) >>> d.debug = True >>> d.items() [('debug', True), ('log', False)]
这是我为读取variables名而创build的函数。 这是更一般的,可用于不同的应用程序:
def get_variable_name(*variable): '''gets string of variable name inputs variable (str) returns string ''' if len(variable) != 1: raise Exception('len of variables inputed must be 1') try: return [k for k, v in locals().items() if v is variable[0]][0] except: return [k for k, v in globals().items() if v is variable[0]][0]
要在指定的问题中使用它:
>>> foo = False >>> bar = True >>> my_dict = {get_variable_name(foo):foo, get_variable_name(bar):bar} >>> my_dict {'bar': True, 'foo': False}
>>> a = 1 >>> b = 1 >>> id(a) 34120408 >>> id(b) 34120408 >>> a is b True >>> id(a) == id(b) True
这种方式得到一个可能'a'或'b'的varname。