Распечатайте все локальные переменные, доступные для текущей области в Lua

Я знаю, как печатать "все" глобальные переменные, используя следующий код

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

Итак, мой вопрос заключается в том, как сделать это для всех переменных, доступных из текущей исполняемой функции, что может сделать то, что locals() для Python.

Ответ 1

Вот реализация функции locals(). Он вернет таблицу локалей из области вызова:

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 каждая строка представляет собой отдельный фрагмент с отдельными локалями. Кроме того, возвращаются внутренние переменные (имена начинаются с '(' если вы хотите их удалить):

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

Спасибо за согласие. Вы разблокировали последний кусочек головоломки!; -)

Upvalues ​​- это локальные переменные из внешних областей, которые используются в текущей функции. Они не находятся ни в _G, ни в locals()

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

Пример (обратите внимание, что вы должны использовать его для отображения):

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

Ответ 2

Используйте debug.getlocal.

Ответ 3

См. debug.getlocal:

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

Вывод:

foobar  1
i       2

Ответ 4

Проблема с версией цикла Judge Maygarden выше просто local i = 0. Он ничего не делает, потому что первый индекс с "0" всегда будет возвращать нуль.

Помните, что индексы Lua по умолчанию начинаются с "1", а не "0" , как C/С++. Вы можете использовать "0" для индекса с вашими типами курсов, но функции по умолчанию ожидают, что по умолчанию "1" будет первым индексом.

Просто измените его на local i = 1, и его цикл будет работать нормально.

Ответ 5

Вы можете использовать getfenv, чтобы получить локальную среду.

getfenv ([f]) Возвращает текущий окружающая среда, используемая функцией. е может быть функцией Lua или числом, которое определяет функцию в этом стеке level: Уровень 1 - вызов функции getfenv. Если данная функция не является функция Lua, или если f равно 0, getfenv возвращает глобальную среду. значение по умолчанию для f равно 1.

Изменить: извините, я ошибся.

Я только что проверил исходный код Lua. debug.getlocal() - единственный способ получить локальные переменные.
Lua использует внутреннюю структуру Proto и не дает нам доступ к этому.
(Proto содержит локальные свойства, а также родительскую ссылку Proto. Итерационная функция Proto, используя getfenv,
мы также итерируем унаследованные свойства, а не то, что хотели)

Пользователи могут определять свои Proto с средами и функциями set/getfenv или с помощью метатегов.