Распечатать все локальные переменные, доступные для текущей области в Lua
Я знаю, как напечатать "все" глобальные переменные, используя следующий код
for k,v in pairs(_G) do
print("Global key", k, "value", v)
end
Поэтому мой вопрос заключается в том, как это сделать для всех переменных, которые доступны из выполняемой в данный момент функции, что может сделать то, что locals()
делает для Python.
5 ответов
Вот реализация 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
Спасибо за согласие. Вы открыли последний кусок головоломки!;-)
Повышающие значения - это локальные переменные из внешних областей, которые используются в текущей функции. Они ни в _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
Проблема с версией петли судьи Мейгардена просто local i = 0
, Это ничего не делает, потому что первый индексированный с '0' всегда будет возвращать ноль.
Помните, что индексы Lua по умолчанию начинаются с "1", а не с "0", как C/C++. Конечно, вы можете использовать '0' для индекса с вашими собственными типами, но функции по умолчанию ожидают значение по умолчанию '1' в качестве первого индекса.
Просто измените это на local i = 1
и его цикл будет работать нормально.
Увидеть 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
Вы можете использовать getfenv, чтобы получить локальную среду.
getfenv ([f]) Возвращает текущее окружение, используемое функцией. f может быть функцией Lua или числом, которое определяет функцию на этом уровне стека: уровень 1 - это функция, вызывающая getfenv. Если данная функция не является функцией Lua или если f равно 0, getfenv возвращает глобальную среду. Значением по умолчанию для f является 1.
Изменить: извините, я был не прав.
Я только что проверил исходный код Lua. debug.getlocal()
это единственный способ получить локальные переменные.
Lua использует внутреннюю структуру Proto и не дает нам доступа к этому.
(Proto содержит локальные свойства плюс родительскую ссылку на Proto. Итерация функции Proto с помощью getfenv,
мы также перебираем наследуемые свойства, а не то, что хотели)
Пользователи могут определять свои Proto- ы либо с помощью сред и set/getfenv
функции или с помощью метатаблиц.