关于自省:打印Lua中当前作用域可访问的所有局部变量

Print all local variables accessible to the current scope in Lua

我知道如何使用以下代码打印"所有"全局变量

1
2
3
for k,v in pairs(_G) do
    print("Global key", k,"value", v)
end

因此,我的问题是如何对当前执行函数可访问的所有变量执行此操作,以达到locals()对于Python的作用。


这是locals()函数的实现。它将从调用范围返回一个本地表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function locals()
  local variables = {}
  local idx = 1
  while true do
    local ln, lv = debug.getlocal(2, idx)
    if ln ~= nil then
      variables[ln] = lv
    else
      break
    end
    idx = 1 + idx
  end
  return variables
end

请注意,在lua REPL中,每一行都是一个单独的块,具有单独的局部变量。此外,还返回内部变量(如果要删除它们,名称以'('开头):

1
2
3
> local a = 2; for x, v in pairs(locals()) do print(x, v) end
a   2
(*temporary)    function: 0x10359b38

感谢你的接纳。您已经解开了难题的最后一块! ;-)

上值是来自外部作用域的局部变量,在当前函数中使用。它们既不在_G中也不在locals()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function upvalues()
  local variables = {}
  local idx = 1
  local func = debug.getinfo(2,"f").func
  while true do
    local ln, lv = debug.getupvalue(func, idx)
    if ln ~= nil then
      variables[ln] = lv
    else
      break
    end
    idx = 1 + idx
  end
  return variables
end

示例(注意,您必须使用来显示它):

1
2
> local a= 2; function f() local b = a; for x,v in pairs(upvalues()) do print(x,v) end end; f()
a   2


使用debug.getlocal


上面的Maygarden法官的循环版本的问题只是local i = 0
它没有任何作用,因为第一个索引为" 0"的索引将始终返回nil。

请记住,默认情况下,Lua索引以" 1"开头,而不是像C / C ++那样的" 0"开头。
当然,您可以使用自己的类型将" 0"用于索引,但是默认功能
期望默认值" 1"作为第一个索引。

只需将其更改为local i = 1,他的循环就可以正常工作。


参见debug.getlocal

1
2
3
4
5
6
7
8
9
10
local foobar = 1

local i = 0
repeat
    local k, v = debug.getlocal(1, i)
    if k then
        print(k, v)
        i = i + 1
    end
until nil == k

输出:

1
2
foobar  1
i       2


您可以使用getfenv获取本地环境。

getfenv ([f]) Returns the current
environment in use by the function. f
can be a Lua function or a number that
specifies the function at that stack
level: Level 1 is the function calling
getfenv. If the given function is not
a Lua function, or if f is 0, getfenv
returns the global environment. The
default for f is 1.

编辑:对不起,我错了。

我刚刚检查了Lua源代码。 debug.getlocal()是获取局部变量的唯一方法。
Lua使用内部Proto结构,但不允许我们访问它。
(Proto保留本地属性以及父Proto引用。使用getfenv迭代函数的Proto,
我们还会迭代继承的属性,而不是我们想要的属性)

用户可以使用环境和set/getfenv函数或使用元表来定义其Proto。