简体   繁体   English

将变量名转换为字符串?

[英]Convert Variable Name to String?

I would like to convert a python variable name into the string equivalent as shown.我想将 python 变量名转换为所示的等效字符串。 Any ideas how?任何想法如何?

var = {}
print ???  # Would like to see 'var'
something_else = 3
print ???  # Would print 'something_else'

TL;DR: Not possible. TL;DR:不可能。 See 'conclusion' at the end.见最后的“结论”。


There is an usage scenario where you might need this.有一个使用场景,您可能需要它。 I'm not implying there are not better ways or achieving the same functionality.我并不是暗示没有更好的方法或实现相同的功能。

This would be useful in order to 'dump' an arbitrary list of dictionaries in case of error, in debug modes and other similar situations.这对于在出现错误、调试模式和其他类似情况下“转储”任意字典列表非常有用。

What would be needed, is the reverse of the eval() function:需要的是eval()函数的反向:

get_indentifier_name_missing_function()

which would take an identifier name ('variable','dictionary',etc) as an argument, and return a string containing the identifier's name.它将采用标识符名称('variable'、'dictionary' 等)作为参数,并返回一个包含标识符名称的字符串。


Consider the following current state of affairs:考虑以下当前的事态:

random_function(argument_data)

If one is passing an identifier name ('function','variable','dictionary',etc) argument_data to a random_function() (another identifier name), one actually passes an identifier (eg: <argument_data object at 0xb1ce10> ) to another identifier (eg: <function random_function at 0xafff78> ):如果将标识符名称('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>)

From my understanding, only the memory address is passed to the function:根据我的理解,只有内存地址被传递给函数:

<function at 0xafff78>(<object at 0xb1ce10>)

Therefore, one would need to pass a string as an argument to random_function() in order for that function to have the argument's identifier name:因此,需要将字符串作为参数传递给random_function()以便该函数具有参数的标识符名称:

random_function('argument_data')

Inside the random_function()在 random_function() 内部

def random_function(first_argument):

, one would use the already supplied string 'argument_data' to: ,可以使用已经提供的字符串'argument_data'来:

  1. serve as an 'identifier name' (to display, log, string split/concat, whatever)用作“标识符名称”(显示、记录、字符串拆分/连接等)

  2. feed the eval() function in order to get a reference to the actual identifier, and therefore, a reference to the real data:提供eval()函数以获得对实际标识符的引用,因此,对真实数据的引用:

     print("Currently working on", first_argument) some_internal_var = eval(first_argument) print("here comes the data: " + str(some_internal_var))

Unfortunately, this doesn't work in all cases.不幸的是,这并不适用于所有情况。 It only works if the random_function() can resolve the 'argument_data' string to an actual identifier.它仅在random_function()可以将'argument_data'字符串解析为实际标识符时才有效。 Ie If argument_data identifier name is available in the random_function() 's namespace.即,如果argument_data标识符名称在random_function()的命名空间中可用。

This isn't always the case:情况并非总是如此:

# 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))
######

Expected results would be:预期结果是:

Currently working on: argument_data
here comes the data: my data

Because argument_data identifier name is not available in the random_function() 's namespace, this would yield instead:因为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

Now, consider the hypotetical usage of a get_indentifier_name_missing_function() which would behave as described above.现在,考虑一下 get_indentifier_name_missing_function get_indentifier_name_missing_function()的假设用法,它的行为如上所述。

Here's a dummy Python 3.0 code: .这是一个虚拟的 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) )
######

Expected results would be:预期结果是:

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.

Unfortunately, get_indentifier_name_missing_function() would not see the 'original' identifier names ( some_dictionary_ , some_other_dictionary_2 , some_other_dictionary_n ).不幸的是, get_indentifier_name_missing_function()不会看到“原始”标识符名称( some_dictionary_some_other_dictionary_2some_other_dictionary_n )。 It would only see the a_dictionary_object identifier name.它只会看到a_dictionary_object标识符名称。

Therefore the real result would rather be:因此,真正的结果宁愿是:

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.

So, the reverse of the eval() function won't be that useful in this case.因此,在这种情况下,反向使用eval()函数不会那么有用。


Currently, one would need to do this:目前,人们需要这样做:

# 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) )
    ######

In conclusion:综上所述:

  • Python passes only memory addresses as arguments to functions. Python 仅将内存地址作为参数传递给函数。
  • Strings representing the name of an identifier, can only be referenced back to the actual identifier by the eval() function if the name identifier is available in the current namespace.如果名称标识符在当前命名空间中可用,则表示标识符名称的字符串只能被eval()函数引用回实际标识符。
  • A hypothetical reverse of the eval() function, would not be useful in cases where the identifier name is not 'seen' directly by the calling code.在调用代码不能直接“看到”标识符名称的情况下, eval()函数的假设反转将没有用。 Eg inside any called function.例如在任何被调用的函数中。
  • Currently one needs to pass to a function:目前需要传递给一个函数:
    1. the string representing the identifier name表示标识符名称的字符串
    2. the actual identifier (memory address)实际标识符(内存地址)

This can be achieved by passing both the 'string' and eval('string') to the called function at the same time.这可以通过同时将'string'eval('string')传递给被调用函数来实现。 I think this is the most 'general' way of solving this egg-chicken problem across arbitrary functions, modules, namespaces, without using corner-case solutions.我认为这是在不使用极端情况解决方案的情况下跨任意函数、模块、命名空间解决这个蛋鸡问题的最“通用”方法。 The only downside is the use of the eval() function which may easily lead to unsecured code.唯一的缺点是使用eval()函数可能很容易导致不安全的代码。 Care must be taken to not feed the eval() function with just about anything, especially unfiltered external-input data.必须注意不要向eval()函数提供任何东西,尤其是未过滤的外部输入数据。

I searched for this question because I wanted a Python program to print assignment statements for some of the variables in the program.我搜索这个问题是因为我想要一个 Python 程序来打印程序中某些变量的赋值语句。 For example, it might print "foo = 3, bar = 21, baz = 432".例如,它可能会打印“foo = 3, bar = 21, baz = 432”。 The print function would need the variable names in string form.打印函数需要字符串形式的变量名。 I could have provided my code with the strings "foo","bar", and "baz", but that felt like repeating myself.我本可以为我的代码提供字符串“foo”、“bar”和“baz”,但这感觉就像是在重复我自己。 After reading the previous answers, I developed the solution below.在阅读了之前的答案后,我开发了以下解决方案。

The globals() function behaves like a dict with variable names (in the form of strings) as keys. globals() 函数的行为就像一个以变量名(以字符串的形式)作为键的字典。 I wanted to retrieve from globals() the key corresponding to the value of each variable.我想从 globals() 检索与每个变量的值对应的键。 The method globals().items() returns a list of tuples; globals().items() 方法返回一个元组列表; in each tuple the first item is the variable name (as a string) and the second is the variable value.在每个元组中,第一项是变量名称(作为字符串),第二项是变量值。 My variablename() function searches through that list to find the variable name(s) that corresponds to the value of the variable whose name I need in string form.我的 variablename() 函数搜索该列表以查找与我需要的字符串形式的名称的变量值对应的变量名称。

The function itertools.ifilter() does the search by testing each tuple in the globals().items() list with the function lambda x: var is globals()[x[0]] .函数 itertools.ifilter() 通过使用函数lambda x: var is globals()[x[0]]测试 globals().items() 列表中的每个元组来进行搜索。 In that function x is the tuple being tested;在该函数中 x 是被测试的元组; x[0] is the variable name (as a string) and x[1] is the value. x[0] 是变量名(作为字符串),x[1] 是值。 The lambda function tests whether the value of the tested variable is the same as the value of the variable passed to variablename(). lambda 函数测试被测试变量的值是否与传递给 variablename() 的变量值相同。 In fact, by using the is operator, the lambda function tests whether the name of the tested variable is bound to the exact same object as the variable passed to variablename().事实上,通过使用is运算符,lambda 函数测试被测试变量的名称是否与传递给 variablename() 的变量绑定到完全相同的对象。 If so, the tuple passes the test and is returned by ifilter().如果是,则元组通过测试并由 ifilter() 返回。

The itertools.ifilter() function actually returns an iterator which doesn't return any results until it is called properly. itertools.ifilter() 函数实际上返回一个迭代器,它在被正确调用之前不会返回任何结果。 To get it called properly, I put it inside a list comprehension [tpl[0] for tpl ... globals().items())] .为了正确调用它,我将它放在列表[tpl[0] for tpl ... globals().items())] The list comprehension saves only the variable name tpl[0] , ignoring the variable value.列表推导式只保存变量名tpl[0] ,忽略变量值。 The list that is created contains one or more names (as strings) that are bound to the value of the variable passed to variablename().创建的列表包含一个或多个名称(作为字符串),这些名称绑定到传递给 variablename() 的变量值。

In the uses of variablename() shown below, the desired string is returned as an element in a list.在下面显示的 variablename() 的使用中,所需的字符串作为列表中的元素返回。 In many cases, it will be the only item in the list.在许多情况下,它将是列表中的唯一项目。 If another variable name is assigned the same value, however, the list will be longer.但是,如果为另一个变量名称分配了相同的值,则列表会更长。

>>> 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']

as long as it's a variable and not a second class, this here works for me:只要它是一个变量而不是第二个类,这对我有用:

def print_var_name(variable):
 for name in globals():
     if eval(name) == variable:
        print name
foo = 123
print_var_name(foo)
>>>foo

this happens for class members:这发生在班级成员身上:

class xyz:
     def __init__(self):
         pass
member = xyz()
print_var_name(member)
>>>member

ans this for classes (as example):类的答案(例如):

abc = xyz
print_var_name(abc)
>>>abc
>>>xyz

So for classes it gives you the name AND the properteries因此,对于类,它为您提供名称和属性

This is not possible.这不可能。

In Python, there really isn't any such thing as a "variable".在 Python 中,真的没有任何“变量”这样的东西。 What Python really has are "names" which can have objects bound to them. Python 真正拥有的是可以绑定对象的“名称”。 It makes no difference to the object what names, if any, it might be bound to.对象的名称(如果有)可能绑定到什么名称没有任何区别。 It might be bound to dozens of different names, or none.它可能绑定到几十个不同的名称,或者一个都没有。

Consider this example:考虑这个例子:

foo = 1
bar = 1
baz = 1

Now, suppose you have the integer object with value 1, and you want to work backwards and find its name.现在,假设您有一个值为 1 的整数对象,并且您想逆向工作并找到它的名称。 What would you print?你会打印什么? Three different names have that object bound to them, and all are equally valid.三个不同的名称都绑定了该对象,并且都同样有效。

In Python, a name is a way to access an object, so there is no way to work with names directly.在 Python 中,名称是访问对象的一种方式,因此无法直接使用名称。 There might be some clever way to hack the Python bytecodes or something to get the value of the name, but that is at best a parlor trick.可能有一些聪明的方法来破解 Python 字节码或其他东西来获取名称的值,但这充其量只是一个客厅技巧。

If you know you want print foo to print "foo" , you might as well just execute print "foo" in the first place.如果你知道你想让print foo打印"foo" ,你不妨首先执行print "foo"

EDIT: I have changed the wording slightly to make this more clear.编辑:我稍微改变了措辞以使其更清楚。 Also, here is an even better example:此外,这里还有一个更好的例子:

foo = 1
bar = foo
baz = foo

In practice, Python reuses the same object for integers with common values like 0 or 1, so the first example should bind the same object to all three names.实际上,Python 对具有 0 或 1 等常见值的整数重用相同的对象,因此第一个示例应该将相同的对象绑定到所有三个名称。 But this example is crystal clear: the same object is bound to foo, bar, and baz.但是这个例子非常清楚:同一个对象绑定到 foo、bar 和 baz。

Technically the information is available to you, but as others have asked, how would you make use of it in a sensible way?从技术上讲,您可以使用这些信息,但正如其他人所问的那样,您将如何以合理的方式使用它?

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

This shows that the variable name is present as a string in the globals() dictionary.这表明变量名称在 globals() 字典中以字符串形式存在。

>>> globals().keys()[2]
'x'

In this case it happens to be the third key, but there's no reliable way to know where a given variable name will end up在这种情况下,它恰好是第三个键,但没有可靠的方法来知道给定的变量名将在哪里结束

>>> for k in globals().keys():
...   if not k.startswith("_"):
...     print k
...
x
>>>

You could filter out system variables like this, but you're still going to get all of your own items.你可以像这样过滤掉系统变量,但你仍然会得到你自己的所有项目。 Just running that code above created another variable "k" that changed the position of "x" in the dict.只是运行上面的代码创建了另一个变量“k”,它改变了字典中“x”的位置。

But maybe this is a useful start for you.但也许这对你来说是一个有用的开始。 If you tell us what you want this capability for, more helpful information could possibly be given.如果您告诉我们您想要此功能的用途,则可能会提供更多有用的信息。

Totally possible with the python-varname package (python3):完全可以使用 python-varname 包(python3):

from varname import nameof

s = 'Hey!'

print (nameof(s))

Output:输出:

s

Get the package here:在这里获取包裹:

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

I think this is a cool solution and I suppose the best you can get.我认为这是一个很酷的解决方案,我想你能得到最好的。 But do you see any way to handle the ambigious results, your function may return?但是你有没有办法处理模棱两可的结果,你的函数可能会返回? As "is" operator behaves unexpectedly with integers shows, low integers and strings of the same value get cached by python so that your variablename-function might priovide ambigous results with a high probability.由于“is”运算符对整数的表现出乎意料, python 会缓存低整数和相同值的字符串,因此您的变量名函数可能会以很高的概率提供不明确的结果。 In my case, I would like to create a decorator, that adds a new variable to a class by the varialbename i pass it:就我而言,我想创建一个装饰器,它通过我传递的 varialbename 向类添加一个新变量:

def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency

But if your method returns ambigous results, how can I know the name of the variable I added?但是如果你的方法返回不明确的结果,我怎么知道我添加的变量的名称?

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...

Maybe if I will also check the local list I could at least remove the "dependency"-Variable from the list, but this will not be a reliable result.也许如果我还要检查本地列表,我至少可以从列表中删除“依赖”变量,但这不会是一个可靠的结果。

You somehow have to refer to the variable you want to print the name of.您必须以某种方式引用要打印名称的变量。 So it would look like:所以它看起来像:

print varname(something_else)

There is no such function, but if there were it would be kind of pointless.没有这样的功能,但如果有它就毫无意义了。 You have to type out something_else , so you can as well just type quotes to the left and right of it to print the name as a string:你必须输入something_else ,所以你也可以在它的左边和右边输入引号以将名称打印为字符串:

print "something_else"

What are you trying to achieve?你想达到什么目的? There is absolutely no reason to ever do what you describe, and there is likely a much better solution to the problem you're trying to solve..绝对没有理由做你描述的事情,而且你试图解决的问题可能有更好的解决方案。

The most obvious alternative to what you request is a dictionary.您请求的最明显的替代方法是字典。 For example:例如:

>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something

Mostly as a.. challenge, I implemented your desired output.主要是作为一个......挑战,我实现了你想要的输出。 Do not use this code, please!请不要使用此代码!

#!/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

Here is a succinct variation that lets you specify any directory.这是一个简洁的变体,可让您指定任何目录。 The issue with using directories to find anything is that multiple variables can have the same value.使用目录查找任何内容的问题在于多个变量可以具有相同的值。 So this code returns a list of possible variables.所以这段代码返回一个可能变量的列表。

def varname( var, dir=locals()):
  return [ key for key, val in dir.items() if id( val) == id( var)]

Does Django not do this when generating field names? Django 在生成字段名称时不这样做吗?

http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names

Seems reasonable to me.对我来说似乎很合理。

it is possible to a limited extent.在有限的范围内是可能的。 the answer is similar to the solution by @tamtam .答案类似于@tamtam 的解决方案。 The given example assumes the following assumptions -给定的示例假设以下假设 -

  • You are searching for a variable by its value您正在按其值搜索变量
  • The variable has a distinct value该变量具有不同的值
  • The value is in the global namespace该值在全局命名空间中

Example:例子:

testVar         = "unique value"
varNameAsString = [k for k,v in globals().items() if v == "unique value"]
#
# the variable "varNameAsString" will contain all the variable name that matches
# the value "unique value"
# for this example, it will be a list of a single entry "testVar"
#
print(varNameAsString)

Output : ['testVar']输出:['testVar']

You can extend this example for any other variable/data type您可以将此示例扩展为任何其他变量/数据类型

By using the the unpacking operator :通过使用解包运算符

>>> def tostr(**kwargs):
    return kwargs

>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}

I don't know it's right or not, but it worked for me我不知道这对不对,但对我有用

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]  

I'd like to point out a use case for this that is not an anti-pattern, and there is no better way to do it.我想指出一个不是反模式的用例,并且没有更好的方法来做到这一点。

This seems to be a missing feature in python.这似乎是 python 中缺少的功能。

There are a number of functions, like patch.object , that take the name of a method or property to be patched or accessed.有许多函数,例如patch.object ,它们采用要修补或访问的方法或属性的名称。

Consider this:考虑一下:

patch.object(obj, "method_name", new_reg)

This can potentially start "false succeeding" when you change the name of a method.当您更改方法的名称时,这可能会开始“错误成功”。 IE: you can ship a bug, you thought you were testing.... simply because of a bad method name refactor. IE:你可以发布一个错误,你以为你在测试......只是因为一个糟糕的方法名称重构。

Now consider: varname .现在考虑: varname This could be an efficient, built-in function.这可能是一个高效的内置函数。 But for now it can work by iterating an object or the caller's frame:但是现在它可以通过迭代一个对象或调用者的框架来工作:

Now your call can be:现在你的电话可以是:

patch.member(obj, obj.method_name, new_reg)

And the patch function can call:而补丁函数可以调用:

varname(var, obj=obj)

This would: assert that the var is bound to the obj and return the name of the member.这将:断言 var 绑定到 obj 并返回成员的名称。 Or if the obj is not specified, use the callers stack frame to derive it, etc.或者,如果未指定 obj,则使用调用方堆栈帧来派生它,等等。

Could be made an efficient built in at some point, but here's a definition that works.在某些时候可以成为一个高效的内置工具,但这里有一个有效的定义。 I deliberately didn't support builtins , easy to add tho:我故意不支持builtins ,很容易添加:

Feel free to stick this in a package called varname.py , and use it in your patch.object calls:随意在了一个叫做坚持这个varname.py ,并在您的通话patch.object使用它:

patch.object(obj, varname(obj, obj.method_name), new_reg)

Note: this was written for python 3.注意:这是为 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

It's not very Pythonesque but I was curious and found this solution.它不是很 Pythonesque 但我很好奇并找到了这个解决方案。 You need to duplicate the globals dictionary since its size will change as soon as you define a new variable.您需要复制 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)}")

which returns:返回:

test = 3
variable name: test

To get the variable name of var as a string:以字符串形式获取var的变量名:

var = 1000
var_name = [k for k,v in locals().items() if v == var][0] 
print(var_name) # ---> outputs 'var'

This will work for simnple data types (str, int, float, list etc.)这适用于简单的数据类型(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!']

Thanks @restrepo, this was exactly what I needed to create a standard save_df_to_file() function.感谢@restrepo,这正是我创建标准 save_df_to_file() 函数所需要的。 For this, I made some small changes to your tostr() function.为此,我对您的 tostr() 函数做了一些小改动。 Hope this will help someone else:希望这对其他人有帮助:

def variabletostr(**df):
        variablename = list(df.keys())[0]
        return variablename
    
    variabletostr(df=0)

The original question is pretty old, but I found an almost solution with Python 3. (I say almost because I think you can get close to a solution but I do not believe there is a solution concrete enough to satisfy the exact request).最初的问题已经很老了,但是我找到了 Python 3 的几乎解决方案。(我说几乎是因为我认为您可以接近解决方案,但我不相信有足够具体的解决方案来满足确切的要求)。

First, you might want to consider the following:首先,您可能需要考虑以下几点:

  • objects are a core concept in Python, and they may be assigned a variable, but the variable itself is a bound name (think pointer or reference) not the object itself对象是 Python 中的核心概念,它们可能被分配了一个变量,但变量本身是一个绑定名称(认为指针或引用)而不是对象本身
  • var is just a variable name bound to an object and that object could have more than one reference (in your example it does not seem to) var只是一个绑定到对象的变量名,并且该对象可能有多个引用(在您的示例中似乎没有)
  • in this case, var appears to be in the global namespace so you can use the global builtin conveniently named global在这种情况下, var似乎位于全局命名空间中,因此您可以方便地使用名为global的 global builtin命令
  • different name references to the same object will all share the same id which can be checked by running the id builtin id like so: id(var)对同一对象的不同名称引用将共享相同的id ,可以通过运行 id builtin id来检查,如下所示: id(var)

This function grabs the global variables and filters out the ones matching the content of your variable.此函数抓取全局变量并过滤掉与变量内容匹配的变量。

def get_bound_names(target_variable):
    '''Returns a list of bound object names.'''
    return [k for k, v in globals().items() if v is target_variable]

The real challenge here is that you are not guaranteed to get back the variable name by itself.这里真正的挑战是你不能保证自己取回变量名。 It will be a list, but that list will contain the variable name you are looking for.这将是一个列表,但该列表将包含您要查找的变量名称。 If your target variable (bound to an object) is really the only bound name, you could access it this way:如果您的目标变量(绑定到对象)确实是唯一的绑定名称,您可以通过以下方式访问它:

bound_names = get_variable_names(target_variable)
var_string = bound_names[0]

Possible for Python >= 3.8 (with f'{var=}' string )可能为 Python >= 3.8(使用 f'{var=}' string )

Not sure if this could be used in production code, but in Python 3.8(and up) you can use f' string debugging specifier.不确定这是否可以用于生产代码,但在 Python 3.8(及更高版本)中,您可以使用 f' 字符串调试说明符。 Add = at the end of an expression, and it will print both the expression and its value:在表达式末尾添加 = ,它将打印表达式及其值:

my_salary_variable = 5000
print(f'{my_salary_variable  =  }')

Output:
my_salary_variable  =  5000

To uncover this magic here is another example:在这里揭开这个魔法是另一个例子:

param_list = f'{my_salary_variable=}'.split('=')
print(param_list)

Output:
['my_salary_variable', '5000']

Explanation: when you put '=' after your var in f'string, it returns a string with variable name, '=' and its value.说明:当您在 f'string 中的 var 之后放置 '=' 时,它会返回一个包含变量名称、'=' 及其值的字符串。 Split it with.split('=') and get a List of 2 strings, [0] - your_variable_name, and [1] - actual object of variable.用 .split('=') 拆分它并获得 2 个字符串的列表,[0] - your_variable_name,和 [1] - 实际变量 object。 Pick up [0] element of the list if you need variable name only.如果您只需要变量名,请选择列表的 [0] 元素。

my_salary_variable = 5000
param_list = f'{my_salary_variable=}'.split('=')
print(param_list[0])
Output:
my_salary_variable

or, in one line

my_salary_variable = 5000
print(f'{my_salary_variable=}'.split('=')[0])
Output:
my_salary_variable

Works with functions too:也适用于功能:

def my_super_calc_foo(number):
    return number**3

print(f'{my_super_calc_foo(5)  =  }')
print(f'{my_super_calc_foo(5)=}'.split('='))

Output: Output:

my_super_calc_foo(5)  =  125
['my_super_calc_foo(5)', '125']

Process finished with exit code 0

This module works for converting variables names to a string: https://pypi.org/project/varname/此模块用于将变量名称转换为字符串: https : //pypi.org/project/varname/

Use it like this:像这样使用它:

from varname import nameof从 varname 导入 nameof

variable=0变量=0

name=nameof(variable)名称=名称(变量)

print(name)打印(名称)

//output: variable //输出:变量

Install it by:通过以下方式安装它:

pip install varname pip 安装变量名

print "var"
print "something_else"

Or did you mean something_else?或者你的意思是something_else?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM