Lua 元表和元方法
一、元表
元表可以修改一个值在面对一个未知操作时的行为,Lua 中使用 table 作为元表的承载。
元表只能给出预先定义的操作集合的行为,比类会更加受限制,不支持继承。
Lua 每一个值都可以有元表 :
- 表和用户数据类型都具有各自独立的元表;
- 其他类型的值则共享对应类型所属的同一个元表;
二、元表的设置
1、类型的原始元表
Lua 中,元表的设置只能针对 table ,其他类型都不能设置。
table 的初始化元表为 nil ,即没有设置元表,只能通过 setmetatable 进行设置,多个 table 可以共享一个 table 作为元表(当然也可以使用他自己作为自己的元表,因为他自身也是一个 table)
Lua 只有 string 初始化了元表,而且是针对了所有的字符串,即 string 都是同一个元表。其他的类型为 nil 。
print("表的初始值", getmetatable({})) --> 表的初始值 nilprint("整型的初始值", getmetatable(10)) --> 整型的初始值 nil
print("浮点型的初始值", getmetatable(10.0)) --> 浮点型的初始值 nil--- 通过打印可以看到两个字符串的元表是同一个
print("字符串的初始值", getmetatable("江澎涌")) --> 字符串的初始值 table: 0x600000b14640
print("字符串的初始值", getmetatable("jiangpengyong")) --> 字符串的初始值 table: 0x600000b14640print("布尔型的初始值", getmetatable(true)) --> 布尔型的初始值 nilprint("nil的初始值", getmetatable(nil)) --> nil的初始值 nilfunction sayHello() end
print("函数的初始值", getmetatable(sayHello)) --> 函数的初始值 nil
2、设置元表和获取元表
2-1、setmetatable(table, metatable)
给表 table 设置元表 metatable
参数
- table:要被设置元表的表
- metabale:元表,如果值为 nil ,则表明要删除 table 的原有元表。如果原来的元表有
__metatable字段,则不能再设置元表,否则会抛出异常cannot change a protected metatable
__metatable会在下面的 “表相关方法” 小节分享
返回值:
返回被设置元表的表,就是参数 table
2-2、getmetatable(object)
如果 object 没有元表,则返回 nil
如果对象 Object 有元表,且该元表有一个 "__metatable" 字段,则返回关联的值。否则,返回给定对象 Object 的元表
2-3、举个例子
local oriTable = {}
local metaTable = {}
print(setmetatable(oriTable, metaTable), oriTable, metaTable) --> table: 0x600001ac0840 table: 0x600001ac0840
print(getmetatable(oriTable), metaTable) --> table: 0x600001ac0900 table: 0x600001ac0900
给元表带有 __metatable 字段的表,设置新的元表,则会抛出异常(见下图)
t2 = { c = 1 }
t2.__metatable = { a = 1 }
s1 = {}
setmetatable(s1, t2)
print('getmetatable(s1)["a"]', getmetatable(s1)["a"]) --> getmetatable(s1)["a"] 1-- 此处会抛出异常:cannot change a protected metatable
print(setmetatable(s1, {}))

三、元表方法
1、具有的元方法
元表方法方法很像 kotlin 中的操作符方法
1-1、算术运算符
| 元表方法 | 含义 |
|---|---|
| __add | 加法 |
| __mul | 乘法 |
| __sub | 减法 |
| __div | 除法 |
| __floor | floor除法 |
| __unm | 负数 |
| __mod | 取模 |
| __pow | 幂运算 |
| __band | 按位与 |
| __bor | 按位或 |
| __bxor | 按位异或 |
| __bnot | 按位取反 |
| __shl | 向左移 |
| __shr | 向右移 |
| __concat | 定义连接运算符 |
1-2、关系运算符
| 元表方法 | 含义 |
|---|---|
| __eq | 等于 |
| __lt | 小于 |
| __le | 小于等于 |
值得注意: ~=、a > b、a >= b 没有对应的元方法,会被转为如下
a ~= b会被转为not( a == b)a > b会被转为b < aa >= b会被转为b <= a
关系运算符遇到两个不同类型的对象,则会直接返回 false ,不会进行搜寻任何的元方法
1-3、库相关方法
| 元表方法 | 含义 |
|---|---|
| __tostring | 当调用 tostring 时,会先检查值是否有一个元方法 __tostring ,有则会先使用。 |
| __metatable | 使用该元方法可以保护元表,用户无法获取也无法修改该元表。当元表设置了 __metatable 的字段,则 getmetatable 会返回这个字段的值,而 setmetatable 则会引发错误 |
| __pairs | 从 Lua 5.2 开始,当元表拥有一个 __pairs 的元方法时,pairs 会调用这个元方法来完成遍历 |
1-4、表相关方法
| 元表方法 | 含义 |
|---|---|
| __index | 一旦访问 table 中不存在的字段,正常情况下会返回 nil 。如果设置了这个元表方法,则会调用自身元表对应的该 __index 元方法,并以被调用的表(即此处的 table ,不是元表)和键作为参,进行调用。也可以给 __index 设置一个 table,这样就会直接在这table 中查询,速度比方法稍快。可以通过 rawget 获取原始数据,不考虑元表。 |
| __newindex | 当调用 table 进行索引赋值时,如果设置了该元表方法,则会使用被调用的表(即此处的 table ,不是元表),键和值作为参,调用该方法。同样也可以给 __newindex 设置一个表,则会将值直接存至该表。可以通过 rawset(talbe, key, value) 相当于 table[key] = value 进行直接对 table 的赋值,不考虑元表。 |
| __len | 获取 table 的长度时,会调用该方法,获取长度 |
__index 和 __newindex 的异同
- 相同点:两个函数都是发生在 table 中没有对应的 key 时触发
- 不同点:当前需要的索引没有对应的值时则调用
__index,如果 table 设置值时,则调用__newindex
2、元方法的搜索
如果两个变量相加,搜索规则如下:
- 先查看第一个值是否有元表,并且是否存在所需元方法,如果存在则使用该元方法,此时第二个值的元方法被忽略。否则进入下一条
- 查看第二个值是否有元表,并且是否存在所需的元方法,如果有则进行使用。否则进入第三条
- 抛出异常
3、举个例子
这里元方法比较多,就不一一粘贴代码了,不然会让文章非常冗长。建议各位童鞋们移步 github clone 下代码自行运行一下会更加深刻理解。
“算术运算符” 、 “关系运算符”、“库相关方法” 相关的代码 可以查看以下的代码:
集合.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E9%9B%86%E5%90%88.lua
集合调用.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E9%9B%86%E5%90%88%E8%B0%83%E7%94%A8.lua
“表相关方法” 相关的代码
表相关元方法.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E8%A1%A8%E7%9B%B8%E5%85%B3%E5%85%83%E6%96%B9%E6%B3%95.lua
四、写在最后
Lua 项目地址:Github传送门 (如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)
如果觉得本篇博文对你有所启发或是解决了困惑,点个赞或关注我呀。
公众号搜索 “江澎涌”,更多优质文章会第一时间分享与你。
相关文章:
Lua 元表和元方法
一、元表 元表可以修改一个值在面对一个未知操作时的行为,Lua 中使用 table 作为元表的承载。 元表只能给出预先定义的操作集合的行为,比类会更加受限制,不支持继承。 Lua 每一个值都可以有元表 : 表和用户数据类型都具有各自…...
【Git】01-Git基础
文章目录 Git基础1. 简述1.1 版本管理演变1.2 Git的特点 2. Git安装2.1 安装文档2.1 配置user信息 3. 创建仓库3.1 场景3.2 暂存区和工作区 4. 重命名5. 常用git log版本历史5.1 查看当前分支日志5.2 简洁查看日志5.3 查看最近指定条数的日志 6. 通过图形界面工具查看版本7. 探…...
【Vue2.0源码学习】生命周期篇-初始化阶段(initState)
文章目录 1. 前言2. initState函数分析3. 初始化props3.1 规范化数据3.2 initProps函数分析3.3 validateProp函数分析3.4 getPropDefaultValue函数分析3.5 assertProp函数分析 4. 初始化methods5. 初始化data6. 初始化computed6.1 回顾用法6.2 initComputed函数分析6.3 defineC…...
专升本英语零基础学习
1. 词法 1.1 名词 名词(n.),是词类的一种,属于实词。他表示人,物,事,地点或抽象概念的统一名称。 1.1 名词的含义 名词(n.),是词类的一种,属于实词。他表示人&#x…...
QUIC协议连接详解(二)
目录 一:RTT解释 二:QUIC 1-RTT连接 三:QUIC 0-RTT连接 一:RTT解释 在介绍QUIC协议的连接之前先科普一下什么是RTT。RTT是Round-Trip Time的英文缩写,翻译过来就是一趟来回的时间即往返时延。时间计算即从发送方发送…...
JAVA 经常遇到一些问题【第二部分36~51】
重拾者: 每日记录至目前(记录51种不同场景的问题可参考解决方案) 异常就两部分: 1、excepiton信息: 报错产生的原因 2、at开头表示: 异常产生的代码位置。 欢迎关注本人微信公众号:AIM…...
蓝桥杯打卡Day6
文章目录 N的阶乘基本算术整数查询 一、N的阶乘OI链接 本题思路:本题是关于高精度的模板题。 #pragma GCC optimize(3) #include <bits/stdc.h>constexpr int N1010;std::vector<int> a; std::vector<int> f[N];std::vector<int> mul(in…...
spark集群问题汇总
一、 磁盘问题 问题描述可能原因解决措施core节点磁盘不足, 并且持续增加未开启spark-history的日志清理打开日志清理: spark.history.fs.cleaner.enabled task节点磁盘不足 APP应用使用磁盘过大: 1. 严重的数据倾斜 2. 应用本身数据量大 1. 解决数据倾斜 2. 加大资源, 增加e…...
WebServer 解析HTTP 请求报文
一、TCP 状态转换 浏览器访问网址,TCP传输全过程 二、TCP协议的通信过程 三、TCP 通信流程 // TCP 通信的流程 // 服务器端 (被动接受连接的角色) 1. 创建一个用于监听的套接字- 监听:监听有客户端的连接- 套接字:这…...
Golang开发--interface的使用
在Go语言中,接口(interface)是一种特殊的类型,它定义了一组方法的集合。接口为实现多态性提供了一种机制,允许不同的数据类型实现相同的方法,从而可以以统一的方式处理这些不同类型的对象。接口在Go中广泛用…...
2023 年高教社杯全国大学生数学建模竞赛题目 B 题 多波束测线问题
B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀速直线传播,在不同界面上产生反射,利用这一原理,从测量船换能器垂直向海底发射声波信号,并记录从声波发射到信号接收的传播…...
leetcode算法题--生成特殊数字的最少操作
原题链接:https://leetcode.cn/problems/minimum-operations-to-make-a-special-number/description/ 感觉还是比较难想到的。。 func minimumOperations(num string) int {res : len(num)if strings.Contains(num, "0") {res-- }f : func(tail string)…...
数学建模--决策树的预测模型的Python实现
目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 """ 决策树的应用:对泰坦尼克号数据集成员进行预测生死 算法流程还是比较简单的,简单学习一下决策树跟着注释写即可 文章参考:https://zhuanlan.zhihu.com/p/133838427 算法种遇上sklear…...
Linkstech多核并行仿真丨光伏发电系统模型及IEEE 39 bus模型多核并行实测
新能源场站和区域电网作为复杂且具有动态特性的大规模电力系统,需要实时仿真测试来验证其性能、稳定性和响应能力。在这种背景下,多核并行仿真运算显得尤为重要。多核并行仿真能够同时处理电力系统的复杂模型,加速仿真过程,实现接…...
在STS里使用Gradle编译Apache POI5.0.0
1、到官方下面地址下载Gradle最新的版本 Gradle Distributions 2、解压后拷贝到D盘下D:\gradle-8.3-rc-4里 3、配置环境变量 新建系统变量 GRADLE_HOME ,值为 路径 4、在 Path 中添加上面目录的 bin 文件路径 (可以用 %GRADLE_HOME%\bin,…...
golang - 使用有缓冲通道控制并发数
在 Go 语言中,使用带缓冲的通道(buffered channels)可以有效地控制并发数。带缓冲的通道可以让你限制同时运行的 goroutine 数量,从而避免过度并发导致的资源耗尽问题。以下是一个使用带缓冲通道控制并发数的示例: pa…...
AUTOSAR测试指标
测试方法 1、测试相关时间2、检查各个状态下ECU的情况3、程序编写 1、测试相关时间 序号时间参数描述测试方法时间1T_Wakeup从睡眠模式到网络模式,(上位机)发送NM报文的时间唤醒源的时间100ms2T_START_NM从睡眠模式到网络模式,DUT发送的第一帧NM报文捕获…...
Vue 前端项目使用alibaba矢量库svg图标
Vue 前端项目使用alibaba矢量库svg图标 这里主要是记录 vue项目中使用阿里矢量库图标的操作流程,方便以后查阅!!! 一、简介 iconfont 是由阿里巴巴体验团队打造的,一款设计和前端开发的便捷工具.拥有着很强大且图标内…...
蓝桥杯官网填空题(距离和)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 两个字母之间的距离定义为它们在字母表中位置的距离。例如 A 和 C 的距离为 2,L 和 Q 的距离为 5。 对于一个字符串,我们称字符串中两两字符…...
【座位调整】Python 实现-附ChatGPT解析
疫情期间课堂的座位进行了特殊的调整,不能出现两个同学紧挨着,必须隔至少一个空位,给你一个整数数组desk,表示当前座位的占座情况,由若于0和1组成,其中 0 表示没有占位,1表示占位。在不改变原有座位秩序情况下,还能安排坐几个人? 输入描述: 第一行是一个数组,表示作为…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
