跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Lua

Lua 元表与元方法详解

综述由AI生成Lua 语言中的元表 (Metatable) 和元方法 (Metamethod)。元表用于定义表在特定操作下的行为,通过 setmetatable 和 getmetatable 进行设置和获取。文章详细讲解了常用元方法,包括 __add 实现加法运算、__tostring 控制打印格式、__index 处理属性访问以及 __newindex 拦截字段赋值。通过代码示例展示了元表在不同场景下的工作原理及注意事项,帮助开发者理解 Lua 的元编程机制。

暖阳发布于 2026/3/23更新于 2026/6/228 浏览

1. 元表 (Metatable)

元表是普通的 Lua 表,定义了原始值在某些特定操作下的行为。 我们称元表中的键为事件,称值为元方法。

设置 (SetMetatable)/获取 (GetMetatable) 元表:

设置元表的两种写法:

local mt = {}
setmetatable(t, mt)
setmetatable(t, {__add = function() end})
local mt = {}
local t = {}
print(getmetatable(t)) -- nil
setmetatable(t, mt) -- 设置表 t 的元表为 mt
print(mt)
print(getmetatable(t)) -- 获取元表地址,和上面打印的 mt 地址相同

输出结果:

nil table: 000001ECD17E3940 table: 000001ECD17E3940

2. 元方法

2.1 __add(对表进行'+'操作时触发)
local mt = {}
mt.__add = function(tab1, tab2)
    local resTab = {}
    local len = math.max(#tab1, #tab2)
    if len == 0 then
        return resTab
    end
    for i = 1, len, 1 do
        if type(tab1[i]) == "nil" then tab1[i] = 0 end
        if type(tab2[i]) == "nil" then tab2[i] = 0 end
        resTab[i] = tab1[i] + tab2[i]
    end
    return resTab
end

local tab1 = {1, 2, 3}
local tab2 = {4, 5, 6}
setmetatable(tab1, mt)
setmetatable(tab2, mt)
local resTab = tab1 + tab2
for index, value in ipairs(resTab) do
    print(value)
end

输出结果:

5
7
9
元方法对应运算符
__add+
__sub-
__mul*
__div/
__mod%
__concat…(连接符)
__eq==
__lt<
__le<=

注意事项 当涉及二元操作符时:两表元表有以下情况

  • 相同元表:执行元表中的元方法
  • 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元表:报错
local mt1 = {}
local mt2 = {}
mt1.__sub = function(t1, t2) print("mt1->sub") end
mt2.__sub = function(t1, t2) print("mt2->sub") end
local t1 = {}
local t2 = {}
local t3 = {}
setmetatable(t1, mt1) -- 设置 mt1 为 t1(普通表)的元表
setmetatable(t2, mt2) -- 设置 mt2 为 t2(普遍表)的元表
local res1 = t1 - t2 -- 计算过程中调用元表的 mt1.__sub 元方法
print("mt1->sub") -- 模拟输出
local res2 = t2 - t1 -- 计算过程中调用元表的 mt2.__sub 元方法
print("mt2->sub") -- 模拟输出
local res3 = t3 - t1 -- 由于 t3 没有元表 __sub 元方法,所以调用 t1 的元表中的元方法
print("mt1->sub") -- 模拟输出
2.2 __tostring(print() 时触发)
local mt = {}
mt.__tostring = function(tab)
    local str = ""
    for index, value in pairs(tab) do
        str = str .. index .. "--" .. value .. "\n"
    end
    return str
end
local tab = {1, 2, 3}
setmetatable(tab, mt)
print(tab)

输出结果:

1--1
2--2
3--3
2.3 __index(访问表中不存在属性时触发)
  1. __index 是一个表
local mt = {}
mt.__index = {sex = "boy"}
local tab = {name = "ming", age = 18}
print(tab.name, tab.age) -- ming 18
print(tab.sex) -- nil
setmetatable(tab, mt)
print(tab.sex) -- boy
print(tab.enjoy) -- nil
  1. __index 是一个函数
local mt = {}
mt.__index = function(table, key)
    print(table) -- 打印 t 表
    print(key) -- 打印 name
end
local t = {}
setmetatable(t, mt)
print(t.name) -- t 表不可以找到,调用元表的 __index 元方法

输出结果:

table: 0000026EFEE9F4C0 name nil
2.4 __newindex(对 table 中不存在的字段赋值时调用)
  1. 普通表修改键值 存在则修改,不存在就会增加
local t = {name = "Y"}
t.name = "YY" -- 修改
t.age = 23 -- 添加
for key, value in pairs(t) do -- 无序遍历字典类型表
    print(key .. " : " .. value)
end

输出结果:

age : 23
name : YY
  1. __newindex 是一个函数 调用 __newindex 函数,但是不会给元表赋值
local mt = {}
mt.__newindex = function(table, key, value)
    print(table)
    print("key:" .. key)
    print("value:" .. value)
end
local t = {}
setmetatable(t, mt)
print(t.name) -- nil
t.name = "YY"
print(t.name) -- 赋值后先调用__newindex 函数然后打印 nil

输出结果:

nil
table: 0000012C2529F5F0
key:name
value:YY
nil
  1. __newindex 是一个表 如果普通表没有该变量,那么到元表查找,并在元表新增或修改变量值
local k = {name = "ming"}
local mt = {}
mt.__newindex = k
local t = {}
setmetatable(t, mt)
print(t.name) -- nil 查询
print(k.name) -- Y 查询
t.name = "YY" -- 到对应的 k 表修改
print(k.name) -- YY 查询
print(t.name) -- nil 查询

输出结果:

nil
ming
YY
nil

目录

  1. 1. 元表 (Metatable)
  2. 2. 元方法
  3. 2.1 __add(对表进行“+”操作时触发)
  4. 2.2 __tostring(print() 时触发)
  5. 2.3 __index(访问表中不存在属性时触发)
  6. 2.4 __newindex(对 table 中不存在的字段赋值时调用)
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 生成 4 位随机数的多种实现方法与最佳实践
  • C++ 模板编程:typename 关键字与分离编译陷阱
  • FPGA 基础概念与架构面试题详解
  • Java RESTful 接口开发:Spring Boot 实战指南
  • AI 前端提示词设计与高效交互实践
  • LogiOps 在 Linux 下配置 Logitech 鼠标完整教程
  • 使用 Java 计算 1 到 20 的阶乘之和
  • 自主无人机硬件搭建及 EGOPlanner 实现
  • 开源游乐场收银台与押金系统多场景收银能力设计
  • Faster-Whisper 本地实时语音转文本部署指南
  • 基于 YOLOv5 的深度学习火焰检测与识别系统
  • 阶跃星辰开源图生视频模型,大模型落地引发市场关注
  • Java 入门实战:从环境配置到 Hello World
  • Ground Slow, Move Fast: Dual-System Foundation Model for VLN
  • MySQL 基本查询进阶:分页、更新、删除与聚合函数
  • Stable Diffusion 整合包安装与使用指南
  • 程序员身份认同与银行服务的定制化探索
  • 玩转Llama Factory:打造你的第一个角色扮演AI
  • Gitee 版本控制新手入门指南
  • 集群中继无人机应急通信双层多目标协同优化部署

相关免费在线工具

  • 数学计算器

    计算数学表达式的计算器。您可以使用sqrt、cos、sin、abs等函数。 在线工具,数学计算器在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online