如何记录嵌套表的访问/写入?
2019-9-25 23:55:8
收藏:0
阅读:99
评论:1
作为我正在工作的项目的一部分,我想能够在表被访问或写入时打印出来,以及访问/写入表中的内容。查找了一下,我发现了 这个,其中描述了如何使用代理表和 __index 和 __newindex 元方法跟踪表何时被访问/更新。然而,他们提供的代码如果使用嵌套表作为代理表,则不能正确显示正在发生的情况。假设我写以下代码,根据上一个进行调整:
mt = {}
function mt.__index(self, key)
print('正在访问键 '..key)
return self.proxy[key]
end
function mt.__newindex(self, key, value)
print('将键 '..key..' 设置为值 '..tostring(value))
self.proxy[key] = value
end
function setproxy(t)
new_t = {proxy = t}
setmetatable(new_t, mt)
return new_t
end
t = {
a = 1,
b = 2,
c = {
a = 3,
b = 4,
},
}
t = setproxy(t)
t.a = 2 -- 正如预期地打印出“将键 a 设置为值 2”
t.c.a = 4 -- 打印“访问键 c”,没有其他输出
问题在于 __index 被调用以访问键 c,并返回代理表中的一个值,但是它没有相同的元表,因此它不会记录对 t.c 的写入。我想要第二个赋值语句打印出类似于“将键 c.a 设置为值 4”的内容,但是我不知道从哪里开始实际实现这样的事情。
经过许多思考,我认为你可以通过使具有表值的每个键也是另一个代理表来实现这一点,但是然后你必须
- 递归地用代理表替换所有表值,我正在考虑每个代理表是否包含一些信息,以允许
这个代理表的
__newindex打印出正确的键 - 如果某个键设置为表值,则必须递归地将其替换为 代理表,然后才能设置实际值
这似乎只是为了某些应该比这更简单的事情而进行的大量工作和复杂性。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

你需要为你想要访问的每个表创建一个代理表。最简单的方法是,每当原始代理被访问时返回一个新的代理表,同时返回一个普通表:
mt = {} function mt.__index(self, key) print('accessing key '..key) local value = self.proxy[key] if type(value)=='table' then return setmetatable({proxy=value}, mt) else return value end end function mt.__newindex(self, key, value) print('setting key '..key..' to value '..tostring(value)) self.proxy[key] = value end function setproxy(t) new_t = {proxy = t} setmetatable(new_t, mt) return new_t end t = { a = 1, b = 2, c = { a = 3, b = 4, }, } t = setproxy(t) t.a = 2 --按预期工作 t.c.a = 4 --同样按预期工作关于性能的说明:
由于Lua中的表是进行垃圾回收的,创建新表通常被认为是“慢”的。不过这仍然是一种相对性观点;如果你正在编写一个简单的脚本,用于手动运行,不必优化,它仍然会非常快。如果你正在编写嵌套循环,有数百万次迭代,或者你的代码需要尽可能在几毫秒内响应,则应该考虑根据你的用例缓存这些代理表。如果你发现你的代码不断地访问相同的代理表,每次都创建新的代理表,则可以将它们缓存在一个_proxies_表中,其中
proxies[table_A] == proxy_to_A,并设置一个__index元方法,如果代理不存在,则创建代理(此时,权衡是由于元方法调用创建新代理可能会稍微慢一些)。