我想将python变量名称转换为等效的字符串,如图所示。有什么想法吗?
var = {}
print ??? # Would like to see 'var'
something_else = 3
print ??? # Would print 'something_else'
我想将python变量名称转换为等效的字符串,如图所示。有什么想法吗?
var = {}
print ??? # Would like to see 'var'
something_else = 3
print ??? # Would print 'something_else'
Answers:
在一个使用场景中,您可能需要此场景。我并不是在暗示没有更好的方法或实现相同的功能。
为了在调试,模式和其他类似情况下出现错误时“转储”任意词典列表,这将很有用。
需要的是该eval()
功能的反向功能:
get_indentifier_name_missing_function()
它将以标识符名称(“变量”,“字典”等)作为参数,并返回包含标识符名称的字符串。
考虑以下当前状态:
random_function(argument_data)
如果将一个标识符名称(“函数”,“变量”,“字典”等)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
现在,考虑a的假设用法,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()
函数提供几乎任何东西,尤其是未经过滤的外部输入数据。
我搜索此问题是因为我想要一个Python程序来打印程序中某些变量的赋值语句。例如,它可能会显示“ foo = 3,bar = 21,baz = 432”。打印功能将需要字符串形式的变量名。我本可以为代码提供字符串“ foo”,“ bar”和“ baz”,但这就像在重复自己。阅读之前的答案后,我在下面开发了解决方案。
globals()函数的行为类似于以变量名(以字符串形式)作为键的dict。我想从globals()中检索与每个变量的值相对应的键。globals()。items()方法返回一个元组列表;在每个元组中,第一项是变量名(作为字符串),第二项是变量值。我的variablename()函数在该列表中进行搜索,以找到与变量名的值相对应的变量名,我需要使用字符串形式的名称。
itertools.ifilter()函数通过使用函数测试globals()。items()列表中的每个元组来进行搜索lambda x: var is globals()[x[0]]
。在该函数中,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']
只要它是一个变量而不是第二类,这对我有用:
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
因此,对于班级,它会为您提供名称和属性
从技术上讲,您可以使用这些信息,但是正如其他人所问的那样,您将如何以明智的方式利用它?
>>> 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”,该变量改变了“ x”在字典中的位置。
但这也许对您来说是一个有用的开始。如果您告诉我们您希望此功能做什么,则可能会提供更多有用的信息。
这不可能。
在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。
foo
bar
,baz
所有示例都包含在内1
。那……的“名字”是1
什么?如果查看所有全局变量,则可以返回变量名列表:(['foo', 'bar', 'baz']
以某种随机顺序)。好的。该列表的用途是什么?名称之一是“真”名称1
吗?(不。)我们中那些不可能说“它”的人都同意,您可以浏览全局变量并找到所有名称。我们只是认为这不是一件有用的事情。就像我说的:一个对象“可能绑定到数十个不同的名称,或者没有。”
您想达到什么目的?绝对没有理由去做您描述的事情,而且对于您要解决的问题,可能有更好的解决方案。
您所要求的最明显的替代方法是词典。例如:
>>> 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
Django在生成字段名称时不这样做吗?
http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names
对我来说似乎合理。
我认为这是一个不错的解决方案,我想您将获得最好的解决方案。但是,您是否看到任何处理歧义结果的方法,您的函数可能会返回?由于“ is”运算符在整数显示中表现异常,低整数和相同值的字符串将被python缓存,因此您的variablename-function可能会以很高的可能性优先处理大量结果。就我而言,我想创建一个装饰器,该装饰器通过我通过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...
也许如果我还要检查本地列表,我至少可以从列表中删除“ dependency” -Variable,但这将不是一个可靠的结果。
它不是很像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
globals
字典。在之前的答案中已经完成了此操作,而没有创建额外的变量并使用itertools
。尽管答案是好的,但我认为由于提供了类似的解决方案,因此您应该对此表示反对,并避免重复。