lua:浅谈对元表和元方法的认识

news2025/1/11 10:19:52
前言
本篇在讲什么

浅谈对Lua元表和元方法的理解
本篇适合什么

适合初学Lua的小白
本篇需要什么

Lua语法有简单认知
依赖Lua5.1的环境
依赖Sublime Text3编辑器

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


目录

  • ♠ 元表和元方法
    • ♥ 元表
    • ♥ 获取元表
    • ♥ 设置元表
    • ♥ 元方法
      • ♣ 算数运算相关的元方法
        • ♦ 两表相加的简单示例
        • ♦ 两组不同数据相加的示例
      • ♣ 关系运算相关的元方法
      • ♣ 库定义相关的元方法
      • ♣ 表相关的元方法
        • ♦ __index元方法
        • ♦ __newindex元方法
  • ♠ 推送
  • ♠ 结语


♠ 元表和元方法

个人浅见,元表就是Lua中对某一个数据或者某一类数据的扩展和补充,而元方法就是已经被定义好功能的可被重写的函数

以最常见的表举例:

local t = {}
local t1 = {}
t1.__index = function(_, key)
    return tbl[key]
end
setmetatable(t, t1) 

print(t[key])

当我们为表t设置元表t1后,并在元表t1中补充__index元方法,当我们根据键key从表t中获取数据的时候,如果t中没有,那么就会去拿__index的返回值

下面我们将更细节讨论元表和元方法


♥ 元表

  • 元表就是一个表

  • Lua语言中的每一个值(所有类型)都可以有元表

  • 每个表(table)和用户数据类型(userdata)都具有各自独立的元表

  • 其他类型共享同类型所属的同一个元表(所有字符串string共用一个元表)

  • 新创建的表没有元表

  • 字符串都有一个默认的统一元表,其他类型默认没有元表

  • 在Lua代码中我们仅能为表(table)添加元表,其他类型可通过c或调试库


注:一个表还可以成为他自己的元表


♥ 获取元表

t = {}
getmetatable(t) 

通过方法getmetatable获取元表


♥ 设置元表

t = {}
t1 = {}
setmetatable(t, t1) 

通过方法setmetatable将t1设置为t的元表


♥ 元方法

元表为定义的各种行为,每个行为都关联对应的元方法,元方法可以简单的分为以下几大类型,我们简答叙述和举例演示


♣ 算数运算相关的元方法

下面表格记录了和算数运算相关的元方法及其功能描述

元方法名功能描述
__add加法
__sub减法
__mul乘法
__div除法
__idivfloor除法
__unm负数
__mod取模
__pow幂运算
__band
__bor
__bxor异或
__bnot取反
__shl向左移位
__shr向右移位
__concat连接运算符

♦ 两表相加的简单示例

local t_1 = {1,2,3}
local t_2 = {4,5,6}

local t1 = {}

t1.__add = function(a,b)
    local tbl = {}
    for k,v in pairs(a) do
        table.insert(tbl,v)
    end
    for k,v in pairs(b) do
        table.insert(tbl,v)
    end
    return tbl
end

setmetatable(t_1, t1) 

local result = t_1+t_2
print(result[1],result[2],result[3],result[4],result[5],result[6])

在这里插入图片描述

我们来简单分析一下:

  • 我们希望两个表通过算数运算符+达到一个相加的目的
  • 为表t_1添加元表t1
  • 为元表添加代表相加的元方法__add
  • 执行t_1+t_2的操作,我们获取到了一个融合的表

问题剖析一下:

问题1: 为什么只为表t_1设置了元表

实际上算数类的元方法的执行并不需要二者同时具备
当执行+的操作时,会按相加顺序从两者中检索__add元方法
以第一个检索到的元方法为执行方案
二者都没有__add元方法,则抛异常出来

问题2: 两者融合具体的行为处理

元方法__add的参数a和b,即为相加的二者
在方法体内,我们可以自定义融合逻辑
在上述例子中,我们创建新表容纳了参数所有的子集,然后返回


♦ 两组不同数据相加的示例

实际上相加只是一个广义的行为,Lua并不局限于同类型数据之间的操作
存在元方法的情况下,我们可以对任意数据进行相加的操作
下述例子我们尝试对表(table)字符串(string)相加

local t_1 = {1,2,3}
local t_2 = "aaaaa"

local t1 = {}

t1.__add = function(a,b)
    local temp = ""
    for k,v in pairs(a) do
        temp = temp..v
    end
    temp = temp .. b
    return temp
end

setmetatable(t_1, t1) 

print(t_1+t_2)

在这里插入图片描述

我们只需要在元方法__add的方法体内对不同类型的数据做好处理即可
上述例子中我们将表内子集和字符串连接成了一个新字符串作为返回值


注:其他算数元方法使用方式和例子中的__add一样


♣ 关系运算相关的元方法

元方法名功能描述
__eq等于
__lt小于
__le小于等于

Lua的关系运算符其实只有三个分别是:

  • 等于(a==b)
  • 小于(a<b)
  • 小于等于(a<=b)

对于其他三种运算关系,Lua会对其进行转换

  • 不等于(a~=b -> not (a==b))
  • 大于 (a>b -> b<a)
  • 大于等于 (a>=b -> b<=a)

和算数运算有区别:

注:关系运算二者必须共用相同的元表!!

在这里插入图片描述

注:不同数据只有相等可以比较,但是会一直返回false

在这里插入图片描述

注:不同数据除相等的比较,均会抛出异常

在这里插入图片描述


♣ 库定义相关的元方法

程序库在元表中定义和使用它们自己的字段也是一种常见的实践

常见例子1:tostring

在这里插入图片描述
在这里插入图片描述

我们输出print时候,会优先检索目标是否包含__tostirng元方法,如果存在,则会根据方法输出

常见例子2:

在这里插入图片描述

可以通过设置元表__metatable字段,使用户既不能看到也不能修改元表


♣ 表相关的元方法

♦ __index元方法

类似于C#中属性的get方法,获取表值的时候,如果存在该元方法,在不存在对应key值的情况下,回去所求__index的返回值

在这里插入图片描述


♦ __newindex元方法

类似于C#中属性的set方法,在对表赋值的时候,如果key值不存在并且__newindex存在,则会调用该元方法

在这里插入图片描述


注:我们可以用这两个元方法去制作一些受限制的表,例如只读只写、不能修改的表等等


♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/529752.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ETCD实现分布式锁

分布式锁具备特点 互斥性&#xff1a;在同一时刻&#xff0c;只有一个客户端能持有锁 安全性&#xff1a;避免死锁&#xff0c;如果某个客户端获得锁之后处理时间超过最大约定时间&#xff0c;或者持锁期间发生了故障导致无法主动释放锁&#xff0c;其持有的锁也能够被其他机制…

ANR实战案例 - FCM拉活启动优化

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、Trace日志分析二、业务分析1.Firebase源码分析2.Firebase官方查看官方文档Dem…

数据压缩新利器!小精灵ELF助你高效存储与传输

存储空间不够用&#xff1f;网络传输太慢&#xff1f;想必每个人在生活中都会遇到这些问题。看着爆满的硬盘、焦急的等待数据的接受&#xff0c;更新设备&#xff1f;不是每个人都能承担这个成本。那不如尝试一下无损压缩&#xff1f; 为了减少存储空间的占用&#xff0c;提高…

《Netty》从零开始学netty源码(五十七)之ServerBootstrap.bind()

目录 ServerBootstrap.bind()initAndRegister()init()register()doBind0() ServerBootstrap.bind() 在第一篇的HelloWorld中通过ServerBootstrap.bind()方法绑定端口号并最终启动Netty的服务&#xff0c;服务端的bind过程如下&#xff1a; 上面的代码主要分成两部分&#xff0…

【P20】JMeter XPath提取器(XPath Extractor)

文章目录 一、准备工作二、测试计划 一、准备工作 百度&#xff1a;https://www.w3school.com.cn/example/xmle/cd_catalog.xml 进入网页后&#xff0c;右键检查或按F12&#xff0c;打开调试工具 如图&#xff0c;使用XPath提取器&#xff08;XPath Extractor&#xff09;获取…

typescript学习笔记(下)

1、类型拓宽 所有通过 let 或 var 定义的变量、函数的形参、对象的非只读属性&#xff0c;如果满足指定了初始值且未显式添加类型注解的条件&#xff0c;那么它们推断出来的类型就是指定的初始值字面量类型拓宽后的类型&#xff0c;这就是字面量类型拓宽。 下面我们通过字符串…

数据结构-排序-(选择、堆排序、归并排序、基数排序)

目录 一、选择排序 二、堆排序 排序 效率分析 三、归并排序 排序 分析 四、基数排序 一、选择排序 思想&#xff1a;每趟在待排序元素中选取关键字最小的元素加入有序子列 不稳定性 空间复杂度&#xff1a;O(1) 时间复杂度&#xff1a; void swap(int &a,int &…

[Linux] 动态 / 静态库的生成与使用

文章目录 简要概念 静态库生成使用 动态库生成使用 简要概念 库一般分为两种&#xff1a; 静态库动态库 在 Linux 中&#xff1a; 如果是动态库&#xff0c;库文件是以 .so 作后缀的如果是静态库&#xff0c;库文件是以 .a 作后缀的 库文件的命名&#xff1a; libXXX.so …

RBTree

目录 红黑树的概念 红黑树性质 红黑树节点设计 红黑树的插入 红黑树的验证 红黑树和AVL树的比较 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的…

Point-SLAM: Dense Neural Point Cloud-based SLAM阅读记录

前言 只读了前半部分就感慨文章结构真的好清晰&#xff0c;从Introduction到related work完完全全都在体现它的motivation——他做了一件什么事情&#xff1f;以及为什么要这么做&#xff1f;解决了什么问题。 第一遍阅读 keywords: 以RGBD作为输入 使用点云表示场景的 dens…

【P21】JMeter XPath2 提取器(XPath2 Extractor)

文章目录 一、准备工作二、测试计划 一、准备工作 百度&#xff1a;https://www.w3school.com.cn/example/xmle/cd_catalog.xml 进入网页后&#xff0c;右键检查或按F12&#xff0c;打开调试工具 如图&#xff0c;使用XPath2 提取器&#xff08;XPath2 Extractor&#xff09;…

python 使用pandas或xlrd、xlwt实现对Excel的读取、添加、追加等一系列封装

不说了&#xff0c;又是造轮子的一天。在此我要严重批评CSDN或百度一堆浑水摸鱼的&#xff0c;某些人明明代码明显报错也来上传发博客&#xff0c;要么就是标题党&#xff0c;代码没报错但压根就不是实现那个功能的&#xff0c;简直是浪费时间。 废话不多说直接贴代码&#xff…

Linux—网络基础

目录 计算机网络背景 网络发展 认识 "协议" 网络协议初识 协议分层 OSI七层模型 TCP/IP五层(或四层)模型 网络传输基本流程 协议报头 局域网通信 网络传输流程图 局域网通信图 跨网络通信图 数据包封装和分用 网络中的地址管理 认识IP地址 认识MAC地址…

8款主流产品原型设计软件分享

在产品设计中&#xff0c;你知道如何选择合适的产品设计软件吗&#xff1f;每个产品设计软件的功能实际上是不同的&#xff0c;不同的产品设计软件应用领域是不同的。 只有深入了解每个产品设计软件的功能和主要适合该软件的行业&#xff0c;我们才能在设计相应的产品时找到合…

linux内核篇-进程及其调度

介绍一个程序从源文件到进程执行的过程 1、编译链接&#xff08;源文件到二进制文件&#xff09; Linux 下面二进制的程序也要有严格的格式&#xff0c;称为ELF&#xff08;Executeable and Linkable Format&#xff0c;可执行与可链接格式&#xff09; &#xff0c;这个格式可…

Simulink 和 Gazebo联合仿真控制机械臂【Matlab R2022a】

逛 B 站&#xff0c;偶然发现一个 up 主上传的视频&#xff0c;可以实现 Simulink 中搭建机器人的控制器设计&#xff0c;对运行在虚拟机中 Gazebo 中的机械臂进行控制&#xff0c;链接&#xff1a;三关节机械臂Gazebo-Simulink联合仿真&#xff0c;这让我很感兴趣&#xff0c;…

Web基础 ( 一 ) HTML

1.HTML <input /><input typebutton value按钮 />1.1.概念 1.1.1.HTML文件是什么 HTML表示超文本标记语言&#xff08;Hyper Text Markup Language&#xff09;, HTML文件是一个包含标记的文本文件, 必须有htm标记或者html扩展名。 可以通过浏览器(Browser)直接…

如何用自己公司的知识、流程等来训练Chat GPT?

在玩过 ChatGPT 并向它询问有关世界、金融和初创公司的一般问题后&#xff0c;我开始思考&#xff1a;“如果我可以用我自己的初创公司甚至大型公司的所有流程、知识和商业经验来训练 AI 模型会怎样&#xff1f;企业&#xff1f;” 使用您自己公司的知识、流程等培训 ChatGPT …

华为OD机试 - 计算网络信号、信号强度( Python)

题目描述 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。 注意:网络信号可以绕过阻隔物。 array[m][n] 的二维数组代表网格地图, array[i][j] = 0代表i行j列是空旷位置; array[i][j] = x(x为正整数)代表i行j列是信号源,…

Python实现哈里斯鹰优化算法(HHO)优化XGBoost回归模型(XGBRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 2019年Heidari等人提出哈里斯鹰优化算法(Harris Hawk Optimization, HHO)&#xff0c;该算法有较强的全…