lua基础语法

lua输出语句 print() 注释 -- 单行注释 --[[ 多行注释 lua语句可以省略; ]] 变量 lua不需要显式声明变量类型 -- 简单类型 nil number -- 所有数值类型都是number不论浮点还是整形 string

lua输出语句

print()

注释

-- 单行注释
--[[
    多行注释
    lua语句可以省略;
]]

变量

lua不需要显式声明变量类型

-- 简单类型
nil
number -- 所有数值类型都是number不论浮点还是整形
string -- 单双引号都可以
boolean
-- 复杂类型
function
table
-- 数据结构
userdata
-- 协同程序(线程)
thread

-- 声明变量 (local) 变量名 = 值
-- 全局变量前面要加local
-- 声明变量不赋值不会报错默认值nil
a = nil

-- 获取变量类型
type(a)

全局变量

--局部变量 local
local a;
--不加local是全局变量

字符串操作

#'abcd' -- 字符串长度 汉字长度3 英文长度1

'123\n123' -- 支持转义字符

-- 多行字符
[[
123
123
]]

'123' .. '456' -- 字符串拼接使用 ..

string.format("%d,%a,%s",18,true,'a');
--%d :与数字拼接
--%a:与任何字符拼接
--%s:与字符配对
-- ...

tostring(true) -- 其他类型转字符串

-- 字符串公共方法
string.upper()(.lower()) -- 字符串转大小写
string.reverse() -- 翻转
string.find('123456','12') -- 索引查找
string.sub('123456',3--[[起点]],4--[[终点取的到]]) -- 截取
string.rep('123',2) -- 重复
string.gsub('123','23','32') -- 替换
a = string.byte('123',1) -- 转ASCII码
string.char(a) -- ASCII转字符
-- ...其他方法

运算符

-- 算术运算符
 + - * / % ^
-- ^ 幂运算 2^3 = 8
-- 没有自增自减,也没有复合运算符 += -=之类
-- lua 会把字符串转成数值类型(只要能转)进行计算
'123' + 1 -- 输出结果为124

-- 逻辑运算符
and or not
-- lua中支持短路

-- 条件运算符
 > < >= <= == ~=
-- lua中 不等于是 ~=

-- 三目运算符
-- 也不支持

-- 位运算符
-- 不支持位运算符

分支

if 条件 then
(elseif 条件 then)
(else)
end

-- lua没有switch

循环

for i=1,5,-1 do -- 默认是递增,第三个数是增量
-- ...
end

while 条件 do
-- ...
end

repeat
-- ...
until 条件

函数

function 函数名(参数1,参数2,...)
-- ...
    return 返回值1(,返回值2,返回值..)
end

fun = function(参数1,参数2,...)
-- ...
return 返回值1(,返回值2,返回值..)
end

-- 传入实参与形参不匹配,不会报错,会丢弃或补空nil
-- 多返回值时,要声明多个变量来截取不然默认只会得到第一个返回值,其余会被丢弃
-- 不支持重载,默认调用最后一个声明的函数

function 函数名( ... )
-- 变长参数使用得先用一个表存起来
    arg = {...}
    for i=1,#arg do
        print(arg[i])
    end
    return 返回值1(,返回值2,返回值..)
end


function 函数名(  )
-- 函数嵌套
    return function 函数名(  )
        return 返回值1(,返回值2,返回值..)
    end
end

function 函数名( x )
-- 函数闭包
    return function 函数名(y  )
        return x+y
    end
end

表table

表实现数组

-- 数组
index = 1
a = {1,2,3,4--[[,...]]}
b= a[index]
print(b)
-- lua索引从1开始
-- #是获取长度的关键字,空值不会被计入长度 例a={nil,1,2}  #a长度为2

-- 遍历
for i=1,#a do
    print(a[i])
end

-- 二维数组
a = {
    {1,2,3},
    {2,3,4}
}

--二维数组遍历
for i=1,#a do
    for j=1,#a[i] do
        print(a[i][j])
    end
end

-- 自定义索引
a = {[0]=1,2,[-1] = 3,4,5}
a[0] == 1
-- 自定义索引和默认索引分开计算
-- a[1] == 2, a[2] == 4,a[3] == 5

迭代器遍历表

-- 主要用来遍历表
-- ipairs从1开始遍历索引,小于等于0的索引值得不到
-- 只能找到连续索引的键
for i,k in ipairs(a) do
    print(i .. '/' .. k)
end

-- pairs遍历
-- pairs能把所有的键都找到再通过键得到值
-- 先从索引1开始遍历顺序索引,再遍历乱序的索引
for i,v in pairs(a) do
    print(i .. '/' .. k)
end

表实现字典

-- 字典的声明
a = {
    ['name'] = 'value',
    ['age'] = 14
}
-- 使用
a['name'] -- or a.name
a['age'] -- or a.age
-- a.1这样不行

-- 增加
a['id'] = 1
--删除
a['id'] = nil 

-- 遍历
for k,v in pairs(a) do
    print('k:' .. k .. ',v:' .. v)
end

表实现类

-- lua默认没有面向对象需要自己实现
Student = {
    id = 1,
    age = 18,
    name = 'test',
    say = function(name)
        print(name) -- 这里的name和表中的name没关系表示一个全局变量
        -- 在表内函数调用表本身的属性或者方法需使用表名.属性(方法名())
        print(Student.name)
    end
    say2 = function(t)
        print(t.name)

    end
}

Student.say()
-- lua中使用:调用会默认把调用者作为第一个实参
Student:say2()

表的公共方法

-- 插入
table.insert(t1,t2)把t2插入t1

-- 删除指定元素
table.remove(t1--[[,index]]) -- 默认移除最后一个索引内容,第二个参数为指定索引

-- 排序
table.sort(t1-[[,function(a,b)]]) -- 默认为升序排序,第二个参数为排序函数

-- 拼接
table.concat(t1,',') -- 将表中元素用参数二拼接后返回一个字符串

多脚本执行

require(--[["脚本名"]]) -- 执行另一个脚本
-- 另一个脚本内使用local 声明的变量无法在该脚本使用
-- 例
-- a.lua
a = 1;
local b = 2;
return b -- 如果在脚本最后返回一个外部希望获取的内容

-- b.lua
local c = require("a") -- 可以声明一个变量接收另一个脚本返回的内容
print(a) -- 输出 1
print(b) -- 输出 nil
print(c) -- 输出 2

脚本卸载

require("a")
require("a") -- require加载执行的脚本只会执行一次,重复加载不会重复执行

package.loaded['a'] -- 返回值是boolean 表示该脚本是否被执行
package.loaded['a'] = false -- 设置为false表示卸载脚本
require("a") -- 此时就可以重新加载执行

大G表

-- _G表是一个总表table,声明的所有全局变量都存储在里面
-- 局部变量即加了local关键字的变量不会存储在_G表内

特殊用法

多变量赋值

a,b,c = 1,2,"123"
a,b,c = 1,2
-- 多变量赋值
-- 如果后面的值不够会自动不空
-- 如果后面的值多了会自动忽略

函数多返回值

-- 函数多返回值同多变量赋值
-- 如果接受的变量不够会自动忽略多余返回值
-- 如果接受的变量多了会自动赋空值

and or

-- and or 可以连接任何类型不局限于boolean
-- 在lua中只有nil和false为假

-- 模拟三目运算符
-- 利用逻辑运算符优先级 以及 短路特性
a = 1
b = 2
local res = (a>b) and x or y
-- ((a>b) and x) or y
-- a>b = true
-- x or y
-- x = true
-- 返回y
-- a>b = false
-- 返回y

协程

-- 创建协程(2种创建方式)
-- coroutine.create(函数名) -- 返回线程类型
-- coroutine.wrap(函数名) -- 返回函数类型
co = coroutine.create(function()
print(123)
end)

co2 = coroutine.wrap(function()
print(123)
end)

-- 协程运行(2种运行方式)
-- coroutine.resume(线程名)
coroutine.resume(co)
co2()

-- 协程的挂起
fun2 = function()
   while true do
       print(123)
       -- 挂起
       coroutine.yield(value)
    end
end

co2 = coroutine.create(fun2)
-- 挂起(暂停)后要重新执行
temp = coroutine.resume(co2) -- 这里的temp是上面yield返回的值 
temp = coroutine.resume(co2) 
temp = coroutine.resume(co2) 
temp = coroutine.resume(co2) 

-- 协程的状态(running, suspended, dead)
-- coroutine.status(协程对象)

-- coroutine.running() -- 返回正在运行的协程的协程号

元表

-- 任何表变量都可以作为另一个表的元表,任何元表都可以有自己的元表(父级)
-- 在子表进行一些特殊操作时会执行元表中的内容

-- 设置元表
meta = {
    __tostring = function()
        return "qwq"
    end,

    __call = function()
       return "haha"
    end
    age = 6
}

meta.__index = meta
meta.__newIndex = meta
table1 = {}
setmetatable(table1,meta); -- 参数1子表,参数2元表

-- 特殊操作 __tostring
-- 当子表被当字符串使用时,会默认调用元表中的__tostring方法
print(table1) -- 输出qwq

-- 特殊操作 __tocall
-- 当子表被当函数使用时,调用元表中的__call方法,同时第一个参数默认会把子表自身传入当实参
table1()

-- 特殊操作 运算符重载
-- 在元表中写__add(+),__sub(-),__mul(*),__div(/),__mod(%),__pow(^)方法分别重载+-*/%^运算
-- 在元表中写__eq(==),__lt(<),__le(<=)方法分别重载==,<,<=运算(没有>,>=)
-- 在元表中写__concat(..)方法重载 .. 拼接运算
print(table1 + 1)

-- 如果要用条件运算符来比较两个子表
-- 这两个子表的元表一定要是同一个元表

-- 特殊操作 __index 和 __newIndex
-- 当子表中找不到某一个属性时,会到元表中__index指定的表去照索引
-- 元表__index的赋值,写在元表外进行赋值
print(table1.age)

-- 当给子表赋值时,赋值一个不存在的索引会把这个值赋值到__newIndex执行的表中
-- 不会修改子表自己
-- 元表__newIndex的赋值,写在元表外进行赋值
table1.id = 1

-- 得到某一个表的元表的方法
getmetatable(table1)

-- 查找自身有没有该变量
rawget(table1,"age") --参数1自身变量名,参数2查找的变量名(字符串)
-- rawget()会忽略__newIndex的设置只在自身寻找

面向对象

封装

Object = {}

-- :调用会将调用者这里也就是Object作为第一个参数传入
function Object:new()
   local obj = {}
   -- self指定是默认传入的第一个参数
   self.__index = self
   setmetatable(obj,self)
end
local obj = Object:new()
obj:Test(); 
-- 返回的obj是个空表里面没有Test方法所以回去元表__index里面指向的表中去寻找该方法

继承

-- 整一个用于继承的方法
function Object:subClass(className)
    _G[className] = {}
    local obj = _G[className]
    self.__index = self
    obj.base = self
    setmetatable(obj,self)
end

多态

Object:subClass("GameObject")
function GameObject:speak()
   print(self.posX)
end
GameObject:subClass("Player")
function Player:speak()
   -- 自己声明一个base变量存储元表
   -- 通过base使用冒号调用父类方法有坑
   -- 如果要执行父类逻辑不要用冒号调用要用.调用自己传入第一个参数
   self.base.speak(self)
   print('player' .. self.posX)
end

local p1 = Player:new()
p1.speak()

自带库

-- 时间
os.time() -- 系统时间戳
os.time({year = 2025,month=8,day = 8}) -- 将指定时间转换成时间戳
os.date("*t") -- 返回读取系统时间的一个表

-- 数学运算
math.abs() -- 绝对值
math.deg() -- 弧度转角度
-- 三角函数
math.cos()
math.sin()
math.tan()
-- 取整
math.floor()
math.ceil()
math.round()
-- 最大最小值
math.max(a,b)
math.min(a,b)
-- 小数分离
math.modf(1.2) -- 返回两个值,将传入的值分成整数部分和小数部分
-- 幂运算
math.pow(a,b) -- 返回a的b次方
-- 随机数 先设置随机数种子
math.randomseed(os.time())
math.random(100)
-- 开方
math.sqrt(4)

-- 路径
package.path -- 返回lua脚本加载路径
package.loaded() -- 这个方法加载的脚本就是从上面的路径中寻找

垃圾回收

collectgarbage("count") -- 返回当前lua占用内存数 K字节为单位
collectgarbage("collect") -- 进行垃圾回收

-- lua想要释放某个变量占用的空间只要将其置空即可nil
LICENSED UNDER CC BY-NC-SA 4.0
评论