我想将python变量名转换为等效的字符串,如图所示。有什么想法吗?
var = {}
print ??? # Would like to see 'var'
something_else = 3
print ??? # Would print 'something_else'
答案 0 :(得分:36)
有一种使用场景,您可能需要这样做。我并不是说没有更好的方法或实现相同的功能。
这对于在出现错误时,在调试模式和其他类似情况下“转储”任意字典列表非常有用。
需要什么,与eval()
函数相反:
get_indentifier_name_missing_function()
将标识符名称('variable','dictionary'等)作为参数,并返回a 包含标识符名称的字符串。
考虑以下当前事态:
random_function(argument_data)
如果有人将标识符名称('function','variable','dictionary'等)argument_data
传递给random_function()
(另一个标识符名称),则实际传递一个标识符(例如:<argument_data object at 0xb1ce10>
)到另一个标识符(例如:<function random_function at 0xafff78>
):
<function random_function at 0xafff78>(<argument_data object at 0xb1ce10>)
根据我的理解,只将内存地址传递给函数:
<function at 0xafff78>(<object at 0xb1ce10>)
因此,需要将一个字符串作为参数传递给random_function()
,以使该函数具有参数的标识符名称:
random_function('argument_data')
在random_function()
中def random_function(first_argument):
,可以使用已提供的字符串'argument_data'
来:
提供eval()
函数以获取对实际标识符的引用,因此引用实际数据:
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
不幸的是,这并不适用于所有情况。仅当random_function()
可以将'argument_data'
字符串解析为实际标识符时,它才有效。即如果argument_data
命名空间中有random_function()
标识符名称。
情况并非总是如此:
# main1.py
import some_module1
argument_data = 'my data'
some_module1.random_function('argument_data')
# some_module1.py
def random_function(first_argument):
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
######
预期结果将是:
Currently working on: argument_data
here comes the data: my data
由于argument_data
的名称空间中没有random_function()
标识符名称,因此会产生相反的结果:
Currently working on argument_data
Traceback (most recent call last):
File "~/main1.py", line 6, in <module>
some_module1.random_function('argument_data')
File "~/some_module1.py", line 4, in random_function
some_internal_var = eval(first_argument)
File "<string>", line 1, in <module>
NameError: name 'argument_data' is not defined
现在,考虑get_indentifier_name_missing_function()
的假设用法,其行为如上所述。
这是一个虚拟的Python 3.0代码:。
# main2.py
import some_module2
some_dictionary_1 = { 'definition_1':'text_1',
'definition_2':'text_2',
'etc':'etc.' }
some_other_dictionary_2 = { 'key_3':'value_3',
'key_4':'value_4',
'etc':'etc.' }
#
# more such stuff
#
some_other_dictionary_n = { 'random_n':'random_n',
'etc':'etc.' }
for each_one_of_my_dictionaries in ( some_dictionary_1,
some_other_dictionary_2,
...,
some_other_dictionary_n ):
some_module2.some_function(each_one_of_my_dictionaries)
# some_module2.py
def some_function(a_dictionary_object):
for _key, _value in a_dictionary_object.items():
print( get_indentifier_name_missing_function(a_dictionary_object) +
" " +
str(_key) +
" = " +
str(_value) )
######
预期结果将是:
some_dictionary_1 definition_1 = text_1
some_dictionary_1 definition_2 = text_2
some_dictionary_1 etc = etc.
some_other_dictionary_2 key_3 = value_3
some_other_dictionary_2 key_4 = value_4
some_other_dictionary_2 etc = etc.
......
......
......
some_other_dictionary_n random_n = random_n
some_other_dictionary_n etc = etc.
很遗憾,get_indentifier_name_missing_function()
无法看到“原始”标识符名称(some_dictionary_
,some_other_dictionary_2
,some_other_dictionary_n
)。它只会看到a_dictionary_object
标识符名称。
因此,真正的结果将是:
a_dictionary_object definition_1 = text_1
a_dictionary_object definition_2 = text_2
a_dictionary_object etc = etc.
a_dictionary_object key_3 = value_3
a_dictionary_object key_4 = value_4
a_dictionary_object etc = etc.
......
......
......
a_dictionary_object random_n = random_n
a_dictionary_object etc = etc.
因此,eval()
函数的反向在这种情况下不会那么有用。
目前,人们需要这样做:
# main2.py same as above, except:
for each_one_of_my_dictionaries_names in ( 'some_dictionary_1',
'some_other_dictionary_2',
'...',
'some_other_dictionary_n' ):
some_module2.some_function( { each_one_of_my_dictionaries_names :
eval(each_one_of_my_dictionaries_names) } )
# some_module2.py
def some_function(a_dictionary_name_object_container):
for _dictionary_name, _dictionary_object in a_dictionary_name_object_container.items():
for _key, _value in _dictionary_object.items():
print( str(_dictionary_name) +
" " +
str(_key) +
" = " +
str(_value) )
######
eval()
函数只能将表示标识符名称的字符串引用回实际标识符。eval()
函数的假设反转,在调用代码不直接“看到”标识符名称的情况下不会有用。例如。在任何被调用的函数内。这可以通过同时将'string'
和eval('string')
传递给被调用函数来实现。我认为这是在任意函数,模块,名称空间中解决这个鸡蛋问题的最“通用”方法,而不使用角落案例解决方案。唯一的缺点是使用eval()
函数,这可能很容易导致不安全的代码。必须注意不要为eval()
函数提供任何内容,尤其是未经过滤的外部输入数据。
答案 1 :(得分:9)
这是不可能的。
在Python中,确实没有任何“变量”这样的东西。 Python真正拥有的是“名称”,它们可以绑定对象。它对象可能会绑定哪些名称(如果有的话)没有区别。它可能会绑定几十个不同的名称,或者没有名称。
考虑这个例子:
foo = 1
bar = 1
baz = 1
现在,假设你有一个值为1的整数对象,并且你想要向后工作并找到它的名字。你会打印什么?三个不同的名称将该对象绑定到它们,并且所有这些都同样有效。
在Python中,名称是访问对象的一种方式,因此无法直接使用名称。可能有一些聪明的方法来破解Python字节码或某些东西来获取名称的值,但这最多只是一个客厅技巧。
如果您知道希望print foo
打印"foo"
,那么您最好先执行print "foo"
。
编辑:我稍微改变了措辞,以使其更加清晰。此外,这是一个更好的例子:
foo = 1
bar = foo
baz = foo
实际上,Python为具有公共值(如0或1)的整数重用相同的对象,因此第一个示例应将同一对象绑定到所有三个名称。但是这个例子很清楚:同一个对象被绑定到foo,bar和baz。
答案 2 :(得分:8)
我搜索了这个问题,因为我想要一个Python程序来打印程序中某些变量的赋值语句。例如,它可能会打印“foo = 3,bar = 21,baz = 432”。 print函数需要字符串形式的变量名。我可以用字符串“foo”,“bar”和“baz”提供我的代码,但这感觉就像在重复自己。在阅读了之前的答案后,我开发了以下解决方案。
globals()函数的行为类似于带有变量名称(以字符串形式)作为键的dict。我想从globals()中检索与每个变量的值对应的键。方法globals()。items()返回元组列表;在每个元组中,第一项是变量名(作为字符串),第二项是变量值。我的variablename()函数搜索该列表,以找到与字符串形式所需名称的变量值对应的变量名称。
函数itertools.ifilter()通过使用函数lambda x: var is globals()[x[0]]
测试globals()。items()列表中的每个元组来进行搜索。在那个函数中x是被测试的元组; x [0]是变量名(作为字符串),x [1]是值。 lambda函数测试测试变量的值是否与传递给variablename()的变量的值相同。事实上,通过使用is
运算符,lambda函数测试测试变量的名称是否与传递给variablename()的变量绑定到完全相同的对象。如果是,则元组通过测试并由ifilter()返回。
itertools.ifilter()函数实际上返回一个迭代器,它在正确调用之前不会返回任何结果。为了正确调用它,我把它放在列表理解[tpl[0] for tpl ... globals().items())]
中。列表推导仅保存变量名tpl[0]
,忽略变量值。创建的列表包含一个或多个名称(作为字符串),这些名称绑定到传递给variablename()的变量的值。
在下面显示的variablename()的使用中,所需的字符串作为列表中的元素返回。在许多情况下,它将是列表中唯一的项目。但是,如果为另一个变量名指定了相同的值,则列表将更长。
>>> def variablename(var):
... import itertools
... return [tpl[0] for tpl in
... itertools.ifilter(lambda x: var is x[1], globals().items())]
...
>>> var = {}
>>> variablename(var)
['var']
>>> something_else = 3
>>> variablename(something_else)
['something_else']
>>> yet_another = 3
>>> variablename(something_else)
['yet_another', 'something_else']
答案 3 :(得分:7)
从技术上讲,您可以获得这些信息,但正如其他人所问,您将如何以合理的方式使用它?
>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__',
'x': 52, '__doc__': None, '__package__': None}
这表明变量名在globals()字典中以字符串形式出现。
>>> globals().keys()[2]
'x'
在这种情况下,它恰好是第三个键,但没有可靠的方法来知道给定的变量名称最终会在哪里
>>> for k in globals().keys():
... if not k.startswith("_"):
... print k
...
x
>>>
您可以过滤掉这样的系统变量,但您仍然可以获得所有自己的项目。刚刚运行上面的代码就创建了另一个变量“k”,它改变了dict中“x”的位置。
但也许这对你来说是一个有用的开始。如果您告诉我们您希望使用此功能,可能会提供更多有用的信息。
答案 4 :(得分:4)
只要它是变量而不是第二类,这对我有用:
def print_var_name(variable):
for name in globals():
if eval(name) == variable:
print name
foo = 123
print_var_name(foo)
>>>foo
对于班级成员来说会发生这种情况:
class xyz:
def __init__(self):
pass
member = xyz()
print_var_name(member)
>>>member
这是针对类的(例如):
abc = xyz
print_var_name(abc)
>>>abc
>>>xyz
因此,对于类,它会为您提供名称和属性
答案 5 :(得分:3)
你不得不引用你想要打印名称的变量。所以它看起来像:
print varname(something_else)
没有这样的功能,但如果有这样的话会有点毫无意义。您必须输入something_else
,因此您也可以在其左侧和右侧键入引号以将名称打印为字符串:
print "something_else"
答案 6 :(得分:3)
你想要达到什么目的?绝对没有理由做你所描述的,并且可能有更好的解决方案来解决你想要解决的问题..
您要求的最明显的替代方法是字典。例如:
>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something
主要是作为挑战,我实现了你想要的输出。请不要使用此代码!
#!/usr/bin/env python2.6
class NewLocals:
"""Please don't ever use this code.."""
def __init__(self, initial_locals):
self.prev_locals = list(initial_locals.keys())
def show_new(self, new_locals):
output = ", ".join(list(set(new_locals) - set(self.prev_locals)))
self.prev_locals = list(new_locals.keys())
return output
# Set up
eww = None
eww = NewLocals(locals())
# "Working" requested code
var = {}
print eww.show_new(locals()) # Outputs: var
something_else = 3
print eww.show_new(locals()) # Outputs: something_else
# Further testing
another_variable = 4
and_a_final_one = 5
print eww.show_new(locals()) # Outputs: another_variable, and_a_final_one
答案 7 :(得分:2)
我认为这是一个很酷的解决方案,我想你能得到最好的解决方案。但是你看到有什么方法可以处理这些恶劣的结果,你的功能可能会回归吗? 正如"is" operator behaves unexpectedly with integers所示,低整数和具有相同值的字符串会被python缓存,因此您的variablename-function可能会以极高的概率提供ambigous结果。 在我的例子中,我想创建一个装饰器,它通过我传递的varialbename向类添加一个新变量:
def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency
但是如果你的方法返回了不明确的结果,我怎么知道我添加的变量的名称?
var any_var="myvarcontent"
var myvar="myvarcontent"
@inject(myvar)
class myclasss():
def myclass_method(self):
print self.__myvar #I can not be sure, that this variable will be set...
也许如果我也检查本地列表,我至少可以从列表中删除“依赖” - 变量,但这不是一个可靠的结果。
答案 8 :(得分:2)
这是一个简洁的变体,可让您指定任何目录。 使用目录查找任何内容的问题是多个变量可以具有相同的值。因此,此代码返回可能的变量列表。
def varname( var, dir=locals()):
return [ key for key, val in dir.items() if id( val) == id( var)]
答案 9 :(得分:2)
Django在生成字段名称时不会这样做吗?
http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names
对我来说似乎很合理。
答案 10 :(得分:1)
使用 python-varname 包 (python3) 完全可能:
from varname import nameof
s = 'Hey!'
print (nameof(s))
输出:
s
从这里获取包裹:
答案 11 :(得分:0)
这适用于简单数据类型(str,int,float,list等)
>>> def my_print(var_str) : print var_str+':', globals()[var_str] >>> a = 5 >>> b = ['hello', ',world!'] >>> my_print('a') a: 5 >>> my_print('b') b: ['hello', ',world!']
答案 12 :(得分:0)
不是很像Python,但是我很好奇,发现了这个解决方案。您需要复制globals词典,因为一旦定义新变量,它的大小就会改变。
def var_to_name(var):
# noinspection PyTypeChecker
dict_vars = dict(globals().items())
var_string = None
for name in dict_vars.keys():
if dict_vars[name] is var:
var_string = name
break
return var_string
if __name__ == "__main__":
test = 3
print(f"test = {test}")
print(f"variable name: {var_to_name(test)}")
返回:
test = 3
variable name: test
答案 13 :(得分:0)
使用拆箱操作符:
>>> def tostr(**kwargs):
return kwargs
>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}
答案 14 :(得分:0)
我不知道对与错,但是对我有用
def varname(variable):
names = []
for name in list(globals().keys()):
string = f'id({name})'
if id(variable) == eval(string):
names.append(name)
return names[0]
答案 15 :(得分:0)
以字符串形式获取var
的变量名:
var = 1000
var_name = [k for k,v in locals().items() if v == var][0]
print(var_name) # ---> outputs 'var'
答案 16 :(得分:0)
我想指出一个用例,它不是反模式,并且没有更好的方法来做到这一点。
这似乎是 Python 中缺失的功能。
有许多函数,例如 patch.object
,它们采用要修补或访问的方法或属性的名称。
考虑一下:
patch.object(obj, "method_name", new_reg)
当您更改方法名称时,这可能会导致“错误成功”。 IE:你可以发布一个错误,你以为你在测试......只是因为一个糟糕的方法名称重构。
现在考虑:varname
。这可能是一个高效的内置函数。但是现在它可以通过迭代一个对象或调用者的框架来工作:
现在您的电话可以是:
patch.member(obj, obj.method_name, new_reg)
并且补丁函数可以调用:
varname(var, obj=obj)
这将:断言 var 绑定到 obj 并返回成员的名称。或者,如果未指定 obj,则使用调用方堆栈帧来派生它,等等。
在某些时候可以成为一个高效的内置工具,但这里有一个有效的定义。我故意不支持内置,容易添加:
随意将其粘贴在名为 varname.py
的包中,并在您的 patch.object 调用中使用它:
patch.object(obj, varname(obj, obj.method_name), new_reg)
注意:这是为 python 3 编写的。
import inspect
def _varname_dict(var, dct):
key_name = None
for key, val in dct.items():
if val is var:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def _varname_obj(var, obj):
key_name = None
for key in dir(obj):
val = getattr(obj, key)
equal = val is var
if equal:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def varname(var, obj=None):
if obj is None:
if hasattr(var, "__self__"):
return var.__name__
caller_frame = inspect.currentframe().f_back
try:
ret = _varname_dict(var, caller_frame.f_locals)
except NameError:
ret = _varname_dict(var, caller_frame.f_globals)
else:
ret = _varname_obj(var, obj)
if ret is None:
raise NameError("Name not found. (Note: builtins not supported)")
return ret
答案 17 :(得分:-1)
print "var"
print "something_else"
或者你的意思是something_else?
答案 18 :(得分:-1)
此模块用于将变量名称转换为字符串: https://pypi.org/project/varname/
像这样使用它:
from varname import nameof
变量=0
name=nameof(variable)
打印(名称)
//输出:变量
安装方式:
pip install varname