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") |