Lua基础
Lua基础
Lua 教程 | 菜鸟教程(https://www.runoob.com/lua/lua-tutorial.html) 嫌啰嗦可以看这个
一、简单变量
分为:nil,number,string,boolean。
1.变量申明
lua中所有的变量申明,都不需要申明变量类型,它会自动判断类型。而且
可以随便赋值。
1 | a=1 |
2.nil
nil 类似于C#中的null,空的概念,也等同于false
1 | a=nil |
3.number
所有的数值都是number。默认只有一种double类型
1 | a=1 |
4.string
字符串的声明 使用单引号或者双引号,都能声明。
lua中没有char
1 | a='123' |
5. boolean
包含两个值false和true。
1 | a=true |
6.如何得到变量类型
通过type函数 我们可以得到变量的类型。
返回值是string类型
注:lua 中没有使用声明过的变量,不会报错默认值是 nil。
二、字符串操作
语法:#字符串变量
1 | s = "123123" |
注:英文字符占1个长度,汉字占3个长度
注:lua中也是支持转义字符的
1. 字符串多行打印
转义字符
或[[]]
1 | print("111\n123") |
2. 字符串拼接
通过..拼接 或string.format()函数
1 | print("123" .. "456") |
3. 别的类型转字符串
默认打印自动转string,也可以用函数tostring()显示转换
1 | a = true |
4.string公共方法
注:这些方法都不会改变原字符串,只是返回一个新字符串
(1) 小写转大写
string.upper
1 | str=“abcdefg” |
(2) 大写转小写
string.lower
1 | str=“ABCD” |
(3) 翻转字符串
string.reverse()
1 | str=“ABCD” |
(4)字符串索引查找
string.find(str,”cde”)
1 | str=“ABCD” |
(5) 截取字符串
string.sub,有两个重载
1 | str=“ABCD” |
(6) 字符串修改
string.gsub(str,要修改的子串,要替换的字符串)
1 | str=“ABCD” |
(7) 字符转 ASCLL码
string.byte
1 | str=“ABCD” |
三、运算符
1. 算数运算符
与C#大体都一致
注:Lua中没有自增自减,不支持++或--
注:没有复合运算符 += -= /= *=
注:Lua中会将字符串自动转为数值进行计算
因为number类型为double所以1/2为5,而不是0
1 | print("123"+1)--124 |
特殊:lua中有幂运算
^
1 | print(2^2)--4 |
2. 条件运算符
大体与c#一致,不同为不等于,~=为不等于
3. 逻辑运算
与是and 或是or 非为not 支持短路
C#中 && || !
4.位运算符
不支持,需要自己实现
5.三目运算符
? : 不支持
四、条件分支语句
if 条件 then ……end
1 | a=1 |
注:条件分支就像填空一样,先把then end写完之后往里填。最开始的then end就像大括号一样
注:lua中没有switch语法 需要自己实现
五、循环语句
1.while语句
while 条件 do…..end
1 | while num <5 do |
2. do…while 语句
repeat ….until 条件 (z注意:条件是结束条件)
1 | num = 0 |
3. for循环
for 变量= 起始值,终止值,每次递增的数值(不写默认为1) do ….. end
注:lua中 for循环默认递增 i会默认+1
1 | for i=1,5 do |
六、函数变长嵌套闭包多返回值
1.函数
function 函数名()
end
a = function()–有点类似 C#中的事件和委托
end
2. 无参数无返回值
1 | --函数申明 |
1 | F2 =function() |
3.有参数
1 | function F3(a) |
如果你传入的参数 和函数参数个数不匹配
不会报错只会补空nil 或者丢弃
4.有返回值
函数声明是
不需要规定返回值类型的,你直接返回,外面直接 接取就行。
1 | function F4(a) |
多返回值时 在前面申明多个变量接取即可
如果变量不够
不影响值接取对应位置的返回值如果变量多了也不影响,直接赋nil
1 | function F4(a) |
5.函数的类型
就是function
1 | F5 = function() |
6.函数的重载
函数名相同 参数类型不同 或者参数个数不同
注:Lua中函数不支持重载,默认调用最后一个声明的函数
7.变长参数
function 函数名 (…) 输入类型随便
1 | function F7(...) |
8.函数嵌套
函数内部定义函数
1 | function F8() |
9.闭包(面试考点)后面详细补充
在函数里面返回一个函数,改变大函数变量的生命周期。
子函数可以使用父函数中的局部变量,这种行为叫做闭包。
1 | function F9(x) |
七、复杂数据类型——table表
所有的复杂类型都是table(表):数组、字典、类等等。
1.数组
声明:a = {1,2,3,4,”123”,true,nil}
注:lua中索引从1开始。
注:#是通用的获取长度关键字,并且在打印长度时nil被忽略。只要遍历到nil,就认为数组断了。所以用#获取长度并不准确。
2.数组遍历
1 | for i=1,#a do |
3.二维数组
表中表,一个大括号包含n个小括号
1 | a = {{1,2,3}, |
4.二维数组遍历
1 | for i=1,#a do |
5.自定义索引
1 | aa ={[0]=1,2,3,[-1]=4,5} |
注:如果用#aa计算 数组长度只能得到3,因为这里面0和-1编辑器不认识。#默认从1开始计算,没有自定义的会从1开始一个一个排
1 | aa ={[0]=1,2,3,[-1]=4,5} |
深坑:如果自定义隔一个数定义,lua默认空的是nil
并且会计算入数组长度。如果隔一个以上则直接断开,了解即可
6. 迭代器遍历
因为用#获取表长不准确,所以迭代器遍历 主要是用来遍历表的。
(1) ipairs
ipairs遍历 还是 从1 开始往后遍历的 小于等于0的值得不到。并且只能找到连续的索引。如果中间断了 ,他无法遍历出后面的内容
1 | a = {[0]=1,2,[-1]=3} |
(2) pairs
pairs能把所有的键都找到,
建议使用它遍历各种不规则表。
1 | a = {[0]=1,2,[-1]=3} |
(3)ipairs和pairs区别(面试考点)
后续补充
八、用table表示字典
1.字典的声明
字典由键值对构成
访问单个变量 用中括号填键来访问
还可以类似 . 成员变量的形式得到值(不能是数字)
1 | a = {["name"]="wqx",["age"]=14,["1"]=5} |
2.字典遍历
如果要模拟字典 遍历一定用pairs
1 | a = {["name"]="wqx",["age"]=14,["1"]=5} |
九、用table表示类和结构体
Lua中默认是没有面向对象的 需要我们自己实现
1. 表示类
成员变量 成员函数
1 | Student = { |
C#要是使用类 实例化对象new 静态直接点
Lua中类的表现更像一个类中 有很多静态变量和函数
1 | print(Student.age) |
表外申明 在
表外可以继续申明表中变量
1 | Student.name= "wqx" |
2. Lua中 . 和:的区别(面试)
点调用函数,需要传什么参数就传什么
冒号调用函数 会
默认把调用者 作为第一个变量
1 | Student.Learn(Student) |
lua中有一个关键字 self 表示 默认传入的第一个参数
1 | function Student:Speak2() |
十、表的公共操作
表中 table提供的一些公共方法的讲解
我们先声明一张表
1 | t1 = {{age=1, name = "123"},{age = 2 ,name="345"}} |
1. 插入函数
table.insert(被插的表,要插的表)
1 | print(#t1) |
2.删除指定元素
remove 方法 传表进去 会移除最后一个索引内容
1 | table.remove(t1) |
remove 方法 传两个参数
第一个参数 是要移除内容的表
第二个参数 是要移除内容的索引
1 | table.remove(t1,1) |
3. 排序函数
可以将表中数字排序
1 | t2 = {5,2,7,9,5} |
传入两个参数 第一个是用于排列的表
第二个是 排序规则函数
1 | table.sort(t2,function(a,b) |
- 如果
a > b,则a排在b前面(降序)。 - 如果
a <= b,则a排在b后面(不返回true,默认返回nil)。
4.拼接函数
table.concat(
表,分割元素的分隔符) 返回一个string用于拼接表中元素 返回值 是字符串
1 | tb = {"123","456","789","10101"} |
十一、特殊用法:多变量赋值 三目运算符
1. 多变量赋值
多变量赋值,如果后面的值不够,会自动补空。
后面值多了,会自动省略。
1 | a,b,c = 1,2,"123" |
2.多返回值
规则同上
1 | function Test() |
3. and or
and or 它们不仅可以连接 boolean
任何东西 都可以用来连接。在lua中 只有
nil和 false 才认为是假并且支持短路
4.模拟三目运算符
? : 公式: (x>y) and x or y
1 | x=3 |
十二、多脚本执行
1.全局变量和本地变量
lua脚本中
所有不加local声明的变量都是全局变量
1 | for i=1,2 do |
本地(局部)变量关键字
local
1 | for i = 1,2 do |
2. 多脚本执行
关键字 require(“脚本名”)
也是从上往下依次执行
- 注1:只要是
执行过的脚本,全局变量都可以互相使用。本地变量则不行。 - 注2:require加载执行的脚本
加载一次过后不会在被执行
如要使用其他脚本的 本地变量 可以使用return 返回一个外部的变量


3. 脚本卸载
package.loaded[“脚本名”] 可以得到脚本有没有被执行过。
返回值是boolean 意思是 该脚本是否被执行
1 | --卸载已经执行过的脚本 |
3.大G表
G是一个总表(table) 他将我们申明的所有全局的变量都存储在其中. 下划线大G
1 | for k,v in pairs(_G) do |

本地变量 加了local的变量是不会存到大_G表中的_
十三、协程Coroutine
1.协程的创建
第一种(常用):coroutine.create()
1 | fun =function() |

协程的本质是一个线程对象
第二种:coroutine.wrap()
1 | fun =function() |
第二种创建出来的协程是一个函数
2. 协程的运行
第一种:coroutine.resume(协程对象)
对应 create 创建的
1 | coroutine.resume(co) |
第二种:直接调函数即可
1 | co2() |
3. 协程的挂起
coroutine.yield()
yield可以带返回值回来
默认 第一个返回值 为是否启动成功
第二个为 yield里面的返回值
wrap会直接返回值,不会返回boolean
1 | fun2 = function() |
4.协程的状态
coroutine.status(协程对象) 返回string
dead 结束
suspended 暂停
running 进行中
coroutine.running() 可得到
运行的协程线程号

十四、元表
1. 元表概念
任何
表变量都可以作为另一个表变量的元表任何
表变量都可以有自己的元表 (爸爸)当我们
子表中进行一些特定操作时,会执行元表中的内容。
2. 设置元表
setmetatable(mtTable,meta)
第一个参数 子表
第二个参数 元表(爸爸)
1 | meta = {} |
3. 特定操作—___tostring
当子表要当作字符串使用时,默认调用元表中的tostring方法
1 | meta2 = { |
4. 特定操作— __call
当子表被当作函数时使用,就会默认调用__call
当希望传参数时 一定要记住 默认传第一个参数 是调用者自己
1 | meta3 = { |
5. 特定操作—运算符重载
可以在元表中特定一些函数来进行操作
+: __add
— :__sub
*: mul
/ : dov
% : mod
^ : pow
== : eq 注:如果要用条件运算符 来比较 。这两个对象的元表一定要一致 才能准确调用方法。
< : lt
<= :le
.. : concat
1 | meta4 = { --要加的左右元表 |
6. 特定操作—__ index 和__newindex
__当index 当子表中
找不到某一属性时会到元表__index指定的表取找索引
如果__ index 和__ newindex是函数 那就调用这个函数
1 | meta6 = { |
index可以一层一层往上找
1 | meta6Father = { |
newIndex 当赋值时 ,如果赋值一个不存在的表
那么会把这个
值赋值到元表中newindex指定的表中,不会修改自己
1 | meta7 = {} |
getmetatable(myTable6)得到元表
1 | print(getmetatable(myTable6)) |
rawget 当我们使用它时 即使我们设置了元表和index ,只会去找自己身上有没有这个变量
1 | print(rawget(myTable6,"age")) |
rawset 该方法 会忽略newindex 的设置 只会改自己的变量
1 | rawset(mtTable7,"age",2) |
十五、面向对象——封装、继承、多态
1. 封装类
1 | Object = {} |
2. 继承
写一个用于继承的方法 用__G表进行表的创建
1 | function Object:subClass(className) |
实例化 对象逻辑
1 | local p1 = Person:new() |

3. 多态
相同行为 不同表象 就是多态
相同方法 不同执行逻辑 就是多态

1 | Object:subClass("GameObject") |
