Lua 元表,元方法
元表与元方法的概念
Lua中每个值都可具有元表。元表是普通的Lua表,定义了原始值在某些特定操作下 的行为。
例如,当table作为加法的操作数时,Lua检查其“元表”中的“__add”字段是否有 个函数。如果有,Lua调用它执行加法。我们称“元表”中的“键(如__add)”为事件(event),称“值”为元方法(metamethod)。前述例子中的事件(event)是"__add",元方法(metamethod)是执行加法的函数。
又例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。"__add "等即时字段,其对应的值(往往是一个函数或是table)就是"元方法"。
自己的理解:可以理解为“元方法(metamethod)”只存在与“元表”中。或者认为在元表中,元方法才有意义。
Lua创建新的table的同时不会创建元表,但是可以使用“setmetatable”函数为table设置原表
当你通过键来访问table的时候,如果这个键没有值,那么Lua就会寻找该table的元表(metatable)(假定有metatable)中的__index键。如果__index 包含一个表格,Lua会在表格中查找对应的键。如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。__index元方法查看表中元素是否存在,如果不存在,返回结构为nil;如果存在则由__index返回结果。
元方法
常用元方法
- __add:加法
- __sub:减法
- __mul:乘法
- __div:除法
- __unm:相反数
- __mod:取模
- __pow:乘幂
- __index:
- __newindex:
- 等
关系类的元方法
除了加法减法这些算术类的操作之外,大于小于等这些关系类的操作也是有元方法的:
- __eq:等于
- __lt:小于
- __le:小于等于
如果对两个具备不同“元表”的值进行这些比较操作,就会报错,一定要注意,这和加减法的规则不一样。
测试用例
local mtab1 = {}
mtab1.Name = "mtab1 name"
-- 元方法:加法
mtab1.__add = function(t1, t2)local val = "mtab1.__add"-- print(val)return val
end
-- 元方法:减法
mtab1.__sub = function(t1, t2)local val = "mtab1.__sub"-- print(val)return val
end
-- 元方法:小于
mtab1.__lt = function(t1, t2)local val = "mtab1.__lt"print("call metamethod:", val)math.randomseed(os.time())local rval = math.random(1, 10)-- for i = 1, 10 do-- rval = math.random(1, 10)-- endreturn rval < 5
endlocal mtab2 = {}
mtab2.Name = "mtab2 name"
-- 元方法:加法
mtab2.__add = function(t1, t2)local val = "mtab2.__add"-- print(val)return val
end
-- 元方法:减法
mtab2.__sub = function(t1, t2)local val = "mtab2.__sub"-- print(val)return val
endlocal tab1 = {}
local tab2 = {}
local tab3 = {}
local tab4 = {}
-- 元方法:加法,如果没有将 tab4 这是为其它 table 的元表,好像没有意义!!
tab4.__add = function(t1, t2)local val = "tab4.__add"-- print(val)return val
end--此 table 没有元表
local tab5_nomet = {}
-- 元方法:加法
tab5_nomet.__add = function(t1, t2)local val = "tab5_nomet.__add"-- print(val)return val
endlocal tab6 = {}
local tab7 = {}--此 table 没有元表
local tab8_nomet = {}-- 为 table 表设置 元表
setmetatable(tab1, mtab1)
setmetatable(tab2, mtab1)
setmetatable(tab3, mtab2)
setmetatable(tab4, {__index = mtab1})
setmetatable(tab6, tab5_nomet)
setmetatable(tab7, tab4)-------------------------------------------------------- 输出table表的地址
print(tab1, tab2, tab3, tab4, mtab1, mtab2)
-- 输出tabled表的原表地址
-- getmetatable(tab1)与 getmetatable(tab2)的值相等,是因为 tab1 与 tab2 的 元表 都是 mtab1
print(getmetatable(tab1),getmetatable(tab2),getmetatable(tab3),getmetatable(tab4),getmetatable(mtab1),getmetatable(mtab2)
)-- 输出表 key=Name 的值
print("tab1.Name=",tab1.Name,",tab2.Name=",tab2.Name,",tab3.Name=",tab3.Name,",tab4.Name=",tab4.Name,",mtab1.Name=",mtab1.Name,",mtab2.Name=",mtab2.Name
)
------------------------------------------------------------------------------------------------------------
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 都没有元表。所以,报错:attempt to perform arithmetic on local 'mtab1' (a table value)
-- print("mtab1 + mtab2 =",mtab1 + mtab2)
------------------------------------------------------
-- 相同元表:执行元表中的元方法
-- 输出:tab1 + tab2 = mtab1.__add
print("tab1 + tab2 =", tab1 + tab2)
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 输出:tab1 + tab3 = mtab1.__add
print("tab1 + tab3 =", tab1 + tab3)
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 输出:tab1 + tab4 = mtab1.__add
print("tab1 + tab4 =", tab1 + tab4)
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 输出:tab1 + tab5_nomet = mtab1.__add
print("tab1 + tab5_nomet =", tab1 + tab5_nomet)
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 输出:tab5_nomet + tab1 = mtab1.__add
print("tab5_nomet + tab1 =", tab5_nomet + tab1)
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- 输出:tab4 + tab1 = mtab1.__add
print("tab4 + tab1 =", tab4 + tab1)
------------------------------------------------------
-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- tab4有原表,但是没有__add元方法,tab5_nomet也没有__add元方法。所以,报错:attempt to perform arithmetic on local 'tab4' (a table value)
-- print("tab4 + tab5_nomet =",tab4 + tab5_nomet)-- 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,如果没有就看第二个元表是否有元方法。都没有元方法就会报错。
-- tab4有原表,但是没有__add元方法,tab5_nomet也没有__add元方法。所以,报错:attempt to perform arithmetic on local 'tab5_nomet' (a table value)
-- print("tab5_nomet + tab4 =", tab5_nomet + tab4)
------------------------------------------------------
-- 输出:tab5_nomet + tab6 = tab5_nomet.__add
print("tab5_nomet + tab6 =", tab5_nomet + tab6)
-- 输出:tab7 + tab8_nomet = tab4.__add
print("tab7 + tab8_nomet =", tab7 + tab8_nomet)
-- 输出:tab7 + tab4 = tab4.__add
print("tab7 + tab4 =", tab7 + tab8_nomet)
-------------------------------------------------------- 输出:tab1 < tab2 = boolean结果
print("tab1 < tab2 =", tab1 < tab2)
-- 如果对两个具备不同“元表”的值进行这些比较操作,就会报错,一定要注意,这和加减法的规则不一样。
-- 所以,报错:attempt to compare two table values
-- print("tab1 < tab3 =", tab1 < tab3)
print("----------------")
测试用例输出结果
----------------
table: 00C5C9A8 table: 00C5C8E0 table: 00C5C958 table: 00C5C9F8 table: 00C5C9D0 table: 00C5C7F0
table: 00C5C9D0 table: 00C5C9D0 table: 00C5C7F0 table: 00C5C8B8 nil nil
tab1.Name= nil ,tab2.Name= nil ,tab3.Name= nil ,tab4.Name= mtab1 name ,mtab1.Name= mtab1 name ,mtab2.Name= mtab2 name
tab1 + tab2 = mtab1.__add
tab1 + tab3 = mtab1.__add
tab1 + tab4 = mtab1.__add
tab1 + tab5_nomet = mtab1.__add
tab5_nomet + tab1 = mtab1.__add
tab4 + tab1 = mtab1.__add
tab5_nomet + tab6 = tab5_nomet.__add
tab7 + tab8_nomet = tab4.__add
tab7 + tab4 = tab4.__add
call metamethod: mtab1.__lt
tab1 < tab2 = true
----------------
相关文章:
Lua 元表,元方法
元表与元方法的概念 Lua中每个值都可具有元表。元表是普通的Lua表,定义了原始值在某些特定操作下 的行为。 例如,当table作为加法的操作数时,Lua检查其“元表”中的“__add”字段是否有 个函数。如果有,Lua调用它执行加法。我们称“元表”中的“键(如__add)”为事件(event),称…...
C# WPF上位机开发(利用tcp/ip网络访问plc)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 c# wpf如果是用来开发非标上位机的,那么和plc的通信肯定是少不了的。而且,大部分plc都支持modbus协议,所以这个…...
Knife4j 接口文档如何设置 Authorization 鉴权参数?
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…...
CentOS 防火墙管理及使用的redis基本常用命令
文章目录 防火墙管理使用systemctl管理防火墙启动、关闭使用firewalld-cmd配置访问防火墙策略firewalld配置文件修改限制来源IP docker使用 redis 防火墙管理 需要关闭防火墙或者开启对应端口 使用systemctl管理防火墙启动、关闭 启动防火墙: systemctl start fi…...
路由器原理
目录 一.路由器 1.路由器的转发原理 2.路由器的工作原理 二.路由表 1.路由表的形成 2.路由表表头含义 直连: 非直连: 静态 静态路由的配置 负载均衡(浮动路由) 默认路由 动态 三.交换与路由对比 一.路由器 1.路由器…...
采埃孚4D成像雷达拆解
1 基本信息 品牌:海外Tier1采埃孚 • 应用:上汽飞凡中高端纯电平台 • 数量:单车2个,安装在前后保内部 • 最远探测距离:350米 拆解来看,4D雷达主要可以分为4个部分,分别为数字接口板及结构件…...
若依框架springboot——修改前端图片上传样式
简述 使用过若依框架的,一定知道若依前端框架上传图片的样式,是一个正方形加号图片,但是如果你要使用自定义样式呢。 比如将下面这个图进行修改呢 修改后的样式 你可以直接找到element-ui 修改上传图片的组件,也可以加入新的组…...
mysql 数据库 关于库的基本操作
库的操作 如果想到 mysql 客户端当中数据 系统当中的命令的话,直接输入的话,会被认为是 mysql 当中的命令。 所以,在mysql 当中执行系统当中的命令的话,要在系统命令之前带上 ststem ,表示系统命令: 但是…...
【通用】Linux,VSCode,IDEA,Eclipse等资源相对位置
正文 不论是 IDEA、Linux、VSCode、cmd等等吧,都遵循这个规则: 如果以斜杠开头,表示从根开始找: IDEA的根是classpath(classpath就是项目被编译后,位于 target下的 classes文件夹,或者位于ta…...
音视频技术开发周刊 | 323
每周一期,纵览音视频技术领域的干货。 新闻投稿:contributelivevideostack.com。 Meta牵头组建开源「AI复仇者联盟」,AMD等盟友800亿美元力战OpenAI英伟达 超过50家科技大厂名校和机构,共同成立了全新的人工智能联盟。以开源为旗号…...
STM32在CTF中的应用和快速解题
题目给的是bin文件,基本上就是需要我们手动修复的固件逆向。 如果给的是hex文件,我们可能需要使用MKD进行动态调试 主要还是以做题为目的 详细的可以去看文档:https://pdf1.alldatasheet.com/datasheet-pdf/view/201596/STMICROELECTRONIC…...
SaaS 电商设计 (五) 私有化部署-实现 binlog 中间件适配
一、 背景 具体的中间件私有化背景在上文 SaaS 电商设计 (二) 私有化部署-缓存中间件适配 已有做相关介绍.这里具体讨论的场景是通过解析mysql binlog 来实现mysql到其他数据源的同步.具体比如:在电商的解决方案业务流中经常有 ES 的使用场景,用以解决一些复杂的查询和搜索商品…...
Android APP 常见概念与 adb 命令
adb 的概念 adb 即 Android Debug Bridge 。在窗口输入 adb 即可显示帮助文档。adb 实际上就是在后台开启一个 server,会接收 adb 的命令然后帮助管理,控制,查看设备的状态、信息等,是开发、测试 Android 相关程序的最常用手段。…...
菜鸟学习日记(python)——函数
函数是组织好的,用来实现某些功能的代码块,它可以重复使用。 函数能提高应用的模块性,和代码的重复利用率。Python提供了许多内建函数,比如print()。但我们也可以自己创建函数,这被叫做用户自定义函数。 定义函数 用…...
垃圾回收 (GC) 在 .NET Core 中是如何工作的?
提起GC大家肯定不陌生,但是让大家是说一下GC是怎么运行的,可能大多数人都不太清楚,这也很正常,因为GC这东西在.NET基本不用开发者关注,它是依靠程序自动判断来释放托管堆的,我们基本不需要主动调用Collect(…...
Appium 图像识别技术 OpenCV
在我们做App自动化测试的时候,会发现很多场景下元素没有id、content-desc、text等等属性,并且有可能也会碰到由于开发采用的是自定义View,View中的元素也无法识别到,很多的自动化测试框架对此类场景束手无策。Appium在V1.9.0中有给…...
产品Axure的元组件以及案例
前言 产品<Axure的安装以及组件介绍-CSDN博客经过上文我们可以知道我们Axure是一款适用于网站、移动应用和企业软件的交互式原型设计工具。它可以帮助用户创建高保真的交互式原型,包括线框图、流程图、模型、注释和规格等,以便与客户、开发人…...
智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.头脑风暴算法4.实验参数设定5.算法结果6.…...
flutter Pageview组件
PageView组件说明 组件说明PageView,PageController的源码简单demo 组件说明 属性说明scrollDirection滑动反向 Axis.vertical上下滑动 Axis.horizontal左右滑动reverse是否反转 true从最后一个记0controllerPageController见下文physics滚动方式pageSnapping是否有…...
如何用 Cargo 管理 Rust 工程系列 丙
以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/viSsCaFR2x9hZOvo1PoRqA 添加依赖项 前面已经提到过在 cargo 配置文件 Cargo.toml 中如何手动添加工程依赖项,cargo 同样提供了 add …...
Taotoken CLI工具一键配置团队开发环境实战指南
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken CLI工具一键配置团队开发环境实战指南 1. 场景与需求 在团队协作开发中,统一管理大模型调用环境是一个常见且…...
ChatGPT提示词在Discord中失效率高达68%?基于172个真实会话日志的Prompt工程优化矩阵(含Discord专属角色设定模板)
更多请点击: https://intelliparadigm.com 第一章:ChatGPT提示词在Discord中失效率高达68%?基于172个真实会话日志的Prompt工程优化矩阵(含Discord专属角色设定模板) Discord 的异步消息流、上下文截断机制与用户高频…...
消息队列选型对比
目录消息队列选型对比:从核心原理到场景化决策一、快速选型:一张表看懂核心差异二、深入解读:每款 MQ 的设计哲学与适用边界2.1 RabbitMQ:灵活路由的企业级消息代理2.2 Apache Kafka:吞吐为王的日志流平台2.3 Apache R…...
专利数据分析实战:从高通5G专利预测看技术趋势与竞争情报
1. 项目概述:一场关于专利里程碑的预测游戏在科技行业,尤其是半导体和通信领域,专利不仅是技术实力的证明,更是商业竞争的护城河。2018年,美国专利商标局即将迎来一个历史性时刻:颁发第1000万件美国实用专利…...
【JWT】JWS与JWE实战解析:从结构差异到安全选型指南
1. JWT、JWS与JWE的核心概念解析 第一次接触JWT相关技术时,我也曾被各种缩写搞得晕头转向。直到在真实项目中踩过几次坑,才真正理解它们之间的关系。简单来说,JWT就像是一个快递包裹,而JWS和JWE则是两种不同的包装方式——前者像…...
Hermes-Agent 智能体核心能力与实战效能深度评测
在构建自动化工作流或智能客服系统时,开发者最常遇到的痛点往往不是模型本身不够聪明,而是“记不住”和“乱执行”。很多时候,一个智能体在前几轮对话中还逻辑清晰,一旦上下文拉长,就开始遗忘关键约束,或者…...
UWB车内目标探测技术【附仿真】
✨ 长期致力于UWB雷达、活体、目标检测、生命体征、信号模型研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)UWB雷达生命体征信号建模与自适应杂波抑制…...
Gemini插件无法访问本地PDF/网页源码?手把手教你绕过Chrome沙箱限制(含Manifest V3兼容性补丁代码)
更多请点击: https://intelliparadigm.com 第一章:Gemini插件本地资源访问受限的本质原因 沙箱隔离机制的强制约束 Gemini 插件运行于 Chromium 扩展沙箱环境中,该环境默认禁用所有 Node.js API(如 fs、 child_process…...
ChatGPT 2026功能清单泄露事件(OpenAI内部合规审查文档节选):含未公开的「因果推理引擎」与「合规沙盒模式」
更多请点击: https://intelliparadigm.com 第一章:ChatGPT 2026功能清单泄露事件概览 事件背景与时间线 2024年11月,一段标注为“OpenAI Internal – GPT-2026 Roadmap Draft v3.7”的加密ZIP文件在多个匿名开发者论坛意外传播。该文件包含…...
利用taotoken token plan套餐为stm32长期ai项目控制成本
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 利用 Taotoken Token Plan 套餐为 STM32 长期 AI 项目控制成本 对于计划在 STM32 产品中持续集成 AI 功能的项目负责人而言&#x…...
