首页 > 自考资讯 > 自考知识

lua中的table数据结构,lua中table的用法

头条共创 2024-07-05

153084593394501ac9fb87f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720782433&x-signature=yERMGggogE01zUPiM0nd9U%2BtclY%3D 转载自:https://github.com/lujun9972/lujun9972.github.com/blob/source/%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%97%85/lua %E4 %B8%AD%E7%A5%9E%E5%A5%87%E7%9A%84table.org

作者:lujun9972

我最近在尝试建立一个漂亮的WM 时简要了解了lua。 在我的学习过程中,我对Lua对表((tables))的应用彻底着迷了。

表实际上在Lua 中无处不在。首先,表可以用作字典和数组,也可以用来设置闭包环境和模块,还可以用来模拟对象和类。

字典

表最基本的功能就是将其用作字典。 键可以是除nil 之外的任何类型的值。

t={}

t[{}]='table' -- 键可以是表

t[1]='int' -- key 可以是整数

t[1.1]='double' -- key 可以是十进制数

t[function () end]='function' -- key 可以是一个函数

t[true]='Boolean' -- 键可以有布尔值

t['abc']='String' -- 键可以是字符串

t[io.stdout]='userdata' -- key 可以是用户数据

t[coroutine.create(function () end)]='thread' -- key 可以是一个线程

当使用表作为字典时,可以使用pairs函数来迭代表。

对于一对(t) k,v,

打印(k,'-',v)

结尾

执行结果如下。

1-整数

1.1倍

thread:0x220bb08 - 线程

table:0x220b670 - 表

abc - 字符串

文件(0x7f34a81ef5c0) - 用户数据

function:0x220b340 - 功能

true - 布尔值

结果还表明,使用成对遍历时顺序是随机的。事实上,如果多次运行同一条语句,将会得到不同的结果。

表中最常见的两种键类型是整数和字符串。 如果键是字符串,则可以将表用作结构体。同时,写成t['field']的形式可以简写为t.field。

数组

如果键是整数,表可以用作数组。并且这个数组从索引1开始,没有固定长度,并且可以根据需要自动增长。

一个={}

for i=0,5 do -- 请注意,i 是故意写为从0 开始的。

a[i]=0

结尾

当使用表作为数组时,可以使用长度运算符#来获取数组的长度。

打印(#a)

结果如下。

可以看到Lua认为数组a只有5个元素。它的五个元素是什么?您可以使用ipairs 来迭代数组。

对于ipairs(a) 中的i,v 执行

打印(一,五)

结尾

结果如下。

2 0

3 0

4 0

5 0

结果表明,a 的0 索引不被视为数组中的元素。这也验证了Lua中的数组是从1开始索引的。

另外,如果将表用作数组,则需要注意索引不一致。在这种情况下# 长度计算会很奇怪。

一个={}

如果i=1,5 则执行

a[i]=0

结尾

a[8]=0 -- 索引不一致,但长度基于最大索引。

打印(#a)

a[100]=0 -- 索引不一致且长度不基于最大索引。

打印(#a)

结果如下。

8

8

使用ipairs遍历数组时,只会从1开始遍历到下标处。

对于ipairs(a) 中的i,v 执行

打印(一,五)

结尾

结果如下。

2 0

3 0

4 0

5 0

环境(命名空间)

lua 将所有全局/局部变量存储在常规表中。该表通常称为函数的全局或环境(闭包)。

为了方便起见,Lua在创建第一个全局环境时使用全局变量_G来引用全局环境。因此,-G[varname]允许您访问全局变量的值,而无需手动设置环境。

关于k,v 对(_G)

打印(k,'-',v)

结尾

原始平等功能:0x41c2a0

要求功能:0x1ea4e70

_版本- Lua 5.3

调试表:0x1ea8ad0

字符串表:0x1ea74b0

xpcall-function:0x41c720

选择功能:0x41bea0

封装表:0x1ea4820

断言函数:0x41cc50

pcall-function:0x41cd10

下一个函数:0x41c450

tostring-function:0x41be70

_G - 表:0x1ea2b80

协程表:0x1ea4ee0

解包功能:0x424fa0

加载字符串函数:0x41ca00

设置元表函数:0x41c7e0

rawlen-function:0x41c250

位32-table:0x1ea8fc0

utf8-table:0x1ea8650

数学表:0x1ea7770

收集垃圾函数:0x41c650

原始集函数:0x41c1b0

操作系统表:0x1ea6840

配对功能:0x41c950

arg-table:0x1ea9450

表:0x1ea5130

tonumber-function:0x41bf40

io-table:0x1ea5430

加载文件函数:0x41cb10

错误函数:0x41c5c0

加载函数:0x41ca00

打印函数:0x41c2e0

dofile-function:0x41cbd0

rawget-function:0x41c200

类型-功能:0x41be10

获取元表函数:0x41cb80

模块功能:0x1ea4e00

ipairs-function:0x41c970

从Lua 5.2开始,您可以通过更改_ENV的值来设置函数的环境(Lua 5.1中的setfenv从5.2开始已弃用),从而允许该函数的执行语句在新环境中查找全局变量。价值。

a=1 -- 全局变量a=1

local env={a=10,print=_G.print} -- 新环境中a=10,保证全局打印功能可以访问。

函数f1()

local_ENV=环境

print('在f1:a=',a)

a=a*10 -- 改变的是新环境中a的值。

结尾

f1()

print('globally:a=',a)

print('env.a=',env.a)

f1:a=10

全局:a=1

环境a=100

此外,新创建的闭包会继承创建它的函数的环境。

模块

lua 中的模块还返回表供模块用户使用。 该表包含模块导出的所有内容,例如函数和常量。

定义模块的通用模板是:

模块(模块名称,包.seeall)

模块(模块名称)的功能如下。

本地modname=模块名称

local M={} -- M是一个表,存储模块的所有函数和常量

_G[模组名称]=M

package.loaded[modname]=M

setmetatable(M,{__index=_G}) -- package.seeall可以使全局环境_G对当前环境可见。

local _ENV=M -- 设置当前执行环境为M。这样就无需在所有后续代码中限定模块名称,并且定义的所有函数都会自动成为M 的成员。

函数和常量定义

return M -- 模块函数返回模块表,无需手动返回模块表。

对象

表可以用作Lua 中的对象,原因如下:

函数是Lua中的一种值类型,可以直接访问表中的函数值。 这允许表拥有自己的行为和状态:Account={balance=0}

函数Account.withdraw(v)

账户余额=账户余额- v

结尾

Lua支持闭包,可以用来模拟对象的私有成员变量: function new_account(b)

本地余额=b

返回{提款=函数(v)余额=余额-v退出,

get_balance=function() 返回余额结束

}

结尾

a1=新账户(1000)

a1. 提款(10)

打印(a1.get_balance())

990

然而,上面定义对象的第一种方法是有缺陷的。也就是说,该方法绑定到名称Account。 也就是说,该对象必须命名为Account,否则您将收到错误。

a=帐户

帐户=无

a.withdraw(10) -- 报错,因为Account.balance不存在。

为了解决这个问题,给withdraw方法一个额外的参数,指向对象本身。

账户={余额=100}

函数Account.withdraw(self,v)

自平衡=自平衡-v

结尾

a=帐户

帐户=无

a.withdraw(a,10)——没问题。当前self 指向a,因此会搜索a.balance。

打印(a.余额)

90

然而,由于第一个参数self 通常指的是调用该方法的对象本身,Lua 提供了语法糖object:method(.) 来隐藏self 参数的定义和转发。这里的冒号有两个功能。定义函数时在函数的第一个参数位置添加一个额外的隐藏参数sef,调用时在第一个参数位置传递一个额外的隐藏参数self。 也就是说,函数object:method(v) end 相当于函数object.method(self,v) end,object:method(v) 相当于object.method(object,v)。

关于类和继承,使用元表和元方法。事实上,在Lua中对象和类之间并没有严格的区别。

当一个对象在另一个表的__index 元方法中引用时,该表可以引用该对象上定义的方法,因此我们知道该对象是该表的一个类。

类定义的通用模板是:

函数类名:new(o)

o=o 或{}

setmetatable(o,{__index=self})

回去

结尾

或者:

函数类名:new(o)

o=o 或{}

设置元表(o,self)

self.__索引=self

回去

结尾

相反,第二个表示法允许您省略另一个表。

我认为需要解释的另一件事是Lua的元方法是在元表中定义的,而不是在对象本身上定义的。这与其他面向对象语言不同。

点击“了解更多”可访问文内链接

版权声明:本文转载于今日头条,版权归作者所有。如有侵权,请联系本站编辑删除。

猜你喜欢