元表
元表的定义
允许我们改变table的行为。
setmetatable(普通表,元表)
-- 元表
a = {"a","b","c"} -- 普通表 b = {} --元表
c = setmetatable(a,b)
print("------------------------")
f = {}
print("f:",f)
d = setmetatable({"c","d"},f)
print(d[1])
e = getmetatable(d)
print("e:",e)
index元方法
__index (两个下划线)
定义普通表 p。
给普通表p,设置元表y,而元表y中有__index,__index=一个表 i,i中有 我们访问的那个不存在的 key。
__index=表
print("-------------测试__index---------------") -- 普通表
tab1 = {"a","b","c"}
print(tab1[5])
-- 普通表,有一个元素 5="e" newTab = {}
newTab[5] = "e"
metaTab1 = {__index=newTab}
setmetatable(tab1, metaTab1)
print(tab1[5])
--index=函数(表,key)
-- 普通表
tab1 = {"a","b","c"} print(tab1[5])
print("原始的tab1:",tab1)
metaTab1 = {
__index=function(tab, key )
print("参数当中的tab:",tab)
print("参数当中的key:",key)
if(key == 5) then
return "index--5" end
end
}
setmetatable(tab1, metaTab1)
print(tab1[5])
请求表中key的值:
先在普通表中找,有返回,没有,看元表。
如果元表有__index, 且 __index中有对应的key。 如果没有,继续找__index的function。
newindex元方法
对表进行更新时调用。
函数用法
print("-----------newindex--------------") mytab2 = {"a","b"}
metatab2 = {
__newindex = function(tab, key ,value)
print("被调用")
-- tab[key] = value
rawset(tab,key,value)
end
}
setmetatable(mytab2,metatab2)
mytab2[3]="c"
print(mytab2[3])
表
mytab2 = {"a","b"}
mytab21 = {} metatab2 = {
__newindex = mytab21
}
setmetatable(mytab2,metatab2)
mytab2[3]="c"
print(mytab2[3])
print(mytab2[3])
为表添加操作符
加法操作
print("-------------操作符------------") tab3 = {"1","2"}
tab4 = {"a","b","c"}
metatab3 = {
__add = function(tab1,tab2) local m = #tab1
for k,v in pairs(tab2)
do
m = m+1
tab1[m] = v
end
return tab1
end
}
setmetatable(tab3,metatab3)
v = tab3 + tab4 print(v)
for k,v in pairs(v) do
print(k,v) end
__add:+ __sub: - _mul:* __div: /
__mod: %
__concat: ..
__eq:== __lt: <
_le: <=
call元方法
lua中,当表被当成函数调用时,会触发。
print("-----------call-------------") tab_a1 = {"a","b"}
print("tab_a1原始值:",tab_a1) tab_a2 = {"1","2"}
metatab_a = {
__call = function(tab, ...)
local a = {...}
for k,v in pairs(a) do
print(v)
end
end
}
setmetatable(tab_a1,metatab_a)
result = tab_a1(6,7,8)
tostring
用于修改表的输出行为。类似于java中的toString()。
print("-----------call-------------") tab_a1 = {"a","b","c","d"}
print("tab_a1原始值:",tab_a1) tab_a2 = {"1","2"}
metatab_a = {
__call = function(tab, ...)
local a = {...}
for k,v in pairs(a) do
print(v)
end
end,
__tostring = function(tab)
local str = ""
for k,v in pairs(tab) do
str = str..v..","
return str end
}
setmetatable(tab_a1,metatab_a) -- result = tab_a1(6,7,8)
print(tab_a1)
ps:每个元方法之间 用 ,
协同程序
类似于 多线程的概念。
协程和线程的区别:
一个多线程的程序,可以同时运行多个线程。而协程呢,在某个时刻,只有一个协程在运行。 线程由cpu调度,协程由代码调度。
创建协程,并运行:
# 定义协程
testAdd = coroutine.create( function(a,b)
print(a+b)
end
)
# 启动协程
# 原来暂停-》执行,原来执行-》暂停 coroutine.resume(testAdd, 1,2)
wrap
co = coroutine.wrap(
function(a)
print("参数值是:"..a)
end
)
co(2)
启动、停止
testAdd = coroutine.create(
function(a,b)
print("执行--子方法",a+b)
coroutine.yield();
print("执行--子方法",a-b)
end
)
coroutine.resume(testAdd, 1,7)
print("执行主方法")
coroutine.resume(testAdd)
返回值
testAdd = coroutine.create(
function(a,b)
print("协程执行",a+b)
coroutine.yield()
return a+b,a-b end
)
r1,r2,r3 = coroutine.resume(testAdd, 1,7)
print("返回值:",r1,r2,r3)
r1,r2,r3 = coroutine.resume(testAdd, 1,7)
print("重新执行,返回值:",r1,r2,r3)
协程状态
testAdd = coroutine.create(
function(a,b)
print("运行中 协程状态:",coroutine.status(testAdd)) coroutine.yield()
return a+b,a-b end
)
print("刚定义好的协程状态:",coroutine.status(testAdd))
r1 = coroutine.resume(testAdd,1,4)
print("启动协程结果:",r1)
print("最终的 协程状态:",coroutine.status(testAdd))
print("yield后 协程状态:",coroutine.status(testAdd))
r1 = coroutine.resume(testAdd,1,4)
print("二启动协程结果:",r1)
print("二最终的 协程状态:",coroutine.status(testAdd))
r1 = coroutine.resume(testAdd,1,4)
print("三启动协程结果:",r1)
结果:
刚定义好的协程状态: suspended
运行中 协程状态: running
启动协程结果: true
最终的 协程状态: suspended
yield后 协程状态: suspended
二启动协程结果: true
二最终的 协程状态: dead
三启动协程结果: false
协程协作
协程唯一标识
testAdd = coroutine.create(
function(a,b)
print(coroutine.running)
print("1") end
)
coroutine.resume(testAdd,1,1)
协程内部和外部协作的例子:
-- 协程内外部协作的例子 function foo(a)
print("foo 参数:",a)
return coroutine.yield(a*2) end
co = coroutine.create(
function(a,b)
print("第一次启动协程,参数:",a,b) local r = foo(a+1)
print("第二次启动协程,参数",r)
local x,y = coroutine.yield(a+b,a-b)
print("第三次启动协程,参数",x,y)
return b,"协程结束啦"
end
)
print("主程序:",coroutine.resume(co,1,5))
print("----分隔符---")
print("主程序:",coroutine.resume(co,"r"))
print("----分隔符---")
print("主程序:",coroutine.resume(co,"x","y"))
print("----分隔符---")
print("主程序:",coroutine.resume(co))
第一次resume,传入的参数是 function的参数。
第一次yield的参数,是第一次resume的返回值。
第二次resume的参数,是第一次yield的 返回值。
生产者消费者问题
思路:
1。生产者生产完 产品,(自己停下来),等待消费者消费。
2。消费者消费完产品,(自己停下来),等待生产者生产。
-- 生产者和消费者
function productor()
-- 定义生产的商品,用数字来替代 local i = 0
while i<100
do
i = i+1
print("生产了:",i)
-- 通过协程实现
coroutine.yield(i) end
end
function consumer() while true
do
-- 从生产者获取产品
local status,result = coroutine.resume(po) print("消费了:",result)
if (result == 99) then
break
end
end
end
-- 程序开始
po = coroutine.create(productor)
consumer()