test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7", i={"1"}}
需要注意是,如果手动给一个值设置数字作为其键,若没有键的单值的索引(从1开始)大于等于前面这个被设置的数字键,则输出的时候会覆盖掉前面的值
如上,设置test[4]=2, 但是单值的数量为4(3,6,nil,7),所以test[4]被后面的7覆盖掉,变成了 test[4]=7
setmetatable(tableA, tableB):将tableB设置为tableA的元表,返回值为设置元表后的tableA
getmetatable(tableA):返回tableA的元表,若其没有元表,返回nil
__index:用来对表访问
__index的值是一个表
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键
local a = {} local b = {} b.__index = {key="value"} setmetatable(a, b) print(a["key"]) --- value -----等价------ setmetatable(a, {__index={key="value"}}) print(a["key"]) --- value
- `__index`是一个函数
当你通过键访问table的时候,如果这个键没有值,那么Lua会把table和键分别作为`__index`对应函数的两个参数传递过去
```lua
tableA = nil
local fn = function(mytable, key)
tableA = mytable
if key == "key2" then
return "查找的键为key2"
else
return nil
end
end
local a = {key1 = "value1"}
local b = {__index = fn}
setmetatable(a, b)
print(a.key1, a.key2) --- value1 查找的键为key2
print(tableA==a) --- true (说明函数接受的table是原来的table(a),不是table的metatable(b))
print(tableA==b) --- false
----另一种写法----
a = setmetatable({key1 = "value1"}, { __index = {key2 = "查找的键为key2"}})
print(a.key1, a.key2) --- value1 查找的键为key2
print(tableA==a) --- true (说明函数接受的table是主表,不是元表)
print(tableA==b) --- false
```
rawget(table, "key"):让元表的__index方法无效 ```lua
----当__index是一个表时,rawget(table, "key")让其无效---
local a = {}
local b = {}
b.__index = {key="value"}
setmetatable(a, b)
print(a.key) --- value
print(rawget(a, "key")) --- nil
---当__index是一个函数时,rawget(table, "key")让其无效---
local fn = function(mytable, key)
return key
end
local a = {key1 = "value1"}
local b = {__index = fn}
setmetatable(a, b)
print(a.key1, a.key2) --- value1 key2
print(rawget(a, "key1")) --- value1
print(rawget(a, "key2")) --- nil
```
__newindex:用来对表更新当你**给表缺少的索引进行赋值时**,解释器就会查找`__newindex` 元方法
__newindex是一个表会直接把值赋给`__newindex`对应的表,而不会对主表进行赋值
```lua
---对主表不存在的键进行赋值,会触发元表的__newindex方法---
local a = {test="已有的值"}
local b = {}
b.__newindex = {}
setmetatable(a, b)
a["key"] = "没有的key进行赋值"
print(a["key"]) --- nil
print(b["key"]) --- nil
print(b.__newindex["key"]) --- "没有的key进行赋值"
---对主表已有的键进行赋值,不会触发元表的__newindex方法---
local a = {test="已有的值"}
local b = {}
b.__newindex = {}
setmetatable(a, b)
a["test"] = "改变test的值"
print(a["test"]) --- "改变test的值"
print(b["test"]) --- nil
print(b.__newindex["test"]) --- nil
```
__newindex是一个函数在`__newindex`中如果对主表中的键进行赋值,要用`rawset`(直接赋值会导致递归)
```lua
local fn = function(mytable, k, v)
print("k: " .. k)
print("v: " .. v)
end
local a = {test="已有的值"}
local b = {}
b.__newindex = fn
setmetatable(a, b)
a["key"] = "没有的key进行赋值"
--- k: key
--- v: 没有的key进行赋值
print(a["key"]) --- nil
print(b["key"]) --- nil
print(b["__newindex"]["key"]) -- Error,因为__newindex是个函数,不是表
---在__newindex中对主表进行修改---
local fn = function(mytable, k, v)
local modi_v = "【" ..v.. "】"
rawset(mytable, k, modi_v) -- 要用rawset,直接mytable[k]=v会引起递归
end
local a = {test="已有的值"}
local b = {}
b.__newindex = fn
setmetatable(a, b)
a["key"] = "没有的key进行赋值"
--- k: key
--- v: 没有的key进行赋值
print(a["key"]) --- 【没有的key进行赋值】
print(b["key"]) --- nil
```
__call:在 Lua 以函数方式调用主表时,调用元表__call对应的函数 ```lua
local a = {}
local b = {}
b.__call = function (mytable, ...)
local t = {...}
for i, v in pairs(t) do
print(v)
end
return "__call方法"
end
local c = {10, 20, 30}
setmetatable(a, b)
print(a(1)) --- 1
print(a(1, 2, 3)) --- 1 2 3
```
__tostring:元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容 ```lua
local a = {}
local b = {}
b.__tostring = function (mytable)
return "toString方法"
end
local c = setmetatable(a, b)
print(a) --- toString 方法
```
local thing = condition and if_true or if_false ---------------等价于--------------- local thing = nil if condition then thing = if_true else thing = if_false end
pairs:输出所有非nil对象
pairs都可以遍历到,pairs首先给所有非键值对,按顺序赋一个索引作为key值,如下文的“3”、“6”,nil, “7”被分别赋为“1”, “2”, “3”, “4”,然后输出所有键值对(随机顺序,同时跳过nil)
lua
local test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7"}
for k, v in pairs(test) do
print(k..v)
end
--[[输出
13
26
47 -- 这里是7不是2,详见Lua中关于表的定义
e5
a1
]]
ipairs :输出所有非键值对,遇到nil停止
lua
local test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7"}
for i, v in ipairs(test) do
print(i..v)
end
--[[输出
13
26
]]
--因为d=nil, 是键值对,本身就不会被考虑进去,所以在剩下的 3,6,nil,7中,会输出到6,然后遇到nil终止
assert(a, b):a是要检查是否有错误的一个参数,b是a错误时抛出的信息(参数b是可选的)(assert只在debugger模式下有用)
print("enter a number:") n = io.read("*number") if not n then error("invalid input") end ---↓等价于↓--- print("enter a number:") n = assert(io.read("*number"), "invalid input")