lua元表详解

用LUA定义一个简单类模型 用最简单的方法编写一个只能继承纯lua类的,lua类 function Class(classname,super) local class_info = {} setmetatable(class_info,{__index = function(owner,key) ::recheck:: if key:find("__") or owner... 阅读详情

元表的作用

元表是用来定义对table或userdata操作方式的表

举个例子

local t1 = {1}
local t2 = {2}
local t3 = t1 + t2

我们直接对两个table执行+运算,会报错

lua: /usercode/file.lua:3: attempt to perform arithmetic on local 't1' (a table value)

因为程序不知道如何对两个表执行+运行,这时候就需要通过元表来定义如何执行t1的+运算,有点类似于c语言中的运算符重载。

local mt = {}
--定义mt.__add元方法(其实就是元表中一个特殊的索引值)为将两个表的元素合并后返回一个新表
mt.__add = function(t1,t2)
    local temp = {}
    for _,v in pairs(t1) do
        table.insert(temp,v)
    end
    for _,v in pairs(t2) do
        table.insert(temp,v)
    end
    return temp
end
local t1 = {1,2,3}
local t2 = {2}
--设置t1的元表为mt
setmetatable(t1,mt)

local t3 = t1 + t2
--输出t3
local st = "{"
for _,v in pairs(t3) do
    st = st..v..", "
end
st = st.."}"
print(st)

结果为:

{1, 2, 3, 2, }

因为程序在执行t1+t2的时候,会去调用t1的元表mt的__add元方法进行计算。
具体的过程是:
1.查看t1是否有元表,若有,则查看t1的元表是否有__add元方法,若有则调用。
2.查看t2是否有元表,若有,则查看t2的元表是否有__add元方法,若有则调用。
3.若都没有则会报错。
所以说,我们通过定义了t1元表的__add元方法,达到了让两个表通过+号来相加的效果

元表的元方法

函数描述
__add运算符 +
__sub运算符 -
__mul运算符 *
__ div运算符 /
__mod运算符 %
__unm运算符 -(取反)
__concat运算符 ..
__eq运算符 ==
__lt运算符 <
__le运算符 <=
__call当函数调用
__tostring转化为字符串
__index调用一个索引
__newindex给一个索引赋值

由于那几个运算符使用类似,所以就不单独说明了,接下来说 __call, __tostring, __index, __newindex四个元方法。

__call

__call可以让table当做一个函数来使用。

local mt = {}
--__call的第一参数是表自己
mt.__call = function(mytable,...)
    --输出所有参数
    for _,v in ipairs{...} do
        print(v)
    end
end

t = {}
setmetatable(t,mt)
--将t当作一个函数调用
t(1,2,3)

结果:

1
2
3

__tostring

__tostring可以修改table转化为字符串的行为

local mt = {}
--参数是表自己
mt.__tostring = function(t)
    local s = "{"
    for i,v in ipairs(t) do
        if i > 1 then
            s = s..", "
        end
        s = s..v
    end
    s = s .."}"
    return s
end

t = {1,2,3}
--直接输出t
print(t)
--将t的元表设为mt
setmetatable(t,mt)
--输出t
print(t)

结果:

table: 0x14e2050
{1, 2, 3}

__index

调用table的一个不存在的索引时,会使用到元表的__index元方法,和前几个元方法不同,__index可以是一个函数也可是一个table。
作为函数:
将表和索引作为参数传入__index元方法,return一个返回值

local mt = {}
--第一个参数是表自己,第二个参数是调用的索引
mt.__index = function(t,key)
    return "it is "..key
end

t = {1,2,3}
--输出未定义的key索引,输出为nil
print(t.key)
setmetatable(t,mt)
--设置元表后输出未定义的key索引,调用元表的__index函数,返回"it is key"输出
print(t.key)

结果:

nil
it is key

作为table:
查找__index元方法表,若有该索引,则返回该索引对应的值,否则返回nil

local mt = {}
mt.__index = {key = "it is key"}

t = {1,2,3}
--输出未定义的key索引,输出为nil
print(t.key)
setmetatable(t,mt)
--输出表中未定义,但元表的__index中定义的key索引时,输出__index中的key索引值"it is key"
print(t.key)
--输出表中未定义,但元表的__index中也未定义的值时,输出为nil
print(t.key2)

结果:

nil
it is key
nil

__newindex

当为table中一个不存在的索引赋值时,会去调用元表中的__newindex元方法
作为函数
__newindex是一个函数时会将赋值语句中的表、索引、赋的值当作参数去调用。不对表进行改变

local mt = {}
--第一个参数时表自己,第二个参数是索引,第三个参数是赋的值
mt.__newindex = function(t,index,value)
    print("index is "..index)
    print("value is "..value)
end

t = {key = "it is key"}
setmetatable(t,mt)
--输出表中已有索引key的值
print(t.key)
--为表中不存在的newKey索引赋值,调用了元表的__newIndex元方法,输出了参数信息
t.newKey = 10
--表中的newKey索引值还是空,上面看着是一个赋值操作,其实只是调用了__newIndex元方法,并没有对t中的元素进行改动
print(t.newKey)

结果:

it is key
index is newKey
value is 10
nil

作为table
__newindex是一个table时,为t中不存在的索引赋值会将该索引和值赋到__newindex所指向的表中,不对原来的表进行改变。

local mt = {}
--将__newindex元方法设置为一个空表newTable
local newTable = {}
mt.__newindex = newTable
t = {}
setmetatable(t,mt)
print(t.newKey,newTable.newKey)
--对t中不存在的索引进行负值时,由于t的元表中的__newindex元方法指向了一个表,所以并没有对t中的索引进行赋值操作将,而是将__newindex所指向的newTable的newKey索引赋值为了"it is newKey"
t.newKey = "it is newKey"
print(t.newKey,newTable.newKey)

结果:

nil nil
nil it is newKey

rawget 和 rawset

有时候我们希望直接改动或获取表中的值时,就需要rawget和rawset方法了。
rawget可以让你直接获取到表中索引的实际值,而不通过元表的__index元方法。

local mt = {}
mt.__index = {key = "it is key"}
t = {}
setmetatable(t,mt)
print(t.key)
--通过rawget直接获取t中的key索引
print(rawget(t,"key"))

结果:

it is key
nil

rawset可以让你直接为表中索引的赋值,而不通过元表的__newindex元方法。

local mt = {}
local newTable = {}
mt.__newindex = newTable
t = {}
setmetatable(t,mt)
print(t.newKey,newTable.newKey)
--通过rawset直接向t的newKey索引赋值
rawset(t,"newKey","it is newKey")
print(t.newKey,newTable.newKey)

结果:

nil nil
it is newKey    nil

元表的使用场景

作为table的元表

通过为table设置元表可以在lua中实现面向对象编程。

作为userdata的元表

通过对userdata和元表可以实现在lua中对c中的结构进行面向对象式的访问。

利用元表实现lua中的面向对象 lua中表结构在查找元素时首先遍历表如果没有找到对应的元素就会通过元方法__index再次查找,当__index被重写成表时就在这个表中查找,如果是function则执行这个方法。这一点和我们在面向对象编程中子类继承父类的属性和方法很相似。我们首先定义一个方法通过设置元表和元方法实现继承。 我们定义一个父类person。拥有属性name和方法speak(),并定义一个子类student继承person 执行他们的speak方法 再通过构造函数创建对象...... 阅读详情

相关推荐

lua中面向对象(class)实现探索(二)

说明:本文亦作为某章节出现在中山大学某实验室编撰的某教材中,本博客博主即该教程的编撰者,因此请不要因为看到本博客和该书中某章内容相同而认为这之间必有作假必有一方抄袭另一方。 云风的实现十分精妙但功能却有限,原因在于这样的实现无法做到一个功能,即在子类的函数中调用父类的同名函数(当然父类的同名函数中可能又调用了父类的父类的同名函数),你可能会说类不是保存了一个super指针吗?我不可以这样吗?

mywcyfl的专栏 6470

Lua实现面向对象class

实现Lua面向对象继承与实例化

nuozhiyou的专栏 360

Lua元表(Metatable)详解

Lua 元表(Metatable)是 Lua 最强大的特性之一,允许自定义 table 的行为。本文详细介绍了元表的概念、核心元方法及其应用场景: 元表本质是包含特殊键(元方法)的普通表,通过 setmetatable/getmetatable 操作 核心元方法包括: __index(访问不存在键) __newindex(写入不存在键) 运算符重载方法(__add, __sub等) __call(使表可调用) __tostring(自定义输出) 实战应用示例: 实现继承和只读表 向量运算重载 函数式对象 自

weixin_58284606的博客 1398

云模型在综合评价过程中的应用

目录 1 云模型标尺(标准云模型)的构建方法 1.1 通过正态云的“3En 规则”来表示评价论域 1.2 通过论域的边界值隶属度相等来表示评价论域 1.3 通过黄金分割法来表示评价论域 2 确定评价结果的过程 2.1 基本云发生器 2.2 X条件云发生器 2.3 两种方法的区别 综合评价问题一般分为以下六个步骤 1、明确评价目的; 2、确定被评价对象; 3、建立评价指标体系(包括收集评价指标的原始值、评价指标的若干预处理等); 4、确立与各项评价指标相对应的权重系数; 5、选..

weixin_62223576的博客 1万+

自动驾驶开发者必看:nuscenes数据集23类物体标注全解析(附避坑指南)

本文深入解析nuscenes数据集的23类物体标注系统,为自动驾驶开发者提供全面的标注规范解读和实战避坑指南。涵盖多模态数据组织、类别细分规则、属性系统应用技巧以及标注质量验证方法,帮助开发者高效利用这一标杆数据集提升模型性能。

weixin_29041767的博客 255

Lua 元表详解

元方法触发条件用途__tostring表转字符串时自定义字符串表示__call表作为函数调用时函数化表对象__add__pow算术运算时运算符重载__eq__le比较运算时比较运算符重载__concat字符串拼接时拼接操作重载__index访问不存在的键时实现继承/默认值__newindex给不存在的键赋值时控制赋值行为元表是 Lua 最强大的特性之一,通过元方法可以完全控制表的行为。合理使用元表可以实现面向对象、操作符重载、属性控制等高级功能。

2301_77213238的博客 385

内网Linux服务器离线安装python包

3、将下载的依赖包和requirements.txt 拷贝到内网主机,依赖包和requirements.txt放同一级目录,进入该目录,运行指令。其实还有个更加方便的办法,联网主机装个与内网主机一样环境的虚拟机,在虚拟机中下载py包,拷贝到内网主机后就能直接安装了,省去手动下载py包的步骤。简单记录下最近遇到的一个小问题,内网主机没有内网源,处于无互联网状态,安装python包只能通过联网主机下载好后拷贝到内网主机。由于内网主机安装了多个版本的python,为了防止搞错,使用这种方式来调用pip安装。

cyc头发还挺多的博客 650

Lua元表详解

今天要来介绍比较好玩的内容——__index元方法 1.我是备胎,记得回头看看咳咳,相信每一位女生都拥有或者不知不觉中拥有了一些备胎,啊,当然,又或许是成为过别人的备胎。没有备胎的人,就不是完整的人生。(小若:停!) 我们来想象一下,如果对一个table进行取值操作,但是table根本就没有这个值呢?比如:复制代码 代码如下: local t = { name = “hehe”, } print(...

Improve_life的博客 291

python DEA: 基于非径向距离NDDF的Malmquist-Luenberger 指数及其分解

点赞发Nature 关注中Science Malmquist-Lenberger指数(ML指数)是距离函数与DEA计算中常用的指数,ML指数可以进一步分解为技术进步technological progress和效率改善effeciency change. 技术进步常被当做增长模型中的全要素生产率,用到许多计量经济研究中,探讨影响技术进步的环境变量。这里我分享一个考虑非期望产出下的NDDF方法计算ML指数。 该ML指数为global ML(区别于sequential ML) import numpy as

Cmmmmm丶的博客 5296

matlab tolx,Nelder-Mead算法matlab

Nelder-Mead算法适合变量数不是很多的方程求极值.原理:Nelder-Mead法是利用多面体来逐步逼近最佳点x*.设函数变量为n维,则在n维空间里多面体有(n+1)个顶点.设x1,x2,...,xn+1为多面体的顶点,且满足:f(x1)<=f(x2)<=...<=f(xn+1)Nelder-Mead法试着将多面体中最差的顶点xn+1(也就是函数的最大点)以新的最佳点替代,...

weixin_36485298的博客 1480

Lua语言之元表(metatable),元方法详解

**(1)**元表作为一个表,可以拥有任意类型的键值对,其真正对被设置的表的影响是Lua规定的元方法键值对。 **(2)**这些键值对就是Lua所规定的键,比如__index,__add,__concat等等。这些键名都是以双下划线__为前缀。其对应的值则为一个函数,被称为元方法(metamethod), **(3)**这些元方法定义了你想对表自定义的操作。如:__index键,在Lua中它所对应...

凉风之魅的专栏 563

Matlab 2023b 科研党必备:MOSEK 10.1.25 安装与配置全记录(附License过期解决方案)

本文详细介绍了在Matlab 2023b中安装与配置MOSEK 10.1.25的全过程,特别针对科研用户提供学术许可申请、证书文件部署及环境集成的实用指南。文章还包含常见问题解决方案和性能调优建议,帮助用户高效完成优化计算任务。

weixin_30598225的博客 171

详解Lua中的元表概念例子解析

Lua中的元表(metatable)是一个非常强大的特性,它允许我们改变表(table)的行为。每个表都可以有一个元表,这个元表是一个普通的表,但是它定义了原始表在特定操作下的行为。元表通过特殊的键(以双下划线__开头)来定义元方法(metamethods),这些元方法可以响应不同的事件,比如索引查找(__index)、赋值(__newindex)、算术运算(__add__sub等)以及其他操作。

IT老农民的博客 1074

从零开始学 AUTOSAR:深入浅出 SAE J1939 诊断通信管理器(J1939Dcm)深度完整版

SAE J1939 是美国汽车工程师学会制定的重型车辆 CAN 总线通信标准,覆盖卡车、客车、工程机械、农机、船舶等,是商用车领域的 “通用语言”。基于CAN 2.0B 扩展帧(29 位 ID)(车规主流)PGN(参数组号)+ SPN(可疑参数号)核心标准:J1939-21:数据链路层(CAN 帧格式、地址声明)J1939-71:应用层(普通信号、报文)诊断层(核心!J1939Dcm 依据)J1939-81:网络管理(地址管理、节点检测)

getusushu的博客 116

Plant Simulation智能行车/天车/起重机建模(1)-基本对象说明

摘要: MultiPortalCrane(多门式起重机)是一种灵活物料搬运设备,适用于造船、钢铁等行业,支持零件预组装、钢板/钢卷智能料场管理及设备装卸。其特点包括: 多门架协同:支持同轨道多门架运行,内置防撞检测; 模块化控制:可独立调节门架、小车及吊钩的速度、加速度和悬臂长度; 多样化搬运:通过目标位置设置或连接器实现零件运输; 故障与统计:可配置MTTR和可用率,实时监控各部件状态。 通过对话框可自定义轨道尺寸、门架数量及运动参数,并支持编程调用(如getPortals方法)。适用于需高精度定位和协同

qq_31964455的博客 315

详解Lua中的元表和元方法例子解析

在Lua中,元表(metatable)是一种强大的机制,它允许我们改变表(table)的行为。每个表都可以有一个关联的元表,元表中可以定义一系列的元方法(metamethods),这些元方法可以覆盖默认的操作,比如算术运算、表的索引访问等。

IT老农民的博客 1051

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Lua元表与元方法详解(转)

Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加。假设a和b都是table,通过元表可以定义如何计算表达式a+b。当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否存在__add字段,如果有,就调用该字段对应的值。这个值就是所谓的“元方法”,这个函数用于计算table的和。  Lua中每个值都有一个元表。t

Change&ce的专栏 6084

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

lua学习笔记16 table元表详解

lua学习笔记16 table元表详解

qq_44910471的博客 204

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

上一篇: Unity Shader 小结
下一篇: C#快速获取JPG图片大小及英寸分辨率
Le_Sam
博客等级 码龄11年 342粉丝 53原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值