Python 创建独立变量字典的更简单方法?
我希望能够以字符串的形式获取变量的名称,但我不知道Python是否有那么多的内省功能。比如:Python 创建独立变量字典的更简单方法?,python,string,variables,Python,String,Variables,我希望能够以字符串的形式获取变量的名称,但我不知道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} 但我想
>>> 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()
,所以我想有一种方法。这在Python中是不可能的,因为Python实际上没有“变量”。Python有名称,同一个对象可以有多个名称。大多数对象没有uu name_u属性。(类、函数和模块都有;还有其他内置类型吗?)
除了print(“my\u var”)
之外,您对print(“my\u var”)
还有什么期望?你能直接使用字符串吗
你可以“切”一条口述:
或者:
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)
正如unwind所说,这并不是在Python中真正要做的事情——变量实际上是到对象的名称映射 但是,有一种方法可以尝试这样做:
>>> 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'
这是一个黑客。它不适用于所有Python实现发行版(特别是那些没有
回溯.extract_stack
的发行版)
请注意,此黑客很脆弱:
make_dict(bar,
foo)
(在两行上调用make_dict)将不起作用
不要试图从值foo
和条
中生成dict,
从字符串变量名'foo'
和'bar'
中生成dict将更具python风格:
dict([(name,locals()[name]) for name in ('foo','bar')])
你想这么做吗
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}
我一直很想这样做。这一黑客行为与rlotun的建议非常相似,但它只是一句话,这对我来说很重要:
blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]
Python 3+
blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]
在读线的时候,我看到了很大的摩擦。这是很容易给的 一个糟糕的答案,然后让别人给出正确的答案。不管怎样,这是我发现的 发件人:[effbot.org]() 名称有点不同——它们不是对象的真正属性,对象本身也不知道它叫什么 一个对象可以有任意数量的名称,也可以根本没有名称 名称存在于名称空间中(例如模块名称空间、实例名称空间、函数的本地名称空间) 注意:它说对象本身不知道它叫什么,所以这就是线索。Python对象不是自引用的。然后它说,名称存在于名称空间中。我们在TCL/TK中有这个。所以也许我的回答会有帮助(但它确实帮助了我) jj=123 打印评估(“”+str(id(jj))+“”) 打印目录() 166707048 [“内置”、“文档”、“文件”、“名称”、“包”、“jj”] 所以在列表的末尾有“jj”。 将代码重写为: jj=123 打印评估(“”+str(id(jj))+“”) 对于dir()中的x: 打印id(eval(x)) 161922920 [“内置”、“文档”、“文件”、“名称”、“包”、“jj”] 3077447796 136515736 3077408320 3077656800 136515736 161922920 这个讨厌的代码id是变量/对象/你学究们怎么称呼它的名字 就这样。当我们直接查找“jj”时,它的内存地址与在全局名称空间中查找字典时相同。我相信你可以做一个函数来做这个。只需记住变量/object/wyci所在的名称空间
QED.好吧,几天前我遇到了同样的需求,必须得到一个变量名,它指向对象本身 为什么这么必要? 简而言之,我正在为Maya构建一个插件。核心插件是用C++构建的,但是GUI是通过Python绘制的(因为它不是处理器密集型的)。由于我目前还不知道如何从插件返回多个值,除了默认的
MStatus
,因此要用Python更新字典,我必须传递变量名,指向实现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
中,这不是一个完美的解决方案。许多键可能指向同一个对象,例如:
而且这种方法不是线程安全的。如果我错了,请纠正我
至少这种方法解决了我的问题,它获得了全局范围内指向对象本身的任何变量的名称,并将其作为参数传递给插件,供其内部使用
我在
int
(基本整数类)上尝试了这个方法,但问题是这些基本类没有被绕过(如果错误,请更正使用的技术术语)。您可以重新实现int
,然后执行int=foo
,但是a=3
将永远不是foo
的对象,而是原语的对象。要克服这一问题,您必须a=foo(3)
才能使a.name()
正常工作。对于python 2.7和更新版本,还有字典理解功能,这使它变得更短。如果可能的话,我会使用getattr代替eval(eval是邪恶的),就像上面的答案一样。Self可以是任何一个对象,它具有你所看到的上下文。它可以是一个对象或locals=locals()等
我认为我的问题将有助于说明为什么这个问题是有用的,它可能会让我们更深入地了解如何回答这个问题。我编写了一个小函数来对代码中的各种变量进行快速内联头检查。基本上,它列出了变量名、数据类型、大小和其他属性,因此我可以快速发现我犯的任何错误。代码很简单:
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)))
因此,如果您有一些复杂的字典/列表/元组情况,则可能会退出
jj = 123
print eval("'" + str(id(jj)) + "'")
print dir()
166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
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
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
{name: getattr(self, name) for name in ['some', 'vars', 'here]}
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)))
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'>
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'
__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 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}
myVariable = 5
for v in locals():
if id(v) == id("myVariable"):
print(v, locals()[v])
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
>>> 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)]
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]
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)
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True
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}
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
>>|
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"
def get_var_name(**kwargs):
"""get variable name
get_var_name(var = var)
Returns:
[str] -- var name
"""
return list(kwargs.keys())[0]
from sorcery import dict_of
my_dict = dict_of(foo, bar)
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}