Python 以字符串形式获取变量名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18425225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting the name of a variable as a string
提问by Amelio Vazquez-Reina
This thread discusses how to get the name of a function as a string in Python: How to get a function name as a string in Python?
该线程讨论了如何在 Python 中以字符串形式获取函数名称:如何在 Python 中以字符串 形式获取函数名称?
How can I do the same for a variable? As opposed to functions, Python variables do not have the __name__
attribute.
我怎样才能对变量做同样的事情?与函数相反,Python 变量没有该__name__
属性。
In other words, if I have a variable such as:
换句话说,如果我有一个变量,例如:
foo = dict()
foo['bar'] = 2
I am looking for a function/attribute, e.g. retrieve_name
:
我正在寻找一个函数/属性,例如retrieve_name
:
retrieve_name(foo)
that returns the string 'foo'
返回字符串 'foo'
Update:
更新:
Since people are asking why I want to do this, here is an example. I would like to create a DataFrame in Pandas from this list, where the column namesare given by the names of the actual dictionaries:
既然人们问我为什么要这样做,这里有一个例子。我想从这个列表在 Pandas 中创建一个 DataFrame,其中列名由实际字典的名称给出:
# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
采纳答案by Panwen Wang
Using the python-varname
package, you can easily retrieve the name of the variables
使用该python-varname
包,您可以轻松检索变量的名称
https://github.com/pwwang/python-varname
https://github.com/pwwang/python-varname
In your case, you can do:
在你的情况下,你可以这样做:
from varname import Wrapper
foo = Wrapper(dict())
# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2
Or you can also try to retrieve the variable name directly:
或者你也可以尝试直接检索变量名:
from varname import nameof
foo = duct()
fooname = nameof(foo)
# fooname == 'foo'
I am the author of this package. Please let me know if you have any questions or you can submit issues on github.
我是这个包的作者。如果您有任何问题,请告诉我,或者您可以在 github 上提交问题。
回答by kindall
The only objects in Python that have canonical names are modules, functions, and classes, and of course there is no guarantee that this canonical name has any meaning in any namespace after the function or class has been defined or the module imported. These names can also be modified after the objects are created so they may not always be particularly trustworthy.
Python 中唯一具有规范名称的对象是模块、函数和类,当然,在定义函数或类或导入模块后,不能保证该规范名称在任何命名空间中具有任何意义。这些名称也可以在创建对象后修改,因此它们可能并不总是特别值得信赖。
What you want to do is not possible without recursively walking the tree of named objects; a name is a one-way reference to an object. A common or garden-variety Python object contains no references to its names. Imagine if every integer, every dict, every list, every Boolean needed to maintain a list of strings that represented names that referred to it! It would be an implementation nightmare, with little benefit to the programmer.
如果不递归地遍历命名对象树,你想要做的事情是不可能的;名称是对对象的单向引用。一个普通的或花园式的 Python 对象不包含对其名称的引用。想象一下,如果每个整数、每个字典、每个列表、每个布尔值都需要维护一个表示引用它的名称的字符串列表!这将是一个实现噩梦,对程序员几乎没有好处。
回答by korylprince
I don't believe this is possible. Consider the following example:
我不相信这是可能的。考虑以下示例:
>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664
The a
and b
point to the same object, but the object can't know what variables point to it.
在a
与b
指向同一个对象,但对象无法知道指向它哪些变量。
回答by blakev
>>> locals()['foo']
{}
>>> globals()['foo']
{}
If you wanted to write your own function, it could be done such that you could check for a variable defined in locals then check globals. If nothing is found you could compare on id() to see if the variable points to the same location in memory.
如果您想编写自己的函数,可以这样做,以便您可以检查局部变量中定义的变量,然后检查全局变量。如果什么也没找到,您可以比较 id() 以查看变量是否指向内存中的相同位置。
If your variable is in a class, you could use className.dict.keys() or vars(self) to see if your variable has been defined.
如果您的变量在一个类中,您可以使用 className。dict.keys() 或 vars(self) 以查看您的变量是否已定义。
回答by nneonneo
In Python, the def
and class
keywords will bind a specific name to the object they define (function or class). Similarly, modules are given a name by virtue of being called something specific in the filesystem. In all three cases, there's an obvious way to assign a "canonical" name to the object in question.
在 Python 中,def
andclass
关键字会将特定名称绑定到它们定义的对象(函数或类)。类似地,模块通过在文件系统中被称为特定的东西而被赋予一个名称。在所有三种情况下,有一种明显的方法可以为相关对象分配“规范”名称。
However, for other kinds of objects, such a canonical name may simply not exist. For example, consider the elements of a list. The elements in the list are not individually named, and it is entirely possible that the only way to refer to them in a program is by using list indices on the containing list. If such a list of objects was passed into your function, you could not possibly assign meaningful identifiers to the values.
然而,对于其他类型的对象,这样的规范名称可能根本不存在。例如,考虑列表的元素。列表中的元素没有单独命名,完全有可能在程序中引用它们的唯一方法是使用包含列表上的列表索引。如果将这样的对象列表传递到您的函数中,则您不可能为这些值分配有意义的标识符。
Python doesn't save the name on the left hand side of an assignment into the assigned object because:
Python 不会将赋值左侧的名称保存到指定的对象中,因为:
- It would require figuring out which name was "canonical" among multiple conflicting objects,
- It would make no sense for objects which are never assigned to an explicit variable name,
- It would be extremely inefficient,
- Literally no other language in existence does that.
- 它需要弄清楚在多个冲突对象中哪个名称是“规范的”,
- 对于从未分配给显式变量名的对象来说,这是没有意义的,
- 这将是非常低效的,
- 从字面上看,现有的其他语言都没有这样做。
So, for example, functions defined using lambda
will always have the "name" <lambda>
, rather than a specific function name.
因此,例如,使用定义的函数lambda
将始终具有 "name" <lambda>
,而不是特定的函数名称。
The best approach would be simply to ask the caller to pass in an (optional) list of names. If typing the '...','...'
is too cumbersome, you could accept e.g. a single string containing a comma-separated list of names (like namedtuple
does).
最好的方法是简单地要求调用者传入一个(可选的)名称列表。如果键入'...','...'
太麻烦,您可以接受例如包含逗号分隔名称列表的单个字符串(就像这样namedtuple
做)。
回答by scohe001
Even if variable values don't point back to the name, you have access to the list of every assigned variable and its value, so I'm astounded that only one person suggested looping through there to look for your var name.
即使变量值不指向名称,您也可以访问每个已分配变量及其值的列表,所以我很惊讶只有一个人建议在那里循环查找您的 var 名称。
Someone mentioned on that answer that you might have to walk the stack and check everyone's locals and globals to find foo
, but if foo
is assigned in the scope where you're calling this retrieve_name
function, you can use inspect
's current frame
to get you all of those local variables.
有人在该答案中提到您可能必须遍历堆栈并检查每个人的局部变量和全局变量才能 find foo
,但是如果foo
在调用此retrieve_name
函数的范围内分配了inspect
's ,则可以使用'scurrent frame
来获取所有这些局部变量.
My explanation might be a little bit too wordy (maybe I should've used a "foo" less words), but here's how it would look in code (Note that if there is more than one variable assigned to the same value, you will get both of those variable names):
我的解释可能有点冗长(也许我应该少用“foo”这个词),但这是它在代码中的样子(请注意,如果有多个变量分配给相同的值,您将获取这两个变量名):
import inspect
x,y,z = 1,2,3
def retrieve_name(var):
callers_local_vars = inspect.currentframe().f_back.f_locals.items()
return [var_name for var_name, var_val in callers_local_vars if var_val is var]
print retrieve_name(y)
If you're calling this function from another function, something like:
如果您从另一个函数调用此函数,例如:
def foo(bar):
return retrieve_name(bar)
foo(baz)
And you want the baz
instead of bar
, you'll just need to go back a scope further. This can be done by adding an extra .f_back
in the caller_local_vars
initialization.
而你想要的baz
而不是bar
,你只需要进一步返回一个范围。这可以通过.f_back
在caller_local_vars
初始化中添加额外内容来完成。
See an example here: ideone
在此处查看示例:ideone
回答by fdvfcges
def name(**variables):
return [x for x in variables]
It's used like this:
它是这样使用的:
name(variable=variable)
回答by Zachary Ernst
Here's one approach. I wouldn't recommend this for anything important, because it'll be quite brittle. But it can be done.
这是一种方法。我不会推荐任何重要的东西,因为它会很脆弱。但这是可以完成的。
Create a function that uses the inspect
module to find the source code that called it. Then you can parse the source code to identify the variable names that you want to retrieve. For example, here's a function called autodict
that takes a list of variables and returns a dictionary mapping variable names to their values. E.g.:
创建一个函数,该函数使用该inspect
模块查找调用它的源代码。然后,您可以解析源代码以识别要检索的变量名称。例如,这里有一个被调用的函数autodict
,它接受一个变量列表并返回一个将变量名称映射到它们的值的字典。例如:
x = 'foo'
y = 'bar'
d = autodict(x, y)
print d
Would give:
会给:
{'x': 'foo', 'y': 'bar'}
Inspecting the source code itself is better than searching through the locals()
or globals()
because the latter approach doesn't tell you whichof the variables are the ones you want.
检查源代码本身比搜索locals()
or更好,globals()
因为后一种方法不会告诉您哪些变量是您想要的。
At any rate, here's the code:
无论如何,这是代码:
def autodict(*args):
get_rid_of = ['autodict(', ',', ')', '\n']
calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0]
calling_code = calling_code[calling_code.index('autodict'):]
for garbage in get_rid_of:
calling_code = calling_code.replace(garbage, '')
var_names, var_values = calling_code.split(), args
dyn_dict = {var_name: var_value for var_name, var_value in
zip(var_names, var_values)}
return dyn_dict
The action happens in the line with inspect.getouterframes
, which returns the string within the code that called autodict
.
该操作发生在 与 的行中inspect.getouterframes
,它返回调用 的代码中的字符串autodict
。
The obvious downside to this sort of magic is that it makes assumptions about how the source code is structured. And of course, it won't work at all if it's run inside the interpreter.
这种魔法的明显缺点是它对源代码的结构做出了假设。当然,如果它在解释器中运行,它根本不会工作。
回答by juan Isaza
On python3, this function will get the outer most name in the stack:
在 python3 上,此函数将获取堆栈中最外层的名称:
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]
It is useful anywhere on the code. Traverses the reversed stack looking for the first match.
它在代码的任何地方都很有用。遍历反向堆栈以查找第一个匹配项。
回答by Dana
For constants, you can use an enum, which supports retrieving its name.
对于常量,您可以使用枚举,它支持检索其名称。
回答by Joe Camel
I think it's so difficult to do this in Python because of the simple fact that you never will not know the name of the variable you're using. So, in his example, you could do:
我认为在 Python 中执行此操作非常困难,因为您永远不会不知道正在使用的变量的名称这一简单事实。所以,在他的例子中,你可以这样做:
Instead of:
代替:
list_of_dicts = [n_jobs, users, queues, priorities]
dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}