【问题标题】:How to retrieve a variable's name in python at runtime?如何在运行时在 python 中检索变量的名称?
【发布时间】:2009-05-31 20:44:07
【问题描述】:

有没有办法在运行时(从代码中)知道变量的名称? 还是编译过程中忘记了变量名(字节码与否)?

例如:

>>> 变异 = 15 >>> 打印变量。~~名字~~() '变量'

注意:我说的是普通数据类型变量(intstrlist 等)

【问题讨论】:

  • 不是必须输入变量名来获取它的名字吗?
  • 是的,嗯,已经是 3 年前了,我不记得为什么这个问题有意义。但是哇!它非常受欢迎,所以有一些关于它的东西。
  • 这里是一个用法示例:变量 foo,bar,baz 都在那里,我想得到一个与 {'foo':foo,'bar':bar,'baz':baz} 完全一样的字典.当然,我可以像刚才那样打字,但不是很简洁。 locals(),在我看来,传递的信息太多,并不完美。我期望的是像magic_func([foo,bar,baz]) 这样的函数,它返回我想要的字典
  • 在 Python 3.8 中添加的有趣技巧,回答了我与您的问题相关的使用需求:docs.python.org/3/whatsnew/…

标签: python


【解决方案1】:

变量名不会被遗忘,您可以通过自省来访问变量(并查看您拥有哪些变量),例如

>>> i = 1
>>> locals()["i"]
1

但是,由于 Python 中没有指针,所以如果不实际写入变量名,就无法引用变量。所以如果你想打印一个变量名和它的值,你可以通过locals() 或者类似的函数。 ([i] 变为 [1] 并且无法检索到 1 实际上来自 i 的信息。)

【讨论】:

  • 这解决了我的问题。然后我对它们的值进行反向查找,并找到它们的名字。谢谢。
  • 这方面的难点在于,如果你只有i' then it is impossible to find it's name in locals(). Consider 'i=1; j=1;'. After this 'locals()["i"] is locals()["j"]'. If all that you have is i',那么循环通过 locals() 将导致找到i' or j' 作为名称。
  • D.可能是想说“如果你只有1 [...]”
【解决方案2】:

变量名称保留在编译后的代码中(这就是例如 dir 内置可以工作的方式),但那里的映射从名称到值,反之亦然。因此,如果有几个变量都值得,例如,23,则无法仅根据值 23 来区分它们。

【讨论】:

    【解决方案3】:

    这是我用来打印变量值的函数,它适用于本地和全局:

    import sys
    def print_var(var_name):
        calling_frame = sys._getframe().f_back
        var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None))
        print (var_name+':', str(var_val))
    

    所以下面的代码:

    global_var = 123
    def some_func():
        local_var = 456
        print_var("global_var")
        print_var("local_var")
        print_var("some_func")
    
    some_func()
    

    产生:

    global_var: 123
    local_var: 456
    some_func: <function some_func at 0x10065b488>
    

    【讨论】:

    • 这就是我要找的。但是,现在我很好奇这是否可以扩展到在调用print_var 的上下文中适用于任何表达式。一个用例是打印对象字段的名称和值(例如,print_var('myobject.x')
    【解决方案4】:

    这里有一个基本的(可能很奇怪)函数,它显示了它的参数的名称...... 这个想法是分析代码并搜索对函数的调用(在 init 方法中添加它可以帮助找到实例名称,尽管代码分析更复杂)

    def display(var):
        import inspect, re
        callingframe = inspect.currentframe().f_back
        cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines
        m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE)
        print m.group(1), type(var), var
    

    请注意: 从调用代码中获取多行有助于以防调用被拆分,如下例所示:

    display(
            my_var
           )
    

    但会产生意想不到的结果:

    display(first_var)
    display(second_var)
    

    如果您无法控制项目的格式,您仍然可以改进代码以检测和管理不同的情况......

    总的来说,我认为静态代码分析可以产生更可靠的结果,但我现在懒得检查它

    【讨论】:

      【解决方案5】:

      这适用于简单的数据类型(str、int、float、list 等)

      def my_print(var_str) :
          print var_str+':', globals()[var_str]
      

      【讨论】:

      • 需要注意的是,如果你有,比如ix = 200,那么你用my_print("ix")调用这个函数。
      【解决方案6】:

      你可以做到,只是不漂亮。

      import inspect, sys
      
      
      def addVarToDict(d, variable):
          lineNumber = inspect.currentframe().f_back.f_lineno
          with open(sys.argv[0]) as f:
              lines = f.read().split("\n")
      
          line = lines[lineNumber-1]
      
          varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip()
          d[varName] = variable
      
      
      d = {}
      
      a=1
      
      print d # {}
      addVarToDict(d,a)
      print d # {'a': 1}
      

      【讨论】:

        【解决方案7】:

        我尝试了上面帖子中的以下链接,但没有成功: 谷歌搜索返回了这个。

        http://pythonic.pocoo.org/2009/5/30/finding-objects-names

        【讨论】:

        • 除了我已经投了这个,它不一定是“上面的帖子”:我们正在谈论@piquadrat 的答案。
        【解决方案8】:

        就在昨天,我看到一篇博客文章,其中包含可以执行此操作的工作代码。这是链接:

        http://pyside.blogspot.com/2009/05/finding-objects-names.html

        【讨论】:

        • “抱歉,您在此博客中查找的页面不存在。”
        • @StuartWoodward:archive.org 有一个副本:web.archive.org/web/20090624235438/http://pyside.blogspot.com/…
        • 如果在main python 文件中使用,它也只能以当前形式工作,如果导入它会打开错误的文件,因此需要对其进行调整。
        【解决方案9】:

        使用 f 字符串格式的简单解决方案,它是 Python 3.6 及更高版本的本机:

        vari = 15
        vari_name = f"{vari=}".split("=")[0]
        print(vari_name)
        

        生产:

        vari
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-21
          • 1970-01-01
          • 2017-10-12
          • 2019-02-23
          • 2011-03-02
          • 2021-12-20
          相关资源
          最近更新 更多