将变量名称转换为字符串?

Bra*_*rey 57 python string variables

我想将python变量名转换为等效的字符串,如图所示.有什么想法?

var = {}
print ???  # Would like to see 'var'
something_else = 3
print ???  # Would print 'something_else'
Run Code Online (Sandbox Code Playgroud)

Pet*_*ria 39

有一种使用场景,您可能需要这样做.我并不是说没有更好的方法或实现相同的功能.

这对于在出错,在调试模式和其他类似情况下"转储"任意字典列表非常有用.

需要的是eval()功能的反面:

get_indentifier_name_missing_function()
Run Code Online (Sandbox Code Playgroud)

它将标识符名称('variable','dictionary'等)作为参数,并返回包含标识符名称的字符串.


考虑以下当前的事态:

random_function(argument_data)
Run Code Online (Sandbox Code Playgroud)

如果将标识符名称('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>)
Run Code Online (Sandbox Code Playgroud)

根据我的理解,只有内存地址传递给函数:

<function at 0xafff78>(<object at 0xb1ce10>)
Run Code Online (Sandbox Code Playgroud)

因此,需要传递一个字符串作为参数random_function(),以使该函数具有参数的标识符名称:

random_function('argument_data')
Run Code Online (Sandbox Code Playgroud)

在random_function()里面

def random_function(first_argument):
Run Code Online (Sandbox Code Playgroud)

,人们会使用已经提供的字符串'argument_data':

  1. 作为'标识符名称'(显示,记录,字符串拆分/连接,等等)
  2. 提供eval()函数以获得对实际标识符的引用,因此,引用实际数据:

    print("Currently working on", first_argument)
    some_internal_var = eval(first_argument)
    print("here comes the data: " + str(some_internal_var))
    
    Run Code Online (Sandbox Code Playgroud)

不幸的是,这并不适用于所有情况.它只有在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))
######
Run Code Online (Sandbox Code Playgroud)

预期结果将是:

Currently working on: argument_data
here comes the data: my data
Run Code Online (Sandbox Code Playgroud)

因为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
Run Code Online (Sandbox Code Playgroud)

现在,考虑一下如上所述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) )
######
Run Code Online (Sandbox Code Playgroud)

预期结果将是:

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.
Run Code Online (Sandbox Code Playgroud)

不幸的是,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.
Run Code Online (Sandbox Code Playgroud)

因此,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) )
    ######
Run Code Online (Sandbox Code Playgroud)

结论:

  • Python仅将内存地址作为函数的参数传递.
  • eval()如果名称标识符在当前名称空间中可用,则表示标识符名称的字符串只能由函数引用回实际标识符.
  • 如果eval()标识符名称没有被调用代码直接"看到" ,则函数的假设反转将不会有用.例如在任何被调用的函数内
  • 目前需要传递给一个函数:
    1. 表示标识符名称的字符串
    2. 实际标识符(内存地址)

这可以通过同时传递'string'eval('string')调用函数来实现.我认为这是在任意函数,模块,名称空间中解决这个鸡蛋问题的最"通用"方法,而不使用角落案例解决方案.唯一的缺点是使用该eval()功能可能很容易导致不安全的代码.必须注意不要eval()用几乎任何东西来提供功能,特别是未经过滤的外部输入数据.

  • 如果要获取对象的名称,我们需要在 StackOverflow 上找到 5 页的答案,那么 Python 中就有些不对劲了。:/ (9认同)
  • TLDR 指出不可能实现 OP 所要求的目标。然而,@Alice 的答案和其他类似的答案建议使用 locals() 或 globals() 来实现这一目标。所以这个 TLDR 具有误导性,这不应该是公认的答案。 (6认同)
  • 这是一篇出色的文章,也是我来到这里的高质量内容。 (5认同)
  • TL;博士会很好。 (3认同)

Ali*_*ice 11

只要它是一个变量而不是第二个类,这对我有用:

def print_var_name(variable):
 for name in globals():
     if eval(name) == variable:
        print name
foo = 123
print_var_name(foo)
>>>foo
Run Code Online (Sandbox Code Playgroud)

这发生在班级成员身上:

class xyz:
     def __init__(self):
         pass
member = xyz()
print_var_name(member)
>>>member
Run Code Online (Sandbox Code Playgroud)

这对于类(例如):

abc = xyz
print_var_name(abc)
>>>abc
>>>xyz
Run Code Online (Sandbox Code Playgroud)

因此,对于类,它为您提供名称和属性

  • 阅读回答问题的帖子而无需抱怨为什么要问这个问题的帖子真的很高兴。 (9认同)
  • 请注意,可以将相同的值绑定到多个名称。在这种情况下,上面的代码将打印多个名称。没有办法知道哪个名字是“正确”的。 (2认同)

小智 10

我搜索了这个问题,因为我想要一个Python程序来打印程序中某些变量的赋值语句.例如,它可能会打印"foo = 3,bar = 21,baz = 432".print函数需要字符串形式的变量名.我可以用字符串"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']
Run Code Online (Sandbox Code Playgroud)


ste*_*eha 8

这是不可能的.

在Python中,确实没有任何"变量"这样的东西.Python真正拥有的是"名称",它们可以绑定对象.它对象可能会绑定哪些名称(如果有的话)没有区别.它可能会绑定几十个不同的名称,或者没有.

考虑这个例子:

foo = 1
bar = 1
baz = 1
Run Code Online (Sandbox Code Playgroud)

现在,假设您有一个值为1的整数对象,并且您想要向后工作并找到它的名称.你会打印什么?三个不同的名称将该对象绑定到它们,并且所有这些都同样有效.

在Python中,名称是访问对象的一种方式,因此无法直接使用名称.可能有一些聪明的方法来破解Python字节码或某些东西来获取名称的值,但这最多只是一个客厅技巧.

如果您知道要print foo打印"foo",那么您最好print "foo"先执行.

编辑:我稍微改变了措辞,使其更加清晰.此外,这是一个更好的例子:

foo = 1
bar = foo
baz = foo
Run Code Online (Sandbox Code Playgroud)

在实践中,Python为具有常见值(如0或1)的整数重用相同的对象,因此第一个示例应将同一对象绑定到所有三个名称.但是这个例子很清楚:同一个对象被绑定到foo,bar和baz.

  • 对象没有名称,名称有对象 (3认同)

Tod*_*odd 7

从技术上讲,这些信息可供您使用,但正如其他人所问,您将如何以合理的方式使用它?

>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 
'x': 52, '__doc__': None, '__package__': None}
Run Code Online (Sandbox Code Playgroud)

这表明变量名在globals()字典中以字符串形式出现.

>>> globals().keys()[2]
'x'
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它碰巧是第三个键,但没有可靠的方法来知道给定变量名称的最终位置

>>> for k in globals().keys():
...   if not k.startswith("_"):
...     print k
...
x
>>>
Run Code Online (Sandbox Code Playgroud)

您可以过滤掉这样的系统变量,但您仍然可以获得所有自己的项目.刚刚运行上面的代码创建了另一个变量"k",它改变了dict中"x"的位置.

但也许这对你来说是一个有用的开始.如果您告诉我们您希望使用此功能,可能会提供更多有用的信息.

  • 克里斯,你的评论似乎与我的答案或原始问题无关.你是谁在责骂?为什么?你不知道他是在编写生产代码还是只是为自己的教育试验语言功能. (2认同)

Syn*_*ase 6

完全可以使用 python-varname 包(python3):

from varname import nameof

s = 'Hey!'

print (nameof(s))
Run Code Online (Sandbox Code Playgroud)

输出:

s
Run Code Online (Sandbox Code Playgroud)

在这里获取包裹:

https://github.com/pwwang/python-varname