大数据最全lua学习笔记_lua goto(2)

print(k,v)

end
print(“\n”)

local tab2={}
for i=-4,4 do
tab2[i]=i*10
end

for k,v in ipairs(tab2) do --遍历的是数组下标从1开始不能是负数下标,如果是负数下标的话跳过负数下标
print(k,v)
end
print(“\n”)
for k,v in pairs(tab2) do
print(k,v)
end
print(“\n”)

–二维数组
local x={
11,
22,
33
}
local y={
44,
55,
66
}
local tab3={
{
11,
22,
33
},
{
44,
55,
66
}
}

for i=1,2 do
for j=1,3 do
print(i,j,tab3[i][j])
end
print(“\n”)
end
print(“\n”)

for k,v in ipairs(tab3) do
for k2,v2 in ipairs(v) do
print(k,k2,v2)
end
print(“\n”)
end
print(“\n”)

for k,v in pairs(tab3) do
for k2,v2 in pairs(v) do
print(k,k2,v2)
end
print(“\n”)
end
print(“\n”)

–自己创建一个二维数组
local tab4={}
for i=1,3 do
tab4[i]={} --因为是二维数组,所以tab4[i]={}一定要
for j=1,2 do
tab4[i][j]=i*j*10
end
end

for k,v in ipairs(tab4) do
for k2,v2 in ipairs(v) do
print(k,k2,v2)
end
print(“\n”)
end


输出结果:



1 11
2 22
3 33
4 string

1 11
2 22
3 33
4 string
55 lua

1 10
2 20
3 30
4 40

1 10
2 20
3 30
4 40
-2 -20
-1 -10
-4 -40
-3 -30
0 0

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 10
1 2 20

2 1 20
2 2 40

3 1 30
3 2 60

PS D:\lua代码>


## 15、table操作函数



–[[
—@param list table
—@param sep? string
—@param i? integer
—@param j? integer
—@return string
—@nodiscard
function table.concat(list, sep, i, j) end
—提供一个列表,其所有元素都是字符串或数字,返回字符串 list[i]..sep..list[i+1] ··· sep..list[j]

—@param list table
—@param pos? integer
—@return any
function table.remove(list, pos) end
—移除 listpos 位置上的元素,并返回这个被移除的值。默认不写pos是最后一个位置


—查看文档

—@overload fun(list: table, value: any)
—@param list table
—@param pos integer
—@param value any
function table.insert(list, pos, value) end
—在 list 的位置 pos 处插入元素 value


—查看文档

—@generic T
—@param list T[]
—@param comp? fun(a: T, b: T):boolean
—function table.sort(list, comp)
—在表内从 list[1]list[#list] *原地* 对其间元素按指定次序排序。

—将元素从表 a1 移到表 a2
lua ---a2[t],··· = ---a1[f],···,a1[e] ---return a2 ---



—@param a1 table
—@param f integer
—@param e integer
—@param t integer
—@param a2? table
—@return table a2
function table.move(a1, f, e, t, a2) end
]]–

–table.concat(table, sep, i, j),将表中的元素拼接成一个字符串,sep是连接符号,i是起始位置,j是终止位置
–table.remove(list, pos)移除 listpos 位置上的元素,并返回这个被移除的值。默认不写pos是最后一个位置
–table.insert(list, pos, value) 在 list 的位置 pos 处插入元素 value。默认不写pos是在最后一个位置插入
–table.sort(list, comp) 数组排序,默认从小到大,可自定义排序规则
–table.move(a1, f, e, t, a2) 把数组a1中的元素往a2中拷贝



local tab1={
“abc”,
“DEF”,
“123”,
11,
[“key”]=value,
[“id”]=123
}
print(table.concat(tab1))
print(table.concat(tab1,“–”))
print(table.concat(tab1,“–”,2,3))
print(table.concat(tab1,“–”,1,2))
print(“\n”)

print(table.remove(tab1))
print(table.concat(tab1))
print(table.remove(tab1,1))
print(table.concat(tab1))
print(“\n”)

print(table.insert(tab1,“china”))
print(table.concat(tab1))
print(“\n”)

table.sort(tab1)
print(table.concat(tab1))
print(“\n”)

function cmp(a,b)
return a>b
end
table.sort(tab1,cmp)
print(table.concat(tab1))
print(“\n”)

local tab2={
“a”,
“b”
}

table.move(tab1,1,2,3,tab2) --3指定是第二个表tab2中的位置,这里就是第三个位置,1和2代表tab1中的第一个元素开始和结束就是chinaDEF
print(table.concat(tab1))
print(table.concat(tab2))
print(“\n”)

–下面的两种写法表示一样的效果,没区别
local info1={
id=123,
name=“lua”,
grade=60,
sex=“male”
}
local info2={
[“id”]=123,
[“name”]=“lua”,
[“grade”]=60,
[“sex”]=“male”
}


输出结果:



abcDEF12311
abc–DEF–123–11
DEF–123
abc–DEF

11
abcDEF123
abc
DEF123

DEF123china

123DEFchina

chinaDEF123

chinaDEF123
abchinaDEF

PS D:\lua代码>


## 16、string常用api



–[[

—接收一个字符串,将其中的小写字符都转为大写后返回其副本。

—查看文档

—@param s string
—@return string
—@nodiscard
function string.upper(s) end

return string

---
---将其中的大写字符都转为小写后返回其副本。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.lower"])
---
---@param s string
---@return string
---@nodiscard
function string.lower(s) end

return string

---
---返回其长度。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.len"])
---
---@param s string
---@return integer
---@nodiscard
function string.len(s) end

return number

---
---返回字符串 s 的翻转串。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.reverse"])
---
---@param s string
---@return string
---@nodiscard
function string.reverse(s) end

return string

---
---返回字符串的子串, 该子串从 `i` 开始到 `j` 为止。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.sub"])
---
---@param s  string
---@param i  integer
---@param j? integer
---@return string
---@nodiscard
function string.sub(s, i, j) end

return string

---
---查找第一个字符串中匹配到的 `pattern`(参见 [§6.4.1](command:extension.lua.doc?["en-us/54/manual.html/6.4.1"]))。
---
---
---@param s       string
---@param pattern string
---@param init?   integer
---@param plain?  boolean
---@return integer start
---@return integer end
---@return any ... captured
---@nodiscard
function string.find(s, pattern, init, plain) end

return number

---
---将字符串 s 中,所有的(或是在 n 给出时的前 n 个) pattern (参见 [§6.4.1](command:extension.lua.doc?["en-us/54/manual.html/6.4.1"]))都替换成 repl ,并返回其副本。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.gsub"])
---
---@param s       string
---@param pattern string
---@param repl    string|number|table|function
---@param n?      integer
---@return string
---@return integer count
---@nodiscard
function string.gsub(s, pattern, repl, n) end

return string

---
---接收零或更多的整数。 返回和参数数量相同长度的字符串。 其中每个字符的内部编码值等于对应的参数值。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.char"])
---
---@param byte integer
---@param ... integer
---@return string
---@nodiscard
function string.char(byte, ...) end

return string

---
---返回字符 `s[i]`, `s[i+1]`, ... ,`s[j]` 的内部数字编码。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.byte"])
---
---@param s  string
---@param i? integer
---@param j? integer
---@return integer ...
---@nodiscard
function string.byte(s, i, j) end

return number

]]–



local str1=“abCD1234”
local str2=string.upper(str1) --接收一个字符串,将其中的小写字符都转为大写后返回其副本。
print(str2)
local str3=string.lower(str1) --接收一个字符串,将其中的大写字符都转为小写后返回其副本。
print(str3)
print(“\n”)

print(string.len(str1)) --接收一个字符串,返回其长度。
print(string.len(“你好1bc a”)) --其中一个汉字是3个字符,总共11个字符
print(“\n”)

print(string.reverse(str1)) --接收一个字符串,返回字符串 s 的翻转串。
print(“\n”)

local a=0000
print(“china”…" is"…" best"…" country!“…” str1"…1 …1 …a…2) – … 连接符,number 如果在连接符左边,后面要空格
print(“\n”)

print(string.sub(str1,2)) --返回字符串的子串, 该子串从 i 开始到 j 为止。默认有两个参数
print(string.sub(str1,1,2))
print(string.sub(str1,-4,-2)) --负数是从右往左数
print(“\n”)

print(string.find(str1,1)) – 在字符串s中 查找pattern(可以是表达式),如果找到,则返回pattern 第一次出现的开始位置和结束位置,如果没找到,返回nil
print(string.find(str1,“abC”))
print(string.find(str1,“ab”,3)) --从指定位置开始寻找
print(string.find(str1,“ab”,3,5))
print(string.find(str1,“ab”,-8)) --负数是从右往左数
print(“\n”)

print(string.find(str1,“%d”,1)); --最后一个参数,默认就是false,开启正则匹配模式,这里寻找的是%d number型
print(string.find(str1,“(%d%d%d%d)”))
print(string.find(str1,“%d”,6,true));–最后一个参数,true 是直接当子串处理
print(“\n”)

print(string.gsub(str1,1,2)) --全部替换
print(string.gsub(str1,“ab”,“AB”,2)) --最多替换两次
print(“\n”)

print(string.char(65)) --asscil码转字符,数字只能是0~255
print(string.byte(“a”)) --字符转asscil码
print(string.byte(“abc”,1,2)); --1和2代表转几个
print(string.byte(“abc”,1,3));


输出结果:



ABCD1234
abcd1234

8
11

4321DCba

china is best country! str11102

bCD1234
ab
123

5 5
1 3
nil
nil
1 2

5 5
5 8 1234
nil

abCD2234 1
ABCD1234 1

A
97
97 98
97 98 99
PS D:\lua代码>


## 17、function常见表示形式



–[[

function进阶,常见的表现形式
    --函数普通函数

    --函数当右值,赋值给一个变量

    --匿名函数当右值

    --函数当参数

    --函数当返回值

    --匿名函数当返回值

    --函数多返回值

]]–



–普通函数
function show(a,b)
print(a,b)
end
–函数直接调用
show(“abc”,123)

–函数当右值,赋值给一个变量
func1=show
func1(“abc”,123)

–匿名函数当右值
func2=function(a,b)
print(“abc”,123)
end
func2()

–函数当参数
function func3(func,a,b)
func(a,b)
end
func3(show,“abc”,123)
func3(
function(a, b)
print(a, b)
end,
“abc”, “123”
)
print(“\n”)

–函数当返回值
function func4()
return func1
end
fun1=func4()
fun1(“abc”,123)
func4()(“abc”,123)

–匿名函数当返回值
function func5()
return function(a,b)
print(a,b)
end
end
fun2=func5()
fun2(“abc”,123)
func5()(“abc”,123)
print(“\n”)

–函数多返回值
function func6()
function func6_son1(a,b)
print(“son1”,a,b)
end
function func6_son2(a,b)
print(“son2”,a,b)
end
return func6_son1,
func6_son2,
func1,
function(a,b)
print(“son_last”,a,b)
end
end

fun3,fun4,fun5,fun6=func6()
fun4(“abc”,123)
fun5(“abc”,123)
fun6(“abc”,123)
fun3(“abc”,123)


输出结果:



abc 123
abc 123
abc 123
abc 123
abc 123

abc 123
abc 123
abc 123
abc 123

son2 abc 123
abc 123
son_last abc 123
son1 abc 123
PS D:\lua代码>


## 18、table中的function



–[[

function进阶,table中的function

]]–

function show(a)
print(a)
end

local tab1={
t1_show=show,
add=function(a,b)
return a+b
end
}
tab1.sub=function(a,b)
return a-b
end
tab1[“mul”]=function(a,b)
return a*b
end
tab1[“div”]=function(a,b)
return a/b
end

tab1.t1_show(“abc”)
tab1.t1_show(tab1.add(11,22))
tab1"t1_show"
tab1.t1_show(tab1.sub(11,22))
tab1.t1_show(tab1.mul(11,22))
tab1.t1_show(tab1.div(11,22))
print(“\n”)

calc={
add=function(a,b)
return a+b
end,
sub=function(a,b)
return a-b
end,
mul=function(a,b)
return a*b
end,
sub=function(a,b)
return a/b
end,
show=function(a)
print(a)
end
}

calc.show(calc.add(11,22))
calc.show(calc.sub(11,22))
calc.show(calc.mul(11,22))
calc.show(calc.sub(11,22))

tab2={
a=0,
b=0,
result=0,
add=function()
tab2.result=tab2.a+tab2.b
end,
sub=function()
tab2.result=tab2.a-tab2.b
end,
mul=function()
tab2.result=tab2.a*tab2.b
end,
div=function()
tab2.result=tab2.a/tab2.b
end,
show=function()
print (tab2.result)
end
}

tab2.a=11
tab2.b=22
tab2.add()
tab2.show()


输出结果:



abc
33
123
-11
242
0.5

33
0.5
242
0.5

33
0.5
242
0.5
33


## 19、用select处理可变参数



–[[

关于用select处理可变参数

select(n,...),表示获取可变参数的一部分数据从n开始
select("#",...),表示获取可变参数的个数

 ---
---接收任意数量的参数,并将它们的值打印到 `stdout`。 它用 `tostring` 函数将每个参数都转换为字符串。 
--`print` 不用于做格式化输出。仅作为看一下某个值的快捷方式。 多用于调试。 
--完整的对输出的控制,请使用 [string.format](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.format"])
-- 以及 [io.write](command:extension.lua.doc?["en-us/54/manual.html/pdf-io.write"])。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-print"])
---

---
---如果 `index` 是个数字, 那么返回参数中第 `index` 个之后的部分; 负的数字会从后向前索引(`-1` 指最后一个参数)。 
--否则,`index` 必须是字符串 `"#"`, 此时 `select` 返回参数的个数。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-select"])
---
---@param index integer|'"#"'
---@return any
---@nodiscard
function select(index, ...) end

]]–



local function func1(…)
print(select(1,…))
print(select(2,…))
print(select(3,…))
print(select(4,…))
print(select(5,…))
print(select(“#”,…))

local sum=0
local count=select("#",...)
for i=1,count do
    sum=sum+(select(i,...))
end
return sum

end

print(func1(11,22,33,44,55))
print(“\n”)

local function func2()
return 11,22,33
end

local function func3()
return 111,222,333
end

print(func2())
print(func3())
print(“\n”)
print((func2()))
print((func3()))
print(“\n”)
print(func2(),“=“,func3())
print((func2()),”
=”,func3())


输出结果:



11 22 33 44 55
22 33 44 55
33 44 55
44 55
55
5
165

11 22 33
111 222 333

11
111

11 === 111 222 333
11 === 111 222 333
PS D:\lua代码>


## 20、用pack处理可变参数



–[[

---用pack 处理函数可变参数
---table.pack(...) 将可变参打包成一个table,且会在最后多出一个n键,其对应的值是可变参的参数个数
---table.unpack(list, i, j) 解包,将table 解成可变参

---
---返回用所有参数以键 `1`,`2`, 等填充的新表, 并将 `"n"` 这个域设为参数的总数。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-table.pack"])
---
---@return table
---@nodiscard
function table.pack(...) end

---
---返回列表中的元素。 这个函数等价于
---```lua
---    return list[i], list[i+1], ···, list[j]
---```
---i 默认为 1 ,j 默认为 #list。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-table.unpack"])
---
---@generic T
---@param list T[]
---@param i?   integer
---@param j?   integer
---@return T   ...
---@nodiscard
function table.unpack(list, i, j) end

]]–



local function func1(…)
print(table.pack(…).n)

local sum=0
local tab1=table.pack(...)
for k,v in pairs(tab1) do
    if k~="n" then
        sum=sum+v
    end
end

local count=tab1.n
print(count)
for i=1,count do
    if tab1[i]~=nil then
        sum=sum+tab1[i]
    end
end

return sum

end

print(func1(11,22,nil,33,44,55,nil))
print(“\n”)

local function func2()
–return 11,22,33,44,55,66
return table.pack(11,22,33,44,55,66)
end

print(11,22,33,44,55,66)
print(func2())
print(table.unpack(func2()))
print(table.unpack(func2(),1,2))
print(“\n”)

local tab2=func2()
print(table.unpack(tab2))
print(“\n”)

—可变参转成table
local function func3(…)
local sum=0
local tab1={…}
local count=#tab1
print(count)
for k,v in pairs(tab1) do
if k~=“nil” then
sum=sum+v
end
print(k,v)
end
return sum
end

print(func3(11,22,nil,33,44,nil,55,66,77))


输出结果:



7
7
330

11 22 33 44 55 66
table: 000001926BF91DE0
11 22 33 44 55 66
11 22

11 22 33 44 55 66

9
1 11
2 22
4 33
5 44
7 55
8 66
9 77
308
PS D:\lua代码>


## 21、lua中闭包 (closure)的实现



–[[

闭包

百度百科 https://baike.baidu.com/item/闭包/10908873

闭包就是能够读取其他函数内部变量的函数。
例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

lua
当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,
这种特征在lua中我们称作词法定界。
虽然这看起来很清楚,事实并非如此。
词法定界加上第一类函数在编程语言里是一个功能强大的概念,很少语言提供这种支持。

个人理解
闭包就是指一种编码方式,一种思想,而不是指某种具体的技术或函数或库

内部函数读取外部函数的变量

lambda 表达式,经典的闭包表现方式之一

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8m1N0Ihi-1665330518835)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004001207777.png)]



local function func1(a,b)
local x=0
local y=0
return function()
x=x+1 --类似static属性,内部匿名函数访问外部函数func1的变量x
print(a,b,x,y)
end
end

func1(“abc”,123)()
print(“\n”)

local tmp1=func1(“abc”,123)
tmp1()
tmp1()
tmp1()
tmp1()
print(“\n”)

local tmp2=func1(“abc”,123)
tmp2()


输出结果:



abc 123 1 0

abc 123 1 0
abc 123 2 0
abc 123 3 0
abc 123 4 0

abc 123 1 0
PS D:\lua代码>


## 22、用闭包 (closure)实现ipairs迭代器


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NaoNqpue-1665330518835)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004002633436.png)]




---


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2KRhXAO-1665330518836)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004003844556.png)]



–[[

迭代器

百科百科 https://baike.baidu.com/item/迭代器

迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,
可在容器对象(container,例如链表或数组)上遍访的接口,
设计人员无需关心容器对象的内存分配的实现细节。


---
---如果 `t` 有元方法 `__pairs`, 以 `t` 为参数调用它,并返回其返回的前三个值。
---
---否则,返回三个值:`next` 函数, 表 `t`,以及 `nil`。 因此以下代码
---```lua
---    for k,v in pairs(t) do body end
---```
---能迭代表 `t` 中的所有键值对。
---
---参见函数 [next](command:extension.lua.doc?["en-us/54/manual.html/pdf-next"]) 中关于迭代过程中修改表的风险。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-pairs"])
---
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index?: K):K, V
---@return T
function pairs(t) end

---
---返回三个值(迭代函数、表 `t` 以及 `0` ), 如此,以下代码
---```lua
---    for i,v in ipairs(t) do body end
---```
---将迭代键值对 `(1,t[1]) ,(2,t[2]), ...` ,直到第一个空值。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-ipairs"])
---
---@generic T: table, V
---@param t T
---@return fun(table: V[], i?: integer):integer, V
---@return T
---@return integer i
function ipairs(t) end

]]–



local tab1={
11,
22,
33,
nil,
[“string”]=“lua”,
44,
nil,
55
}

for k,v in pairs(tab1) do
print(k,v)
end
print(“\n”)

for k,v in ipairs(tab1) do
print(k,v)
end
print(“\n”)

local function MyIpairs(tab1)
local count=#tab1
local index=0

return function()
    if index <= count then
        index=index+1
        if tab1[index]~=nil then
            return index,tab1[index]
        end
    end
end

end

local function MyPairs(tab1)
local count=#tab1
local index=0

return function()
    if index<=count then
        index=index+1
        -- if tab1[index]~=nil then
        -- return index,tab1[index]
        -- else
        -- index=index+1
        -- return index,tab1[index]
        -- end
        if tab1[index] == nil then
            index=index+1
        end
        return index,tab1[index]
    end
end

end

for k,v in MyIpairs(tab1) do
print(k,v)
end
print(“\n”)

for k,v in MyPairs(tab1) do
print(k,v)
end


输出结果:



1 11
2 22
3 33
5 44
7 55
string lua

1 11
2 22
3 33

1 11
2 22
3 33

1 11
2 22
3 33
5 44
7 55
9 nil
PS D:\lua代码>


## 23、元表和元方法(一)


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2E3VOrse-1665330518837)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004213130240.png)]



–[[

元表 metatable

元表并不是一个普通的表,而是一套自定义的计算规则,用这些规则,可以实现表与表之间的运算
而这些规则,都以函数的方式,写在元表中,所以又称为元方法(就是写在元表里面的方法)

起到一个类似于其它语言中的运算符重载的作用

setmetatable(table, metatable) – 将 metatable 设为 table 的元表,其返回值为table


—给指定表设置元表。 (你不能在 Lua 中改变其它类型值的元表,那些只能在 C 里做。
—如果 metatablenil, 将指定表的元表移除。 如果原来那张元表有 "\_\_metatable" 域,抛出一个错误。


—查看文档

—@param table table
—@param metatable? table
—@return table
function setmetatable(table, metatable) end
]]–



local tab1={
11,
22,
33,
44
}
local tab2={
111,
222,
333,
nil,
444,
nil
}
local tab11={
11,
22,
33,
44
}
local tab22={
111,
222,
333,
nil,
444,
nil
}
local metaTab3={}
setmetatable(tab1,metaTab3)
setmetatable(tab2,metaTab3)
local tab5={
"china ",
"best ",
"country ",
1
}
local tab6={
"is ",
"of ",
2
}
local metaTab4={}
setmetatable(tab5,metaTab4)
setmetatable(tab6,metaTab4)

metaTab3[“__add”]=function (t1,t2)
local res={}
local len1=#t1
local len2=#t2
if len1 >len2 then
len2=len1
end
for i=1,len2 do
– res[i]=t1[i]+t2[i]
local a=t1[i] or 0
local b=t2[i] or 0
res[i]=a+b
end
return res
end

metaTab4.__add=function(t1,t2)
local res={}
local len1=#t1
local len2=#t2
if len1> len2 then
len2=len1
end
for i=1,len2 do
local a=t1[i] or “”
local b=t2[i] or “”
res[i]=a…b
end
return res
end

local metaTab5={}
setmetatable(tab11,metaTab5)
setmetatable(tab22,metaTab5)
metaTab5[“__eq”]=function(t1,t2)
if #t1~=t2 then
return false
end
for i=1,#t1 do
if t1[i] ~= t2[i] then
return false
end
end
return true
end

local tab3=tab1+tab2
print(tab3)
for k,v in ipairs(tab3) do
print(k,v)
end
print(“\n”)

local tab4=tab5+tab6
print(tab4)
print(tab5)
print(tab6)
for k,v in ipairs(tab4) do
print(k,v)
end
print(“\n”)

print(tab11==tab22)


输出结果:



table: 00000290A537E1E0
1 122
2 244
3 366
4 44
5 444

table: 00000290A537D9A0
table: 00000290A537D820
table: 00000290A537D720
1 china is
2 best of
3 country 2
4 1

false
PS D:\lua代码>


## 24、元表和元方法(二)



–[[

元表 metatable

__index
当在一个表中,去取某个key
如果该表中有对应的key,就直接返回
如果没有
看有没有元表
没有元表,返回nil
有元表
看元表中有没有__index
没有,返回nil

如果__index 是个表,
并且有key, 返回值
没有key, 返回nil

如果 __index 是个function
则直接调用该function ,且表和key 都会作为该function 的参数

__newindex
如果是表,则在本表里面设一个没有的key的时候,会写到__newindex 对应的表中,而不会写自己的表
如果本表中有key,则更新本表,不会管元表

如果是function,则直接调用,且本表,key,value 都可作参数
]]–



local tab1={
[“id”]=123,
[“country”]=“china”,
[“province”]=“shanghai”,
–[“phone”]=“new_phone”
}

local meta={
–__index={} --—__index是个空表
–__index={phone=“index_phone”} —__index是一个表
__index=function(t,k)
–print(t,k)
t[k]=“new_phone”
return “index_phone”
end
}

– mm.__index={
– id=123,
– [“name”]=“tom”
– }
– setmetatable(tab1,mm.__index)

print(tab1.phone) --没有key,直接返回nil
setmetatable(tab1,meta) --设置meta为tab1的元表,但没有index表返回nil,有则查找index表
print(tab1.phone) --元表中有key,返回value
tab1.phone=nil --把自己表中的key去掉
print(tab1.phone) --自己tab1中有key,直接返回value

local tab2={}
meta.__index=tab2
print(tab1.phone) --new_phone
print(“\n”)

local tab3={
[“id”]=123,
[“country”]=“china”,
[“province”]=“shanghai”,
–[“phone”]=“new_phone”
}
local tab4={}

local meta2={
–__newindex=tab4
__newindex=function(t,k,v)
–print(t,k,v)
print(tostring(t)…" written to “…k…”:"…v)
–t[k]=v --C stack overflow 死递归,爆栈了
rawset(t,k,v) --调用原生方法,不调用重载的方法
end
}
print(tab3.phone)
setmetatable(tab3,meta2)
tab3[“phone”]=“new_phone” --当有__newindex 的时候,就写到对应的__newindex 的表中去了
print(tab3.phone)
print(tab4.phone)

meta2.__index=tab4
print(tab3.phone)


输出结果:



nil
index_phone
index_phone
new_phone

nil
table: 000002446D03BD00 written to phone:new_phone
new_phone
nil
new_phone
PS D:\lua代码>


## 25、元表和元方法(三)



–[[

元表 metatable

__tostring 用函数接管本表的返回值 返回一个string
__call 把表当类处理,此处类似于类中的构造函数,可传值,本表是第一个参数

rawget(table, index) 取本表中的index 索引对应的值,不受元表干扰,没有就返回nil;
rawset(table, index, value) 给本表添加元素,不受元表干扰


—在不触发任何元方法的情况下 获取 table[index] 的值。 table 必须是一张表; index 可以是任何值。

—查看文档

—@param table table
—@param index any
—@return any
—@nodiscard
function rawget(table, index) end


—在不触发任何元方法的情况下 将 table[index] 设为 value。 table 必须是一张表, index 可以是 nilNaN 之外的任何值。 value 可以是任何 Lua 值。
—这个函数返回 table


—查看文档

—@param table table
—@param index any
—@param value any
—@return table
function rawset(table, index, value) end
]]–



local tab1={
[“id”]=123,
[“name”]=“tom”
}

local meta={}
setmetatable(tab1,meta)

print(tab1)
print(tab1.phone)
print(“\n”)

meta.__tostring=function(t)
local str=“”
for k,v in pairs(t) do
str=str…k…" : "…v
end
t[“phone”]=123456
return str
end

print(tab1)
print(tab1.phone) --在上一句执行完之后,才有phone 字段
print(“\n”)

meta.__call=function(t,…)
print(t)
print(…)
local t2={}
for k,v in pairs(t2) do
print(k,v)
end
end

tab1(123)
print(“\n”)
tab1()
print(“\n”)

local tab2={
[“id”]=123,
[“name”]=“tom”
}
local tab3={}

print(tab2.id)
print(tab2.phone)
print(“\n”)

local MT={
–__index={phone=123456}
__index=function(t,k)
print(t,k)
end,

__newindex=tab3

}
setmetatable(tab2,MT)
print(tab2.id)
print(tab2.phone)
print(“\n”)
print(rawget(tab2,“id”))
print(rawget(tab2,“phone”))
print(“\n”)
print(“\n”)

print(tab2.country)
–tab2.country=“china”
rawset(tab2,“country”,“china”)
print(tab2.country,tab3.country)


输出结果:



table: 000001DCDA5A0770
nil

name : tomid : 123
123456

name : tomphone : 123456id : 123
123

name : tomphone : 123456id : 123

123
nil

123
table: 000001DCDA5A15F0 phone
nil

123
nil

table: 000001DCDA5A15F0 country
nil
china nil
PS D:\lua代码>


## 26、面向对象 self



–[[

类 class
对象 new class(实例化)
继承、构造、析构

table={}
metatable={}
self

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TeV4I1WZ-1665330518838)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005183655058.png)]



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end
}
print(tab1.id,tab1.name,tab1.getId())
print(“\n”)

local tab2=tab1
print(tab1,tab2)
tab1=nil
print(tab2.id,tab2.name)
print(tab2.getId())


输出结果:



123 tom 123

table: 0000022D822910F0 table: 0000022D822910F0
123 tom
C:\Users\hp.vscode\extensions\actboy168.lua-debug-1.60.0-win32-x64\runtime\win32-x64\lua54\lua.exe: …于面向对象/lua关于面向对象_self/lua关于面
向对象_self.lua:17: attempt to index a nil value (global ‘tab1’)
stack traceback:
…于面向对象/lua关于面向对象_self/lua关于面向对象_self.lua:17: in field ‘getId’
…于面向对象/lua关于面向对象_self/lua关于面向对象_self.lua:27: in main chunk
[C]: in ?
PS D:\lua代码>


此时print(tab2.getId())发生错误,错误结果如上图所知,tab1=nil之后,tab2就不能找到tab1.id了。


解决办法1:把对象当做参数传过去



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end,
[“getName”]=function(obj)
return obj.name
end
}
–print(tab2.getId())
print(tab2.getName(tab2))


输出结果:



tom


解决办法2:引入像this指针一样的self引用



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end,
[“getName”]=function(obj)
return obj.name
end
}

function tab1:getId2()
return self.id
end
function tab1:getName2()
return self.name
end

print(tab1.id,tab1.name,tab1.getId())
print(“\n”)

local tab2=tab1
print(tab1,tab2)
tab1=nil
print(tab2.id,tab2.name)
–print(tab2.getId())
print(tab2.getName(tab2))
print(“\n”)

print(tab2:getId2(),tab2:getName2())


输出结果:



123 tom 123

table: 0000026284C41610 table: 0000026284C41610
123 tom
tom

123 tom
PS D:\lua代码>


## 27、面向对象自索引


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPsUuOup-1665330518838)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005191539388.png)]



–[[

自索引 自己索引自己

]]–

local tab1={
[“id”]=123,
[“name”]=“tom”
}

local indexTable={
[“phone”]=123456
}

local meta={
–__index=indexTable
__index=meta, --此处meta不存在,所以索引__index=nil
[“phone”]=123456
}

–meta.__index=meta --自己索引自己,这就是自索引
setmetatable(tab1,meta)

print(tab1.phone)
print(“\n”)

print(tab1,indexTable,meta)


输出结果:



nil

table: 000001EA7DEE1720 table: 000001EA7DEE1AA0 table: 000001EA7DEE1760
PS D:\lua代码>


## 28、面向对象自索引实现继承



–[[

自索引: 自己索引自己

用自索引实现继承

典型的面向对象写法:子类继承父类,子类调用父类方法
]]



local father={
[“id”]=123,
[“name”]=“father”
}

function father:fasy()
print(“father say”,self.id,self.name)
end

father.__index=father --父类加自索引

local son={
[“id”]=456,
[“name”]=“son”
}
function son:sonsy()
print(“son say”)
end
setmetatable(son,father) --设置子类的元表为父类

father:fasy()
son:sonsy()
print(“\n”)

son:fasy()


输出结果:



father say 123 father
son say

father say 456 son
PS D:\lua代码>


## 29、面向对象类的实例化



–[[

类 class
对象   new class()
继承,构造,析构

table {}
metatable {}

class x{
    ....
}

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6AWXUBTq-1665330518840)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005195039237.png)]


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxPgmqge-1665330518840)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005201428470.png)]



local userinfo={
[“id”]=123,
[“name”]=“tom”,
[“age”]=23
}
userinfo.__index=userinfo --自索引

local u1=userinfo
local u2=u1
print(userinfo.id,u1.id,u2.id)
u2.id=456
print(userinfo,u1,u2)
print(userinfo.id,u1.id,u2.id)
print(“\n”)
function userinfo:new(obj)
– local obj=obj or {}
obj=obj or {}
setmetatable(obj,self) --元表继承
return obj
end
function userinfo:setAeg(val)
self.age=self.age+val
return self.age
end

– local u3=userinfo:new({[“id”]=789,[“name”]=“jerry”})
local u3=userinfo:new({[“id”]=789})
userinfo.name=“jerry”
print(u3)
print(u2.id,u3.id)
print(“\n”)
print(u2.name,u3.name)
u3.name=“tom” --__newindex
print(u2.name,u3.name)
userinfo.name=“lucy”
print(u2.name,u3.name)
print(“\n”)

print(u2.age,u3.age)
u3:setAeg(100)
print(u2.age,u3.age)


输出结果:



123 123 123
table: 0000016CCBEB43F0 table: 0000016CCBEB43F0 table: 0000016CCBEB43F0
456 456 456

table: 0000016CCBEB4370
456 789

jerry jerry
jerry tom
lucy tom

23 23
23 123
PS D:\lua代码>


## 30、面向对象多重继承


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n9LV61Kl-1665330518841)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005203241755.png)]



–[[

–多重继承
]]

local grandFather={
[“id”]=123,
[“name”]=“grandFather”
}

grandFather.__index=grandFather

local father={
–[“id”]=456,
[“name”]=“father”
}
father.__index=father
setmetatable(father,grandFather)

local son={
–[“id”]=789,
[“name”]=“son”
}
setmetatable(son,father)

print(grandFather.id);–找自己有没有 id 这个索引,有,直接发返回123

print(father.id);–先找自己,没有 id 这个索引,所以看有没有元表,元表是 grandfather,然后去找 grandfather的 __index,找到,所以返回123

print(son.id);–先找自己,没有 id 这个索引,所以看有没有元表,元表是 father,然后去找 father的 __index,
– father.__index 里面也没有 id 这个索引,但是 father.__index 有元表,是 grandfather
– 所以去找 grandfather.__index 里面有没有 id 这个索引,有,所以返回123

print(grandFather.name,father.name,son.name);
print(“\n”)

local userInfo={
[“id”]=456,
[“name”]=“tom”,
[“age”]=23
}

function userInfo:new(obj)
obj=obj or {}

self.__index=self        --父类自己索引自己

setmetatable(obj,self)  ---谁调用new 方法,此处的 元表self 就是谁
return obj

end

local u1=userInfo:new({[“id”]=456})
print(userInfo.id,u1.id)
print(userInfo.name,u1.name)
print(“\n”)

local u2=u1:new()
print(userInfo.id,u1.id,u2.id)
print(userInfo.name,u1.name,u2.name)
print(“\n”)

local u3=u2:new({[“age”]=22})

print(userInfo.id,u1.id,u2.id,u3.id)
print(userInfo.name,u1.name,u2.name,u3.name)
print(userInfo.age,u1.age,u2.age,u3.age)


输出结果:



123
123
123
grandFather father son

456 456
tom tom

456 456 456
tom tom tom

456 456 456 456
tom tom tom tom
23 23 23 22
PS D:\lua代码>


## 31、面向对象重写



–[[

重写

]]

local userInfo={
[“id”]=123,
[“name”]=“tom”
}

function userInfo:new(obj)
obj=obj or {}
setmetatable(obj,self) —谁调用new 方法,此处的 元表self 就是谁
self.__index=self —父类的索引
return obj
end

function userInfo:say()
print(“useinfo say”)
end

local u1=userInfo:new()
local u2=u1:new({[“id”]=456})
print(userInfo.id,u1.id,u2.id)
print(userInfo.name,u1.name,u2.name)
print(“\n”)

u1[“phone”]=12312
print(userInfo.phone,u1.phone,u2.phone)
u1.phone=nil
print(userInfo.phone,u1.phone,u2.phone)
print(“\n”)

userInfo:say()
u1:say()
u2:say()
print(“\n”)

function u1:say()
print(“u1 say”)
end
u1:say()
print(“\n”)

function u2:hello()
print(“u2 hello”)
end
–userInfo:hello()
–u1:hello()
u2:hello()


输出结果:



123 123 456
tom tom tom

nil 12312 12312
nil nil nil

useinfo say
useinfo say
useinfo say

u1 say

u2 hello
PS D:\lua代码>


## 32、面向对象成员私有化



–[[

成员私有化
]]

function userInfo()
local member={
[“id”]=123,
[“name”]=“tom”,
[“province”]=“shanghai”
}
local function getId()
return member.id
end
local function setId(val)
member.id=val
end

--只暴露方法给外面,表中成员变量私有化
return {
    getId=getId,   --左边key,右边value
    setId=setId,

    getName=function()
        return member.name
    end
}

end

print(userInfo().getName())
print(userInfo().getId())
print(“\n”)

local users=userInfo()
print(users.getId())
print(users.getName())
print(users.setId(456))
print(users.getId())


输出结果:



tom
123

123
tom

456
PS D:\lua代码>


## 33、协程(coroutine)



–[[

协程

协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。
一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。
我们知道多个线程相对独立,有自己的上下文,切换受系统控制;
而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

【可以把协程看成是一个可以自己自行决定调度切换的线程】

编程语言Lua从5.0版开始支持协程的概念,极大的扩展了Lua的能力。Lua的协程通过扩展库coroutine来实现

百度百科 https://baike.baidu.com/item/协程/8652240

API https://www.lua.org/manual/5.4/manual.html#6.2

这里co是协程句柄,由coroutine.create()创建。

coroutine.close (co) -------------------- 关闭协程,返回bool
coroutine.create (f) -------------------- 创建协程,传入一个function,返回一个协程句柄
coroutine.isyieldable ([co]) ------------ 判断协程是否是 yield 状态
coroutine.resume (co [, val1, ···]) ----- 将挂起态的协程重新激活
coroutine.running () -------------------- 获取正在运行的协程
coroutine.status (co) ------------------- 获取co句柄对应的协程的状态 [suspended(挂起),running(执行中),dead(结束)]
coroutine.wrap (f) ---------------------- 用function 创建一个新的协程
coroutine.yield (···) ------------------- 挂起当前协程

对于线程
线程(英语:thread)是操作系统能够进行运算调度的最小单位。
它被包含在进程之中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
在Unix System V及SunOS中也被称为轻量进程(lightweight processes),
但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,
如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如 Windows 7的线程,进行混合调度。

同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。
但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己 的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。

在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执 行吞吐率。
在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计 算的部分分开来执行,
编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。
https://baike.baidu.com/item/%E7%BA%BF%E7%A8%8B/103101?fromModule=lemma- qiyi_sense-lemma

对于进程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位, 是操作系统结构的基础。
在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;
在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的 实体。
https://baike.baidu.com/item/%E8%BF%9B%E7%A8%8B/382503?fromModule=lemma-qiyi_sense-lemma
]]–


协程主要函数如下:



—@meta

    ---
    ---
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine"])
    ---
    ---@class coroutinelib
    coroutine = {}

    ---
    ---创建一个主体函数为 `f` 的新协程。 f 必须是一个 Lua 的函数。 返回这个新协程,它是一个类型为 `"thread"` 的对象。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.create"])
    ---
    ---@param f async fun()
    ---@return thread
    ---@nodiscard
    function coroutine.create(f) end

    ---
    ---如果协程 `co` 可以让出,则返回真。`co` 默认为正在运行的协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.isyieldable"])
    ---
    ---@param co? thread
    ---@return boolean
    ---@nodiscard
    function coroutine.isyieldable(co) end

    ---@version >5.4
    ---
    ---关闭协程 `co`,并关闭它所有等待 \*to-be-closed\* 的变量,并将协程状态设为 `dead` 。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.close"])
    ---
    ---@param co thread
    ---@return boolean noerror
    ---@return any errorobject
    function coroutine.close(co) end

    ---
    ---开始或继续协程 `co` 的运行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.resume"])
    ---
    ---@param co thread
    ---@param val1? any
    ---@return boolean success
    ---@return any ...
    function coroutine.resume(co, val1, ...) end

    ---
    ---返回当前正在运行的协程加一个布尔量。 如果当前运行的协程是主线程,其为真。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.running"])
    ---
    ---@return thread running
    ---@return boolean ismain
    ---@nodiscard
    function coroutine.running() end

    ---
    ---以字符串形式返回协程 `co` 的状态。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.status"])
    ---
    ---@param co thread
    ---@return
    ---| '"running"' # 正在运行。
    ---| '"suspended"' # 挂起或是还没有开始运行。
    ---| '"normal"' # 是活动的,但并不在运行。
    ---| '"dead"' # 运行完主体函数或因错误停止。
    ---@nodiscard
    function coroutine.status(co) end

    ---
    ---创建一个主体函数为 `f` 的新协程。 f 必须是一个 Lua 的函数。 返回一个函数, 每次调用该函数都会延续该协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.wrap"])
    ---
    ---@param f async fun()
    ---@return fun(...):...
    ---@nodiscard
    function coroutine.wrap(f) end

    ---
    ---挂起正在调用的协程的执行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.yield"])
    ---
    ---@async
    ---@return any ...
    function coroutine.yield(...) end

    return coroutine


–业务,取钱,取100w
local function func1(a,b)

local aa=a\*2
local bb=b\*2
local x,y,z=coroutine.yield(aa,bb,"100w")
print(x,y,z)

print(coroutine.status(handle)) --这里能看出协程是执行中
print("\n")

end

handle=coroutine.create(func1) — 去银行办业务, 然后告诉大堂经理,要取现金(要执行func1),大堂经理会帮你叫号,给你一个小票(handle)
print(handle)
print(type(handle))
print(“\n”)

print(coroutine.status(handle)) — 挂起状态,等待执行或结束,(你拿到小票了,就去等着叫号,下一步,也可能这个号作废,也可能叫你去办业务)
print(“\n”)

–print(coroutine.resume(handle)) — 叫到你的号了,你拿着小票去窗口办业务(执行 func1)
print(coroutine.resume(handle,11,22)) — resume是阻塞的,要等到调用结束,然后返回调用成功或失败状态(bool)以及其它值
----这里的coroutine.resume执行的是local x,y,z=coroutine.yield(aa,bb,“100w”)等号左边部分
— 并且把你的身份证,银行卡还给你,再把你取的一百万给你
print(coroutine.status(handle))
print(“\n”)

print(coroutine.resume(handle,“aa”,“bb”,“cc”)) --再办一个业务,查查我其它的卡上的余额,IC卡,IQ都给你(aa,bb,cc)
–这里的coroutine.resume执行的是local x,y,z=coroutine.yield(aa,bb,“100w”)等号右边部分
print(coroutine.status(handle))
print(“\n”)

coroutine.close(handle) ---- 业务办完了,好评结束
print(coroutine.status(handle)) ---- dead 结束状态
print(“\n”)


输出结果:



thread: 00000230356A9418
thread

suspended

true 22 44 100w
suspended

aa bb cc
running

true
dead

dead

PS D:\lua代码>


## 34、协程(coroutine)双循环切换


普通方法双循环输出:



–[[

–协程(coroutine)双循环切换
]]

local function sleep(n)
local now=os.clock()
while now+n >=os.clock() do
– statements
end
end

local function func1()
while true do
print(“func 11”)
sleep(1)
print(“func 22”)
sleep(1)
end
end

local function func2()
while true do
print(“func 22”)
sleep(1)
end
end

func1()
–func2()


输出结果:



func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11


定义一个标志位输出双循环切换:



local function func3(flag)
while true do
print(“func 33”)
sleep(1)
if flag%2 ==0 then
break
end
end
end

local function func4(flag)
while true do
print(“func 44”)
sleep(1)
if flag %2 ~=0 then
break
end
end
end

local flag=0
while true do
if flag %2 ==0 then
func3(flag)
else
func4(flag)
end
flag=flag+1
end


输出结果:



func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11
func 22
func 11


协程实现双循环切换:



local function func5()
while true do
local rs=coroutine.resume(handle2)
print(rs,“func 55”)
sleep(1)
end
end

local function func6()
while true do
print(“xxxsxxxxxxxxxx”)
coroutine.yield()
print(“func 66”)
sleep(1)
end
end

local handle1=coroutine.create(func5)
handle2=coroutine.create(func6)
coroutine.resume(handle1)


输出结果:



xxxsxxxxxxxxxx
true func 55
func 66
xxxsxxxxxxxxxx
true func 55
func 66
xxxsxxxxxxxxxx
true func 55
func 66
xxxsxxxxxxxxxx
true func 55
PS D:\lua代码> ^C


**记住一点:调用者与被调用者之间的resume-yield关系不会颠倒。当一个协同程序调用yield时不会进入新的函数也就是不会执行yield之下的代码,而是执行的是一个未决的resume,意思就是返回执行resume左边的代码。同样,当一个协同程序调用resume时不会进入新的函数也就是不会执行resume之下的代码,而是返回yield的调用。**


## 35、协程(coroutine)生产者消费者模型



–[[

协程

生产者消费者模型

你去吃串,
生产者 烤串的小哥
消费者 你

小哥烤一串,你吃一串
小哥烤一串,你吃一串
小哥烤一串,你吃一串

这就是生产者消费者模型

]]–



local function sleep(n)
local now=os.clock()
while now+n >=os.clock() do
– statements
end
end
local function prod()
local i=0
while true do
i=i+1
coroutine.yield(i) --生产者生产出后,返回给消费者,并挂起,
end
end

local function consume()
while true do
local flag,i=coroutine.resume(prodHandle) --消费者用协程取找生产者要
print(flag,i)
sleep(2)
end
end

prodHandle=coroutine.create(prod)
local consumHandle=coroutine.create(consume)
coroutine.resume(consumHandle) --从消费者开始


输出结果:



true 1
true 2
true 3
true 4
true 5
true 6
true 7
true 8
true 9
true 10
true 11
true 12
true 13
true 14
true 15
true 16
true 17
true 18
true 19
true 20
true 21
true 22
true 23


## 36、文件操作



–[[

文件操作

io.open (filename [, mode])

r 只读方式打开,文件必须存在。
w 只写方式打开,文件存在则删除原有内容,文件不存在则创建。
a 追加方式打开,文件存在,则写入的数据会往最后追加,文件不存在则创建。
r+ 读写方式打开,文件必须存在。
w+ 读写方式打开,文件存在则删除原有内容,文件不存在则创建。
a+ 与a类似,但文件可读写。
b 二进制模式,如果文件是二进制文件,可以加上b

  • 修饰符,表示对文件既可以读也可以写

io.read()
*n 读取一个数字 读取不为字符的后续数字,遇到字符就停止读取
*a 读取所有内容
*l 默认值,读取下一行
123 从当前位置开始,读取123个字符长度

file:seek(whence, offset)

whence
set 从头开始
cur 从当前位置开始
end 从末尾开始

file:seek() 无参数,返回的是当前位置


—用字符串 mode 指定的模式打开一个文件。

—查看文档

—@param filename string
—@param mode? openmode
—@return file*?
—@return string? errmsg
—@nodiscard
function io.open(filename, mode) end


—设置 file 为默认输入文件。

—查看文档

—@overload fun():file*
—@param file string|file*
function io.input(file) end

—读文件 file, 指定的格式决定了要读什么。

—查看文档

—@param … readmode
—@return any
—@return any …
—@nodiscard
function io.read(…) end

function io.read(…integer|“L”|“a”|“l”|“n”)
读文件 file, 指定的格式决定了要读什么。

查看文档

…(param):
| “n” – 读取一个数字,根据 Lua 的转换文法返回浮点数或整数。
| “a” – 从当前位置开始读取整个文件。
-> “l” – 读取一行并忽略行结束标记。
| “L” – 读取一行并保留行结束标记。
end

—设置 file 为默认输出文件。

—查看文档

—@overload fun():file*
—@param file string|file*
function io.output(file) end


—设置及获取基于文件开头处计算出的位置。

—查看文档

—@param whence? seekwhence
—@param offset? integer
—@return integer offset
—@return string? errmsg
function file:seek(whence, offset) end
]]–



local f1=io.open(“file/a.txt”,“r+”)
if f1nil then
print(“文件不存在”)
os.exit()
end
local f2=io.open(“file/b.txt”,“w+”)
if f2
nil then
print(“文件不存在”)
os.exit()
end
– function io.read(…integer|“L”|“a”|“l”|“n”)
– 读文件 file, 指定的格式决定了要读什么。

– 查看文档

– …(param):
– | “n” – 读取一个数字,根据 Lua 的转换文法返回浮点数或整数。
– | “a” – 从当前位置开始读取整个文件。
– -> “l” – 读取一行并忽略行结束标记。
– | “L” – 读取一行并保留行结束标记。
– end

io.input(f1) --把f1的文件句柄放入到io,这里指的是当前输入终端
–print(io.read(“*a”)) --*a是读取文件中所有内容
print(io.read(“*l”)) --*l是读取一行并忽略结束标记
–print(io.read(“*L”)) --“L” – 读取一行并保留行结束标记。
–print(io.read(“*L”))
print(io.read(“*n”)) --*n 读取一个数字 读取不为字符的后续数字,遇到字符就停止读取
print(“\n”)

while true do
local str=io.read()
if str== nil then
break
end
print(str)
end
print(“\n”)

io.write(“AB”)
io.output(f1) --把io的内容写到 f1
–io.write(1234567890)
io.close(f1)
–f1:close()
print(“\n”)

io.output(f2) --把io的内容输出到 f2文件中
io.write(“abc”)
io.write(123)
–io.input(f2)
–print(io.read(“*a”))
print(“\n”)
io.close(f2)

local f3=io.open(“file/a.txt”,“r+”)
if f3 == nil then
print(“文件不存在”)
os.exit()
end

io.input(f3)
print(f3:read(“*l”))
print(f3:read(“*a”))
f3:close()
print(“\n”)

local f4=io.open(“file/a.txt”,“r+”)
if f4 == nil then
print(“文件不存在”)
os.exit()
end
print(“\n”)

print(f4:seek())
io.input(f4)
print(io.read(“*l”))
print(f4:seek())
print(“\n”)

print(f4:seek(“cur”))
print(io.read(“*l”))
print(“\n”)

print(f4:seek(“set”))
print(io.read(“*l”))
print(“\n”)

print(f4:seek(“end”,-5))
print(io.read(“l”))


输出结果:



123456
654

a321
abcdef

AB

123456
654a321
abcdef

0
123456
8

8
654a321

0
123456

18
bcdef
PS D:\lua代码>


## 37、包(模块)管理



local helper2={}

helper2.getIp=function ()
return “127.0.0.1”
end

helper2.getVersion=function()
return “1.0”
end

local tools={}

tools.getOs=function()
return “windows”
end

– return {helper=helper,tools=tools}
return helper2



local helper1={}

helper1.getIp=function ()
return “127.0.0.1”
end

helper1.getVersion=function()
return “1.0”
end

local tools={}

tools.getOs=function()
return “windows”
end

– return {helper=helper,tools=tools}
return helper1



local tmpHelper=require(“helper”)
local tmpHelper2=require(“file/helper2”) --相对路径

package.path=package.path…“;/tmp/?.lua” --把tmp文件下的lua文件加入package.path绝对路径

print(require(“helper”))

helper={
getIp=function()
return “192.168.1.1”
end
}
print(“\n”)
print(helper.getIp())
print(tmpHelper.getIp())
print(tmpHelper.getVersion())
print(tmpHelper2.getVersion())
–print(tmpTools.getOs())
print(“\n”)

–package.preload
–package.loaded;

–找lua源文件和so 库
print(package.path)
print(package.cpath)
print(“\n”)

for k,v in pairs(package.preload) do
print(k,v)
end
print(“\n”)

for k,v in pairs(package.loaded) do
print(k,v)
end


输出结果:



table: 0000021704467FF0

192.168.1.1
127.0.0.1
1.0
1.0

D:\lua代码/?.lua;D:\lua代码/?.lua;/tmp/?.lua
D:\lua代码/?.dll;D:\lua代码/?.dll

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

– 读取一行并保留行结束标记。
– end

io.input(f1) --把f1的文件句柄放入到io,这里指的是当前输入终端
–print(io.read(“*a”)) --*a是读取文件中所有内容
print(io.read(“*l”)) --*l是读取一行并忽略结束标记
–print(io.read(“*L”)) --“L” – 读取一行并保留行结束标记。
–print(io.read(“*L”))
print(io.read(“*n”)) --*n 读取一个数字 读取不为字符的后续数字,遇到字符就停止读取
print(“\n”)

while true do
local str=io.read()
if str== nil then
break
end
print(str)
end
print(“\n”)

io.write(“AB”)
io.output(f1) --把io的内容写到 f1
–io.write(1234567890)
io.close(f1)
–f1:close()
print(“\n”)

io.output(f2) --把io的内容输出到 f2文件中
io.write(“abc”)
io.write(123)
–io.input(f2)
–print(io.read(“*a”))
print(“\n”)
io.close(f2)

local f3=io.open(“file/a.txt”,“r+”)
if f3 == nil then
print(“文件不存在”)
os.exit()
end

io.input(f3)
print(f3:read(“*l”))
print(f3:read(“*a”))
f3:close()
print(“\n”)

local f4=io.open(“file/a.txt”,“r+”)
if f4 == nil then
print(“文件不存在”)
os.exit()
end
print(“\n”)

print(f4:seek())
io.input(f4)
print(io.read(“*l”))
print(f4:seek())
print(“\n”)

print(f4:seek(“cur”))
print(io.read(“*l”))
print(“\n”)

print(f4:seek(“set”))
print(io.read(“*l”))
print(“\n”)

print(f4:seek(“end”,-5))
print(io.read(“l”))


输出结果:



123456
654

a321
abcdef

AB

123456
654a321
abcdef

0
123456
8

8
654a321

0
123456

18
bcdef
PS D:\lua代码>


## 37、包(模块)管理



local helper2={}

helper2.getIp=function ()
return “127.0.0.1”
end

helper2.getVersion=function()
return “1.0”
end

local tools={}

tools.getOs=function()
return “windows”
end

– return {helper=helper,tools=tools}
return helper2



local helper1={}

helper1.getIp=function ()
return “127.0.0.1”
end

helper1.getVersion=function()
return “1.0”
end

local tools={}

tools.getOs=function()
return “windows”
end

– return {helper=helper,tools=tools}
return helper1



local tmpHelper=require(“helper”)
local tmpHelper2=require(“file/helper2”) --相对路径

package.path=package.path…“;/tmp/?.lua” --把tmp文件下的lua文件加入package.path绝对路径

print(require(“helper”))

helper={
getIp=function()
return “192.168.1.1”
end
}
print(“\n”)
print(helper.getIp())
print(tmpHelper.getIp())
print(tmpHelper.getVersion())
print(tmpHelper2.getVersion())
–print(tmpTools.getOs())
print(“\n”)

–package.preload
–package.loaded;

–找lua源文件和so 库
print(package.path)
print(package.cpath)
print(“\n”)

for k,v in pairs(package.preload) do
print(k,v)
end
print(“\n”)

for k,v in pairs(package.loaded) do
print(k,v)
end


输出结果:



table: 0000021704467FF0

192.168.1.1
127.0.0.1
1.0
1.0

D:\lua代码/?.lua;D:\lua代码/?.lua;/tmp/?.lua
D:\lua代码/?.dll;D:\lua代码/?.dll

[外链图片转存中…(img-fgkzkQfb-1714768715222)]
[外链图片转存中…(img-lGZy9agB-1714768715223)]
[外链图片转存中…(img-8jhcXv9r-1714768715224)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值