Lua基本语法(第二部分)

12、复杂数据类型 table

所有的复杂数据类型都是table(表)

1.数组

在lua中 索引不从0开始而是从1开始

#是通用的获取长度的关键字

在打印长度的时候 lua会忽略掉nil

如果表中某一位变成nil,会影响#获取的长度 (若中间有nil后面长度都被忽略)

例:

a = {1,2,3,4,"123",true,nil}

print(#a) = 6

a = {1,2,nil,4,"123",true,nil}

print(#a) = 2

2.数组的遍历

例:

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

3.二维数组

例:

a = {{1,2,3},{4,5,6}}

4.二维数组的遍历

for i = 1,#a do
    b = a[i]
    for j = 1,#b do
        print(b[j])
    end
end

5.自定义索引

例:

aa = {[1] = 1,[2] = 2,[4] = 4,[6] = 6}
print(#aa)
for i = 1,#aa do
    print(aa[i])
end

13、迭代器遍历

迭代器遍历 主要是用来遍历表的
#得到长度 其实并不准确 一般不要用#来遍历表

a = {[0] = 1,2,[-1] = 3, 4, 5,[5] = 6}

1.ipairs迭代器遍历

ipairs
ipairs遍历 还是 从1开始往后遍历的 小于等于0的值得不到
只能找到连续索引的 键 如果中间断序了 他也无法遍历出后面的内容

例:

for i,k in ipairs(a) do
    print("ipairs遍历键值"..i.."_"..k)
end

2.ipairs迭代器遍历键

例:

for i in ipairs(a) do
    print("ipairs遍历键值"..i)
end

3.pairs迭代器遍历

pairs可以把所有的键都找到 通过键可以得到对应的值(推荐用)

例:

for i,v in pairs(a) do
    print("pairs遍历键值"..i.."_"..v)
end

4.pairs迭代器遍历键

例:

for i in pairs(a) do
    print("pairs遍历键值"..i)
end

14、字典

1.字典的声明

a = {["name"] = "XX",["age"] = 18,["sex"]=true}

访问单个变量

print(a["name"])

print(a.name)

修改直接覆盖对应键的值即可

新增直接加就可以 例如:a["12345"] = true

删除将键值赋为nil即可

2.字典的遍历

例:

for k,v in pairs(a) do
    --可以传多个参数 一样可以打印出来
    print(k,v)
end

for k in pairs(a) do
    print(k)
    print(a[k])
end

for _,v in pairs(a) do
    print(_,v)
end

3.类和结构体

Lua中是默认没有面向对象的 需要我们自己来实现

例:

Student = { 
    --年龄
    age = 1,
    --性别
    sex = true,
    --成长函数
    Up = function()
        --这样写 这个age 和表中的age没有任何关系 它是一个全局变量
        --print(age)

        --想要在表内部函数中 调用表本身的属性或者方法
        --一定要指定是谁的 所以要使用 表名.属性 或 表名.方法
        print(Student.age)
        print("我成长了")
    end,
    --学习函数
    Learn = function(t)
        --第二种 能够在函数内部调用自己属性或者方法的 方法
        --把自己作为一个参数传进来 在内部 访问 
        print(t.sex)
        print("好好学习,天天向上")
    end
}

Lua中 .和冒号的区别
Student.Learn(Student)
冒号调用方法 会默认把调用者 作为第一个参数传入方法中
Student:Learn()

申明表过后 在表外去申明表有的变量和方法
Student.name = "XXX"
Student.Speak = function()
    print("说话")
end


函数的第三种申明方式
function Student:Speak2()
    --lua中 有一个关键字 self 表示 默认传入的第一个参数
    print(self.name.."说话2")
end

C#要是使用类 实例化对象new 静态直接点
Lua中类的表现 更像是一个类中有很多 静态变量和函数
print(Student.age)
print(Student.name)
Student.Up()
Student.Speak()
Student:Speak2()
Student.Speak2(Student)

4.表的公共操作

t1 = {{age = 1,name = "123"},{age = 2,name = "345"}}

t2 = {name = "XXX",sex = true}

插入

table.insert(t1,t2);

移除

table.remove(t1)

--remove方法 传两个参数 第一个参数 是要移除内容的表
--第二个参数 是要移除内容的索引

table.remove(t1,1)

排序

t2 = {5,2,7,9,5}

--传入要排序的表 默认 降序排列

table.sort(t2)

降序

--传入两个参数 第一个是用于排序的表
--第二个是 排序规则函数

例:

table.sort(t2,function(a,b)
    if a>b then
        return true
    end
end)

拼接

tb = {"123","456","789","10101"}

str = table.concat(tb,",")

15、多脚本执行

1.全局变量和本地变量

全局变量

即为正常声明的变量

本地变量(局部变量)

需要在变量名字前面加一个 local

2.多脚本执行

关键字 require("脚本名")

3.脚本卸载

如果是require加载执行的脚本 加载一次过后不会再被执行

关键字 package.loaded["脚本名"]

卸载已经执行过的脚本 

package.loaded["脚本名"] = nil

require 执行一个脚本时 可以在脚本最后返回一个外部希望获取的内容

local testLA = require("脚本名") (可以在要执行的脚本末端写一个return 变量名,可以让testLA接收到)

4.大G表

_G表是一个总表(table) 他将我们申明的所有全局的变量都存储在其中

本地变量 加了local的变量是不会存到大_G表中

遍历大G表

for k,v in pairs(_G) do
    print(k,v)
end

16、特殊用法

1.多变量赋值

local a,b,c = 1,2,"123"

多变量赋值 如果后面的值不够 会自动补空 如果后面的值多了 会自动省略

2.多返回值

同上原理

多返回值时 用几个变量接 就有几个值
如果少了 就少接几个 如果多了 就自动补空

3.and or

--逻辑与 逻辑或
-- and or 他们不仅可以连接 boolean 任何东西都可以用来连接
-- 在lua中 只有 nil 和 false 才认为是假
-- "短路"——对于and来说 有假则假 对于or来说 有真则真
-- 所以 他们只需要判断 第一个 是否满足 就会停止计算了

4.三目运算符

由于lua不支持三目运算符 所以我们可以利用and or的机制来实现

x = 3
y = 2
-- ? :
local res = (x>y) and x or y

17、协同程序

1.协程的创建

--常用方式
--coroutine.create()
fun = function()
    print(123)
end
co = coroutine.create(fun)
--协程的本质是一个线程对象

这里返回的类型是一个线程thread

用coroutine.wrap() 返回的类型是函数

2.协程的运行

coroutine.resume(co)

3.协程的挂起

coroutine.yield(i) 

4.协程的状态

coroutine.status(协程对象)

5.协程运行状态

coroutine.running()

6.提供示例

fun2 = function()
    local i = 1
    while true do
        print(i)
        i = i + 1
        --协程的挂起函数
        print(coroutine.status(co3))
        print(coroutine.running())
        coroutine.yield(i)
    end
end

co3 = coroutine.create(fun2)
--默认第一个返回值 是 协程是否启动成功
--yield里面的返回值
isOk,tempI = coroutine.resume(co3)
print(isOk,tempI)
isOk,tempI = coroutine.resume(co3)
print(isOk,tempI)
isOk,tempI = coroutine.resume(co3)
print(isOk,tempI)

co4 = coroutine.wrap(fun2)
--这种方式的协程调用 也可以有返回值 只是没有默认第一个返回值了
print("返回值"..co4())
print("返回值"..co4())
print("返回值"..co4())


--coroutine.status(协程对象)
--dead 结束
--suspended 暂停
--running 进行中
print(coroutine.status(co3))
print(coroutine.status(co))

--这个函数可以得到当前正在 运行的协程的线程号
print(coroutine.running())

18、元表

1.元表概念

--任何表变量都可以作为另一个表变量的元表
--任何表变量都可以有自己的元表(爸爸)
--当我们子表中进行一些特定操作时
--会执行元表中的内容

2.设置元表

meta = {}
myTable = {}
--设置元表函数
--第一个参数 子表
--第二个参数 (爸爸)
setmetatable(myTable,meta)

3.特定操作

(1)__tostring

meta2 = {
    --当子表要被当作字符串使用时 会默认调用这个元表中的tostring方法
    __tostring = function(t)
        return t.name
    end
}

myTable2 = {
    name = "XXX2"

}

--设置元表函数
--第一个参数 子表
--第二个参数 (爸爸)
setmetatable(myTable2,meta2)

print(myTable2)

(2)__call

meta3 = {
    --当子表要被当作字符串使用时 会默认调用这个元表中的tostring方法
    __tostring = function(t)
        return t.name
    end,
    --当子表被当做一个函数来使用时 会默认调用这个__call中的内容
    --当希望传参数时 一定要记住 默认第一个参数 是调用者自己
    __call = function(a,b)
        print(a)
        print(b)
        print("XXX真吊")
    end
}
myTable3 = {
    name = "XXX3"
}
--设置元表函数
--第一个参数 子表
--第二个参数 (爸爸)
setmetatable(myTable3,meta3)
--把子表当作函数使用 就会调用元表的 __call方法
myTable3(1)


(3)运算符重载

meta4 = {
    --相当于运算符重载 当子表使用+运算符时 会调用该方法
    --运算符+
    __add = function(t1,t2)
        return t1.age + t2.age
    end,
    --运算符-
    __sub = function(t1,t2)
        return t1.age - t2.age
    end,
    --运算符*
    __mul = function(t1,t2)
        return 1
    end,
    --运算符/
    __div = function(t1,t2)
        return 2
    end,
    --运算符%
    __mod = function(t1,t2)
        return 3
    end,
    --运算符^
    __pow = function(t1,t2)
        return 4
    end,
    --运算符==
    __eq = function(t1,t2)
        return true
    end,
    --运算符<
    __lt = function(t1,t2)
        return true
    end,
    --运算符<=
    __le = function(t1,t2)
        return false
    end,
    --运算符..
    __concat = function(t1,t2)
        return "567"
    end

}
myTable4 = {age = 1}
setmetatable(myTable4,meta4)
myTable5 = {age = 2}
setmetatable(myTable5,meta4)

print(myTable4 + myTable5)
print(myTable4 - myTable5)
print(myTable4 * myTable5)
print(myTable4 / myTable5)
print(myTable4 % myTable5)
print(myTable4 ^ myTable5)

--如果要用条件运算符 来比较两个对象
--这两个对象的元表一定要一致 才能准确调用方法
print(myTable4 == myTable5)
print(myTable4 < myTable5)
print(myTable4 <= myTable5)

print(myTable4..myTable5)

4.__index和__newIndex

meta6Father = {
    age = 1
}
meta6Father.__index = meta6Father

meta6 = {
    --age = 1
}
--__index的赋值 写在表外面来初始化
meta6.__index = meta6
--meta6.__index = {age = 2}

myTable6 = {}
setmetatable(meta6,meta6Father)
setmetatable(myTable6,meta6)
--得到元表的方法
print(getmetatable(myTable6))

--__index 当子表中 找不到某一个属性时
--会到元表中 __index指定的表去找属性
print(myTable6.age)
--rawget 当我们使用它时 会去找自己身上有没有这个变量
myTable6.age = 1
print(rawget(myTable6,"age"))

--newIndex 当赋值时,如果赋值一个不存在的索引
--那么会把这个值赋值到newindex所指的表中 不会修改自己
meta7 = {}
meta7.__newindex = {}
myTable7 = {}
setmetatable(myTable7,meta7)
myTable7.age = 1
print(myTable7.age)
print(meta7.__newindex.age)
--rawset 该方法会忽略newindex的设置 只会该自己的变量
rawset(myTable7,"age",2)
print(myTable7.age)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值