获取变量名作为字符串 [英] Getting the name of a variable as a string

查看:34
本文介绍了获取变量名作为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此线程讨论如何在 Python 中将函数的名称作为字符串获取:如何获取函数名作为字符串?

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?

我怎样才能对变量做同样的事情?与函数相反,Python 变量没有 __name__ 属性.

How can I do the same for a variable? As opposed to functions, Python variables do not have the __name__ attribute.

换句话说,如果我有一个变量,例如:

In other words, if I have a variable such as:

foo = dict()
foo['bar'] = 2

我正在寻找一个函数/属性,例如retrieve_name() 为了 从此列表中在 Pandas 中创建一个 DataFrame,其中列名由实际字典的名称给出:

I am looking for a function/attribute, e.g. retrieve_name() in order to create a DataFrame in Pandas from this list, where the column names are given by the names of the actual dictionaries:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts] 

推荐答案

TL;DR

使用 python-varnameWrapper 帮助程序>:

from varname.helpers import Wrapper

foo = Wrapper(dict())

# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2

对于列表理解部分,您可以这样做:

For list comprehension part, you can do:

n_jobs = Wrapper(<original_value>) 
users = Wrapper(<original_value>) 
queues = Wrapper(<original_value>) 
priorities = Wrapper(<original_value>) 

list_of_dicts = [n_jobs, users, queues, priorities]
columns = [d.name for d in list_of_dicts]
# ['n_jobs', 'users', 'queues', 'priorities']
# REMEMBER that you have to access the <original_value> by d.value

我是 python-varname 包的作者.如果您有任何问题,请告诉我,或者您可以在 Github 上提交问题.

I am the author of the python-varname package. Please let me know if you have any questions or you can submit issues on Github.

是和否.

我们在运行时检索变量名,因此我们需要调用一个函数来使我们能够访问之前的帧以检索变量名.这就是我们需要一个 Wrapper 的原因.在该函数中,在运行时,我们正在解析前一帧中的源代码/AST 节点以获取确切的变量名称.

We are retrieving the variable names at runtime, so we need a function to be called to enable us to access the previous frames to retrieve the variable names. That's why we need a Wrapper there. In that function, at runtime, we are parsing the source code/AST nodes in the previous frames to get the exact variable name.

但是,之前帧中的源代码/AST节点并不总是可用的,或者它们可能被其他环境修改(例如:pytestassert语句).一个简单的例子是代码通过 exec() 运行.即使我们仍然能够从字节码中检索到一些信息,但它需要付出太多的努力,而且还容易出错.

However, the source code/AST nodes in the previous frames are not always available, or they could be modified by other environments (e.g: pytest's assert statement). One simple example is that the codes run via exec(). Even though we are still able to retrieve some information from the bytecode, it needs too much effort and it is also error-prone.

首先,我们需要确定给定变量的帧.它并不总是简单的直接前一帧.例如,我们可能有另一个函数的包装器:

First of all, we need to identify which frame the variable is given. It's not always simply the direct previous frame. For example, we may have another wrapper for the function:

from varname import varname

def func():
  return varname()

def wrapped():
  return func()

x = wrapped()

在上面的例子中,我们必须跳过 wrapped 内的帧才能到达正确的帧 x = Wrapped() 以便我们能够定位 x.varname 的参数 frameignore 允许我们跳过其中一些中间帧.在 README 文件和包的 API 文档中查看更多详细信息.

In the above example, we have to skip the frame inside wrapped to get to the right frame x = wrapped() so that we are able to locate x. The arguments frame and ignore of varname allow us to skip some of these intermediate frames. See more details in the README file and the API docs of the package.

然后我们需要解析 AST 节点来定位变量被赋值(函数调用)的位置.这并不总是一个简单的任务.有时可能会有复杂的 AST 节点,例如 x = [wrapped()].我们需要通过遍历 AST 树来识别正确的赋值.

Then we need to parse the AST node to locate where the variable is assigned value (function call) to. It's not always just a simple assignment. Sometimes there could be complex AST nodes, for example, x = [wrapped()]. We need to identify the correct assignment by traversing the AST tree.

一旦我们确定了分配节点,它就是可靠的.

Once we identify the assignment node, it is reliable.

varname 完全取决于 executing 包来查找节点.确保执行检测的节点是正确的(另请参见 this).

它部分适用于应用其他 AST 魔法的环境,包括 pytest、ipython、macropy、birdseye、reticulate with R 等.无论是执行还是 varname 都不能 100% 地适用于这些环境.

It partially works with environments where other AST magics apply, including pytest, ipython, macropy, birdseye, reticulate with R, etc. Neither executing nor varname is 100% working with those environments.

嗯,是的,又不是.

如果您的场景很简单,@juan Isaza 或 @scohe001 提供的代码可能足以让您处理在直接前一帧定义变量且 AST 节点是简单赋值的情况.您只需返回一帧并在那里检索信息.

If your scenario is simple, the code provided by @juan Isaza or @scohe001 probably is enough for you to work with the case where a variable is defined at the direct previous frame and the AST node is a simple assignment. You just need to go one frame back and retrieve the information there.

但是,如果场景变得复杂,或者我们需要采用不同的应用场景,你可能需要像 python-varname,来处理它们.这些场景可能包括:

However, if the scenario becomes complicated, or we need to adopt different application scenarios, you probably need a package like python-varname, to handle them. These scenarios may include to:

  1. 在源代码不可用或 AST 节点不可访问时显示更友好的消息
  2. 跳过中间帧(允许在其他中间帧中包装或调用函数)
  3. 自动忽略来自内置函数或库的调用.例如:x = str(func())
  4. 检索赋值左侧的多个变量名称
  5. 等等

f-string怎么样?

就像@Aivar Paalberg 提供的答案一样.它绝对是快速和可靠的.但是,它不是在运行时,这意味着您必须在打印名称之前知道它是 foo.但是使用 varname,您不必知道该变量即将到来:

Like the answer provided by @Aivar Paalberg. It's definitely fast and reliable. However, it's not at runtime, meaning that you have to know it's foo before you print the name out. But with varname, you don't have to know that variable is coming:

from varname import varname

def func():
  return varname()

# In external uses
x = func() # 'x'
y = func() # 'y'

终于

python-varname 不仅能够从赋值中检测变量名,而且:

Finally

python-varname is not only able to detect the variable name from an assignment, but also:

  • 使用 nameof
  • 直接检索变量名
  • 检测下一个直接属性名称,使用 will
  • 使用 argname
  • 获取传递给函数的参数名称/来源
  • Retrieve variable names directly, using nameof
  • Detect next immediate attribute name, using will
  • Fetch argument names/sources passed to a function using argname

从其文档中了解更多信息.

Read more from its documentation.

但是,我想说的最后一句话是,尽量避免使用它.

However, the final word I want to say is that, try to avoid using it whenever you can.

因为您无法确保客户端代码将在源节点可用或 AST 节点可访问的环境中运行.当然,解析源代码、识别环境、检索 AST 节点并在需要时评估它们会耗费资源.

Because you can't make sure that the client code will run in an environment where the source node is available or AST node is accessible. And of course, it costs resources to parse the source code, identify the environment, retrieve the AST nodes and evaluate them when needed.

这篇关于获取变量名作为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆