当前位置: 首页 > news >正文

Lua基础知识精炼

Lua简介

Lua 是一门强大、高效、轻量级、可嵌入的脚本语言。其设计目标是成为一个能够轻松与其它语言(尤其是 C 和 C++)编写的代码集成的、易于使用的扩展语言。

核心特性

轻量级

体积非常小。完整的 Lua 解释器在经过压缩后只有几百 KB。编译速度快,运行开销低。

可嵌入

这是 Lua 最核心的设计目标。它可以非常方便地嵌入到应用程序(如游戏引擎、网络网关)中,作为该应用的脚本接口,为用户提供灵活的定制和扩展能力。

高效

拥有非常快的执行效率。其虚拟机(Lua VM)是最快的脚本语言虚拟机之一。

跨平台

由于 Lua 完全由 ANSI C 编写,它可以在所有主流操作系统(Windows, Linux, macOS, UNIX, Android, iOS 等)以及各种嵌入式系统和微控制器上运行。

补充

 Lua是一门动态强类型语言。它的灵活性来自于类型的动态性(运行时确定),而它的安全性和严谨性来自于类型的强度(限制隐式转换)。这种结合使得Lua既灵活好用,又不容易产生因隐式转换导致的难以察觉的bug。

典例子:数字和字符串的拼接

local result = "Hello, I am " .. 25 -- 正确:数字 25 被显式地转换成了字符串 "25"
print(result) -- 输出: Hello, I am 25local result = 10 + "5" -- 错误!attempt to perform arithmetic (add) on number and string

第一行代码能成功,是因为字符串连接操作符 .. 显式要求其两边的操作数都必须是字符串。如果不是,Lua会调用tostring()函数将它们转换为字符串。这是一种显式的规则,而不是随意的隐式转换。

第二行代码会抛出错误。算术操作符 + 期望两边都是数字,而Lua不会自动将字符串 "5" 转换成数字 5 来满足这个操作。你必须自己转换:10 + tonumber("5")

运行环境搭建

Sublime Text快速搭建Lua语言运行环境_sublime lua-CSDN博客

基本规范

1、Lua文件的后缀名是.Lua

2、变量

变量命名:Lua语言中的标识符是由任意字母、数字和下画线组成的字符串

注意:

(1)不能以数字开头

(2)“下画线 +大写字母”组成的标识符通常被lua语言用作特殊用途,应避 免使用。

变量类型:使用local修饰的变量是局部变量,未使用local修饰的变量是全局变量

3、打印

4、注释

5、分隔符;

在Lua中每个语句的分隔符";"不是必须的,可写可不写,根据自己的编码习惯决定即可。

6、if else

local a = 1
local b = 2----------第一种
if a == b thenend----------第二种
if a == b thenelse   end----------第三种
if a == b thenelseif a < b thenelse   end

数据类型

Lua语言有8种基本类型:

nil

boolean

number

string

table

function

thread

userdata

布尔

数值

字符串

函数

线程

用户数据

nil 空

1、nil 类型表示无效值,它只有一个值 nil。

2、把nil赋值给一个全局变量时,相当于将该变量删除,Lua会回收该全局变量占用的内存。

boolean 布尔

        boolean 类型只有两个可选值:true(真) 和 false(假)。但Lua 把 false 和 nil 都看作是 false,其他的都为 true(数字 0 和空字符串也是 true)。

number 数值

1、number 类型有两种内部表现方式, 整数 和 浮点数。

2、当需要区分整型值和浮点型值时,可以使用函数math.type

3、整数和浮点数的除法

string  字符串

字符串的声明

1、使用双引号

2、使用单引号

3、使用一对双方括号来声明长字符串/多行字符串。方括号括起来的内容可以包括很多行,并且内容中的转义序列不会被转义

 获取字符串长度

字符串拼接

local str = "好好学习".."天天向上"

字符串反转

字符串转数值

字符串转数值,如果转换失败,会返回nil

变量转字符串

重复拼接字符串

截取字符串

也支持负数索引,-1代表最后一个字符,-2代表倒数第二个字符,以此类推

替换字符串

共有四个参数,第四个参数是设置替换的次数,如果不传则全部替换

转大写字母

转小写字母

查找子串

若找到,则返回子串的开始位置和结束位置;若未找到,则返回nil。

字符串格式化

--格式化一个整数  %d
local str1 = string.format("我的分数是:%d",25)--格式化一个浮点数  %f
local str2 = string.format("圆周率:%f",3.25)--格式化一个字符串  %s
local str3 = string.format("我的名字:%s","卡布奇洛")--添加占位符
local str4 = string.format("%04d",56)

table  表

1、表是Lua语言中最主要和强大的数据结构。可以使用表来表示数组、列表、字典等数据结构。2、表是不固定大小的,可以自动扩容,体现了它的灵活性。

3、当程序中不再有指向一个表的引用时,垃圾收集器会最终删除这个表并重用其占用的内存。

4、用表来实现列表时,是以1为初始索引。(C#是以0开始索引)

表的创建和初始化

表的索引

可以用任意类型的值作为表的索引,但这个值不能为nil

易混淆:

表的遍历

使用数值型for循环

遍历输出所有元素,即使遇到nil也输出

ipairs迭代器遍历

遇到nil会退出

pairs迭代器遍历

遇到nil会跳过,不会退出,继续打印输出后续元素

注意

当表表现字典时

ipairs只能遍历键为数值的字典,并且碰到

1、键为0

2、键为负数

3、值为nil

4、索引不连续

就会退出

pairs可以遍历键为任意数据类型的字典,可以遍历键为0、负数、索引不连续的情况不会退出,遇到值为nil的情况会跳过,输出的情况可能不是表中对应的顺序

表的操作

获取表的长度

table.getn(tab)

#tab

连接表中元素

1、table.concat(tab),无缝拼接元素

2、table.concat(tab,s),以字符串s作为分隔符进行拼接

3、table.concat(tab,s,start),从start索引开始,以字符串s作为分隔符进行拼接

4、table.concat(tab,s,start,end)从start索引开始到end索引结束,以字符串作为分隔符进行拼接

向表中插入数据

1、table.insert(tab,value) 向表tab末尾插入value

2、table.insert(tab,pos,vlaue) 向表tab的pos索引位置插入value

删除表中数据

1、table.remove(tab) 删除tab中最后一个元素

2、table.remove(tab,pos) 删除tab中pos位置的元素

上述都返回被删除的值

对表中元素进行排序

--默认为升序

table.sort(tab)

--降序

table.sort(tab,function(a,b)

return a>b

end)

插入元素
local list = {1,2,3,4,5,6}--重载方法1 在列表末尾插入元素
table.insert(list,666)
--打印:1,2,3,4,5,6,666--重载方法2 在列表指定索引位置插入元素
--例子:在列表list的第3个索引位置处插入元素666
table.insert(list,3,666)
--打印:1,2,666,3,4,5,6
删除元素
local list = {1,2,3,4,5,6}--重载方法1 从列表末尾删除元素
table.remove(list)
--打印:1,2,3,4,5--重载方法2 删除列表指定索引位置的元素
table.remove(list,3)
--打印:1,2,4,5,6
拼接元素

是一个非常高效的方法,用于将数组表中的所有字符串元素连接成一个字符串。它比使用 .. 运算符进行多次连接要高效得多。

类似于C#中的string.Join方法

local list = {1,2,3,4,5,6}
local result
--重载方法1 无缝拼接元素
result = table.concat(list)
--打印:123456--重载方法2 用分隔符进行拼接
result = table.concat(list,",")
--打印:1,2,3,4,5,6--重载方法3 从start索引开始,用分隔符进行拼接
result = table.concat(list,",",3)
--打印:3,4,5,6--重载方法4 从start索引开始到end索引结束,用分隔符进行拼接
result = table.concat(list,",",2,5)
--打印:2,3,4,5
元素排序

-----------------单元素排序----------------------
local list = {3,1,5,2,4}--升序排序
--打印:1, 2, 3, 4, 5
table.sort(list)--降序排序
--打印:5, 4, 3, 2, 1
table.sort( list, function(a,b)return a > b
end)-----------------多条件排序----------------------
local list = {{id = 11,score = 606,num = 1},{id = 33,score = 505,num = 3},{id = 33,score = 505,num = 2},{id = 44,score = 303,num = 5},{id = 11,score = 505,num = 4},
}table.sort( list, function(a,b)if a.id ~= b.id thenreturn a.id < b.id endif a.score ~= b.score thenreturn a.score > b.score endreturn a.num > b.num
end)for k,v in ipairs(list) doprint(v.id,v.score,v.num)
end
参数打包

table.pack用于将可变数量的参数打包成一个表,并额外包含一个 n 字段来表示参数的数量。

-- 示例 1: 基本用法
local t1 = table.pack(1, 2, 3, "hello")
print(t1.n)        -- 输出: 4
print(t1[1])       -- 输出: 1
print(t1[4])       -- 输出: hello-- 示例 2: 处理 nil 值
local t2 = table.pack(1, nil, 3, nil)
print(t2.n)        -- 输出: 4
print(t2[2])       -- 输出: nil (不会被截断)-- 示例 3: 空参数
local t3 = table.pack()
print(t3.n)        -- 输出: 0

实际应用:处理可变参数函数

function processArgs(...)local args = table.pack(...)print("参数个数:", args.n)for i = 1, args.n doprint("参数 " .. i .. ":", args[i])end
endprocessArgs("a", "b", "c")
-- 输出:
-- 参数个数: 3
-- 参数 1: a
-- 参数 2: b
-- 参数 3: c
参数解包

table.unpack用于将表中的元素展开为多个返回值

-- 示例 1: 基本展开
local t = {10, 20, 30, 40}
local a, b, c = table.unpack(t)
print(a, b, c)  -- 输出: 10  20  30-- 示例 2: 指定范围
local x, y, z = table.unpack(t, 2, 4)
print(x, y, z)  -- 输出: 20  30  40-- 示例 3: 函数调用
local params = {"hello", "world", 123}
print(table.unpack(params))  -- 输出: hello world 123

与直接使用 ... 的区别

function test1(...)-- 直接使用 ...,无法知道参数个数(如果有 nil 会被截断)local args = {...}print("参数个数(可能不准确):", #args)
endfunction test2(...)-- 使用 table.pack,准确获取参数个数local args = table.pack(...)print("准确参数个数:", args.n)
endtest1(1, nil, 3)   -- 输出: 参数个数(可能不准确): 1
test2(1, nil, 3)   -- 输出: 准确参数个数: 3

function  函数

--形式1
function Test1()print("Hello World!1")
end--形式2
local Test2 = function()print("Hello World!2")
end

多返回值

可变长参数

--计算平均值
function average(...)result = 0local arg={...}for i,v in ipairs(arg) doresult = result + vendreturn result/#arg
endprint("平均值为",average(10,5,3,4,5,6))

3、点和冒号的区别:

点用于表直接调用表内部成员

冒号是将调用者作为第一个参数传入到函数中。使用self关键字就可以对调用者进行交互。

local Animal = 
{name = "动物",height = 10,weight = 20,
}--self就是指代Animal表对象
function Animal:Test()print("动物的名字:",self.name)
endAnimal.Say = function ()print("动物叫声!")
endAnimal:Test()
Animal.Say()

thread  线程

方法

描述

coroutine.create(func)

创建 coroutine,返回 coroutine一个线程, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用

coroutine.resume()

重启 coroutine,和 create 配合使用

coroutine.wrap(func)

创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复

coroutine.status()

查看 coroutine 的状态
注:coroutine 的状态有三种:dead(死亡),suspended(挂起),running(运行)

coroutine.yield()

挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果

coroutine.running()

返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 corouting 的线程号

--使用coroutine.create()创建协程
co=coroutine.create(function ()print("协程")
end)
--协程的状态
print(coroutine.status(co))
--
coroutine.resume(co)--使用coroutine.wrap()创建协程
co1=coroutine.wrap(function()print("第二个协程")
end)co1()--协程挂起function Add()local a=0while(true)doa=a+1print(a)coroutine.yield(a)end
end--用create方法时,接收yield的第一个返回值是boolean
co2=coroutine.create(Add)
local x,y=coroutine.resume(co2)
print(x,y)
x,y=coroutine.resume(co2)
print(x,y)co3=coroutine.wrap(Add)
local m,n=co3()
print(m,n)
m,n=co3()
print(m,n)

循环控制

for循环

顺序遍历

local list = {1,2,3,4,5}--打印:1,2,3,4,5
for i = 1,#list doprint(list[i])
end   

倒序遍历

local list = {1,2,3,4,5}--打印:5,4,3,2,1
for i = #list,1,-1 doprint(list[i])
end   

间隔遍历

例如,间隔2个单位

local list = {1,2,3,4,5}--打印:1,3,5
for i = 1,#list,2 doprint(list[i])
end   

while循环

先判断再运行

local x = 5while(x > 0)dox = x -1
end   

repeat  untile循环

先运行一次再判断

local x = 5repeatx = x - 1
until(x <= 0)

运算符

算术运算符

操作符

描述

+

加法

-

减法

*

乘法

/

除法

%

取余

^

乘幂

-

负号

关系运算符

操作符

描述

==

等于

~=

不等于

>

大于

<

小于

>=

大于等于

<=

小于等于

逻辑运算符

操作符描述实例
and逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B。(A and B) 为 false。
or逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B。(A or B) 为 true。
not逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。not(A and B) 为 true。

and、or、 not分别类似于C#中的 &&、||、! 

and 和or遵循短路求值原则,即只在必要时才对第二个操作数进行求值。

and:如果第一个值为真则返回第二个值,如果第一个值为假则直接返回第一个值

or:如果第一个值为真则返回第一个值,如果第一个值为假则返回第二个值

实现三目运算符

local a = 1
local b = 2--打印较大值:2
local result = a > b and a or b

运算符优先级

从高到低的顺序

错误处理

error函数

功能:终止正在执行的函数,并返回message的内容作为错误信息

assert函数

assert首先检查第一个参数,若为true,assert不做任何事情;若为false,assert以第二个参数作为错误信息抛出。

数学函数

abs

取绝对值

math.abs(-15)

15

acos

反余弦函数

math.acos(0.5)

1.04719755

asin

反正弦函数

math.asin(0.5)

0.52359877

atan2

x / y的反正切值

math.atan2(90.0, 45.0)

1.10714871

atan

反正切函数

math.atan(0.5)

0.463647609

ceil

不小于x的最大整数

math.ceil(5.8)

6

cosh

双曲线余弦函数

math.cosh(0.5)

1.276259652

cos

余弦函数

math.cos(0.5)

0.87758256

deg

弧度转角度

math.deg(math.pi)

180

exp

计算以e为底x次方值

math.exp(2)

2.718281828

floor

不大于x的最大整数

math.floor(5.6)

5

fmod (mod)

取模运算

math.mod(14, 5)

4

frexp

把双精度数val分解为数字部分(尾数)和以2为底的指数n,即val=x*2n

math.frexp(10.0)

0.625 4

ldexp

计算value * 2的n次方

math.ldexp(10.0, 3)

80 = 10 * (2 ^3)

log10

计算以10为基数的对数

math.log10(100)

2

log

计算一个数字的自然对数

math.log(2.71)

0.9969

max

取得参数中最大值

math.max(2.71, 100, -98, 23)

100

min

取得参数中最小值

math.min(2.71, 100, -98, 23)

-98

modf

把数分为整数和小数

math.modf(15.98)

15 98

pow

得到x的y次方

math.pow(2, 5)

32

rad

角度转弧度

math.rad(180)

3.14159265358

random

获取随机数

math.random(1, 100)
math.random(100)

获取1-100的随机数

randomseed

设置随机数种子

math.randomseed(os.time())

在使用math.random函数之前必须使用此函数设置随机数种子

sinh

双曲线正弦函数

math.sinh(0.5)

0.5210953

sin

正弦函数

math.sin(math.rad(30))

0.5

sqrt

开平方函数

math.sqrt(16)

4

tanh

双曲线正切函数

math.tanh(0.5)

0.46211715

tan

正切函数

math.tan(0.5)

0.5463024

举例:除数取整

随机数

math.random()

返回一个在[0,1)范围内的伪随机小数

math.random(x)

返回一个在[1,x]范围内的伪随机整数

math.random(x,y)

返回一个在[x,y]范围内的伪随机整数

math.randomseed(x)

1、math.randomseed(x)用于设置伪随机数发生器的种子,系统默认x为1

2、若x相同,则生成的伪随机数序列也相同,要想生成的随机数序列不同则将x设置伪不同的值

3、使用math.randomseed(os.time())来使用当前系统时间来初始化

--对随机性要求不高的情况
math.randomseed(os.time())
print(math.random(1,20))--对随机性要求较高的情况
local seed = tonumber(tostring(os.time()):reverse():sub(1,6))
math.randomseed(seed*1000)
local num = math.random(1, 20)--生成随机小数
function GetRandom(minValue,maxValue)local value = math.random()return minValue+value*(maxValue-minValue)
end    --生成随机小数(限制位数)
function GetRandom(minValue,maxValue,decimalPlace)local value = math.random()local result = minValue+value*(maxValue-minValue)local format = "%."..decimalPlace.."f"result = string.format(format,result)result = tonumber(result)return result
end  

日期和时间

os.time

获取当前时间戳

os.date

格式化为日期表

字段名

全称

含义

取值范围

示例

year

Year

年份(四位数字)

通常 >= 1970

2024

month

Month

月份

1 (一月) - 12 (十二月)

6

(代表六月)

day

Day

当月的第几天

1 - 31

15

yday

Year Day

当年的第几天

1 - 366

167

(在非闰年中代表6月15日)

wday

Week Day

本周的第几天

1 (星期日) - 7 (星期六)

7

(代表星期六)

hour

Hour

当前小时 (24小时制)

0 - 23

14

(下午2点)

min

Minute

当前分钟

0 - 59

30

sec

Second

当前秒数

0 - 61 (允许闰秒)

45

isdst

Is Daylight Saving Time

是否处于夏令时

boolean

(true

/ false

)

false

(中国不实行夏令时)

wday 的取值范围: 请注意,wday 是从 星期日(Sunday)开始 的。

1 = 星期日、2 = 星期一、3 = 星期二、4 = 星期三、5 = 星期四、6 = 星期五、7 = 星期六

生成当前时间的日期表

生成指定时间戳的日期表

格式化时间字符串

示例1:

local list = 
{"%a","%A","%b","%B","%c","%H","%I","%j","%m","%M","%p","%S","%w","%W","%x","%X","%y","%Y"
}
for k,v in ipairs(list)doprint("指示符:",v,"打印:",os.date(v))
end

示例2:

local date = os.date("%Y/%m/%d %H:%M:%S")

模块和包

模块类似于一个封装库,可以把一些公用的代码放在一个模块文件中,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

_G表

_G是一个总表,他将我们声明的所有全局变量都存储在其中,局部变量不会存到该表中(加了local的变量)

for k,v in pairs(_G) doprint(k,v)
end  

加载文件步骤

1、注册自定义文件加载路径

lua一般会从默认的路径 package.path 进行加载文件,但是有时候我们需要从自己指定的文件夹路径中加载。所以,我们需要在加载文件之前进行注册自定义文件加载路径

local custom_path = 
{"C:\\Users\\24292\\Desktop\\LuaProject\\?.lua","C:\\Users\\24292\\Desktop\\LuaAnother\\?.lua",
}for k,v in pairs(custom_path) dopackage.path = package.path..";"..v
end

2、创建公共代码文件 

C:\Users\24292\Desktop\LuaAnother\MyMath.lua

local MyMath = {}MyMath.Add = function(a,b)return a+b
endreturn MyMath

3、创建测试文件

 C:\Users\24292\Desktop\LuaProject\Main.lua  使用require加载文件

local custom_path = 
{"C:\\Users\\24292\\Desktop\\LuaProject\\?.lua","C:\\Users\\24292\\Desktop\\LuaAnother\\?.lua",
}for k,v in pairs(custom_path) dopackage.path = package.path..";"..v
endlocal MyMath = require("MyMath")
local result = MyMath.Add(1,2)
print(result)

require、dofile、loadfile的功能和区别

一般require比较常用,其他两个函数作了解

require

1、加载并执行指定的模块

2、对于搜索路径,不需要写文件的全路径和.lua扩展名。require 会根据 package.path(用于 Lua 文件)和 package.cpath(用于 C 库)中定义的模板路径来搜索文件。

3、加载后会将该模块缓存起来,多次加载时只会执行一次。这确保了模块的 Singleton(单例)特性,避免了重复定义和资源浪费。

dofile

1、编译并立即执行指定的 Lua 文件。

2、搜索路径需要写文件的全路径和.lua扩展名

2、加载后没有缓存,每次调用,文件都会被重新编译和执行。

loadfile

1、将指定的 Lua 文件编译成 chunk(一个代码块),并将其作为一个函数返回。它并不执行这个函数。执行该函数后,才能获取加载后返回的模块对象。

2、搜索路径需要写文件的全路径和.lua扩展名。

3、加载后没有缓存,每次调用,文件都会被重新编译和执行。

元表和元方法

         元表(Metatable)和元方法(Metamethod)是Lua中实现面向对象编程、操作符重载和自定义行为的重要机制。

元表

        元表是一个普通的Lua表,可以附加到另一个表上,用于定义或修改该表的行为。每个表都可以有自己的元表。

setmetatable(tab,metatab)

将metatab设置为tab的元表

getmetatable(tab)

获取表tab的元表

local t = {}
local mt = {}  -- 元表-- 设置元表
setmetatable(t, mt)-- 获取元表
local mt_of_t = getmetatable(t)

元方法

元方法是定义在元表中的特殊键,当表参与特定操作时会被调用。

 运算相关元方法

local Calculate = {}local data1 = {number = 2}
local data2 = {number = 4}setmetatable(data1,Calculate)
setmetatable(data2,Calculate)--加
Calculate.__add = function(a,b)return a.number+b.number
end
print(data1 + data2)--减
Calculate.__sub = function(a,b)return a.number-b.number
end
print(data1 - data2)--乘
Calculate.__mul = function(a,b)return a.number*b.number
end
print(data1 * data2)--除
Calculate.__div = function(a,b)return a.number/b.number
end
print(data1 / data2)--取余
Calculate.__mod = function(a,b)return a.number%b.number
end
print(data1 % data2)--等于判断
Calculate.__eq = function(a,b)return a.number == b.number
end
print(data1 == data2)--连接符
Calculate.__concat = function(a,b)return a.number .. b.number
end
print(data1..data2)--小于号
Calculate.__lt = function(a,b)return a.number < b.number
end
print(data1<data2)--小于或等于
Calculate.__le = function(a,b)return a.number <= b.number
end
print(data1 <= data2)--幂运算
Calculate.__pow = function(a,b)return a.number ^ b.number
end
print(data1 ^ data2)--负数
Calculate.__unm = function(a)return -a.number
endprint(-data1)

测试打印: 

库定义相关元方法

__tostring

 当要打印表名时,Lua就会查找该表的元表中的__tostring方法,并调用。

local animal = {name = "动物"
}local cat = {name = "小猫咪"
}setmetatable(cat,animal)animal.__tostring = function(t)print(t.name)return "动物方法"
endprint(cat)

__call

当表被当做一个函数被调用时,Lua就会查找该表的元表中的__call方法,并调用

local animal = {name = "动物"
}local cat = {name = "小猫咪"
}setmetatable(cat,animal)animal.__call = function(t)print("我是"..t.name.."的方法")
endcat()

表相关元方法

__index

当访问一个表中不存在的字段时,那么Lua就会寻找该table的metatable中的__index 键

元方法是一个表 

local Human = {}
Human.__index = {score = 250
}
local Student = {}setmetatable(Student,Human)
print(Student.score)

元方法是一个函数 

local Human = {}
Human.__index = function()print("调用index元方法")return 1000
end
local Student = {}
setmetatable(Student,Human)
print(Student.score)

__newindex

        当给表中一个不存在的键赋值时,首先判断该表是否有元表,如果没有则相当于直接在表中声明一个变量并赋值,如果有则在元表中查找__newindex键,如果__newindex包含一个表则直接在该表中赋值,不在原始表中赋值。

__newindex 元方法用来对表更新,__index则用来对表访问 。

rawset

在不触发元方法__newindex的情况下,在原始表中进行声明赋值.

未用rawset情况:如果直接赋值的话,会查找tab2的元表中的元方法__newindex,将在元表tab1中声明该键并赋值,而不在tab2中声明赋值

使用rawset情况:当元表中有元方法__newindex时,使用rawset,给tab2中的不存在的键赋值,不会调用元方法__newindex,直接在tab2中声明赋值

rawget

在不触发元方法__index的情况下,直接在原始表中查找该字段

未用rawget情况:会查找元表中的元方法__index

local Human = {score = 100
}Human.__index = {score = 250
}local Student = {}
setmetatable(Student,Human)
print(rawget(Student,"score"))

使用rawset情况

local Human = {score = 100
}Human.__index = {score = 250
}local Student = {}
setmetatable(Student,Human)
print(rawget(Student,"score"))

垃圾收集

Lua 采用了自动内存管理。不用操心新创建的对象需要的内存如何分配出来, 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。 Lua 运行了一个 垃圾收集器 来收集所有 死对象 (即在 Lua 中不可能再访问到的对象)来完成自动内存管理的工作。 Lua 中所有用到的内存,如:字符串、表、用户数据、函数、线程、 内部结构等,都服从自动管理。

Lua 提供了以下函数collectgarbage ([opt [, arg]])用来控制自动内存管理:

collectgarbage("collect")

做一次完整的垃圾收集循环。 这是默认选项。

collectgarbage("count")

以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分,所以只需要乘上 1024 就能得到 Lua 使用的准确字节数(除非溢出)。

collectgarbage("restart")

重启垃圾收集器的自动运行。

collectgarbage("stop")

停止垃圾收集器的运行

http://www.xdnf.cn/news/1407781.html

相关文章:

  • vim-plugin AI插件
  • 运筹说 第141期 | 启发式算法:用简单规则、破解复杂问题
  • 网络端口与服务对应表 - 白帽子安全参考指南
  • C#基础(③CMD进程)
  • LLM记账智能体-MCP服务-实现步骤与效果展示
  • @Value注解的底层原理(一)
  • (一) aws上微服务
  • C++ 快速复习指南(上半部分)
  • 我开发了一个自动还原源码的小工具
  • AI辅助编程日记和chat历史开源Series 1:VSCode + GitHub Copilot 自动下载及安装软件
  • 《打破 “慢“ 的黑箱:前端请求全链路耗时统计方案》
  • Vue3 响应式基础
  • 前端学习——JavaScript基础
  • 创维LB2004_安装软件教程
  • 37. 解数独
  • GaRe:面向非约束户外照片集的可重光照 3D 高斯溅射技术简要解析
  • Android开发-活动页面
  • C# .Net8 WinFormsApp使用日志Serilog组件
  • c++ Effective c++ 条款5
  • 机器学习之线性回归
  • 数据结构02:排序算法
  • PyQt5 进度条详细示例与性能优化
  • 电商系统的分布式事务调优
  • Knit-易用的prompt管理和调试工具
  • 第六章:透明度-Transparency《Unity Shaders and Effets Cookbook》
  • io进程线程;标准IO;0831
  • 【嵌入式】【调用函数图】手动绘制函数调用状态机
  • 【优先算法--前缀和】
  • 3DES加解密的算法Java Python Golang
  • CVPR上的多模态检索+视频理解,LLM助力提效翻倍