数组table 可以定义一维、二维、多维数组。但是数组的索引从1开始无需声明数组长度。cities{北京,上海,广州} cities[4]南京同一数组的元素可以是任意类型。maptable可以定义出类似map的key-value数据结构。访问时可通过key访问也可以指定索引来访问。emp{name张三,age22,deptIT} emp[gender]男 print(emp[name]) emp.addr北京 print(emp.age) -- 也可以使用表达式作为key 表达式需要中括号括起来。 arr { [emp_..xxx] true, [23] hello, [hi] 123 } print(arr.emp_xxx) -- true print(arr[5]) -- hello print(arr.hi) -- 123混合结构将数组和key-value 混合在一个table中 key-value不会占用数组的数字索引值。emp{北京,name张三,上海,age22,广州,deptIT} print(1) -- 北京 print(2) -- 上海 print(3) -- 广州table操作函数table.concat() 字符串连接table.concat(table[,sep[,start[,end]]]) emp{北京,name张三,上海,age22,广州,deptIT} table.concat(emp,,,1,2) -- 北京上海将指定的table数组元素进行字符串连接。连接从start索引位置到end索引位置的所有数组元素元素间使用sep隔开。如果table是一个混合结构那么这个连接与key-value无关仅是连接数组元素。table.unpack() 拆包返回指定table的数组中从第i个元素到第j个元素的值。i和j可选默认i1j最后一个元素。emp{北京,上海,广州,深圳,大连} print(table.unpack(emp,2,3)) -- 上海 广州table.pack() 打包此函数是一个可变参。将指定参数打包成一个table返回。返回的table中有一个属性n表示table包含元素的个数。ttable.pack(北京,上海,广州,深圳,大连) print(t.n) -- 5table.maxn() 返回table中的数组的最大索引即数组包含元素的个数。table.insert() 指定table的数组部署指定位置插入一个元素其后面的元素会后移。不指定位置就插入到数组部分末尾。ttable.pack(北京,上海,广州,深圳,大连) table.insert(t,2,郑州) table.insert(t,成都)table.remove() 删除并返回table数组部分指定位置的元素。其后面的元素会前移。不指定位置默认删除数组中的最后一个元素。table.remove(t,3)table.sort() 指定table的数组元素升序排序也可以按照指定函数的规则进行排序。注意如果arr中既有字符串又有数值型那么排序会报错。如果数组中多个元素相同那么相同的元素排序结果不确定。如果数组元素中包含nil那么排序会报错。迭代器Lua有两个迭代器pairstable与ipairstable用于泛型for循环pairstable迭代整个table元素无论是数组元素还是key-valueipairstable只迭代table中的数组元素。emp{北京,name张三,上海,age22,广州,deptIT} for i,v in ipairs(emp) do print(i,v) end -- 输出结果如下 1 北京 2 上海 3 广州 for i,v in pairs(emp) do print(i,v) end -- 输出结果如下 1 北京 2 上海 3 广州 name 张三 age 22 dept IT模块Lua可以把一些公用的代码放在一个文件以API接口的形式在其他地方调用有利于代码复用和降低代码耦合度。模块文件主要由table组成。在table中添加相应的变量、函数最后文件返回该table即可。如果其他文件中需要使用该模块通过require导入该模块即可。定义模块-- 定义一个模块 rectangle {} -- 为模块添加一个变量 rectangle.pi 3.14 -- 为模块添加函数 function rectangle.perimeter(a,b) return (ab)*2 end -- 以匿名函数的方式为模块添加一个函数 rectangle.area function (a,b) return a*b end -- 定义一个全局变量与模块无关 goldenRatio 0.618 -- 定义一个局部函数与模块无关 local function circulaArea(r) return rectangle.pi*r*r end -- 定义一个全局函数与模块无关 function maxCirculAreaa,b local r math.min(a,b) return circulaArea(r) end return rectangle将以上文件保存为rectangle.lua使用模块require 文件路径或者 require “文件路径”可以省略括号。其中文件名不能写.lua扩展名。require函数有返回值返回的是模块文件最后return的table。可以使用一个变量接收这个table作为模块的别名后面就可以使用别名来访问模块了。-- 导入模块 rect require rectangle -- 访问模块属性 print(rectangle.pi) print(rect.pi) -- 访问与模块无关内容 printgoldenRatio print(maxCirculArea(3,5))再看模块模块文件中还可以定义其他与table无关的内容。这些全局变量与函数就是普通的全局变量与函数与模块无关其会随着模块的导入而同时导入。所以在使用时可以直接使用无需也不能添加模块名称。元表与元方法元表普通table的元数据表元方法元表中定义的普通表的默认行为。·每个普通table都可为其定义一个元表用于扩展其行为。比如对于table与数值相加的行为Lua没有定义用户可通过为其指定元表来扩展。或者当用户访问不存在的table元素Lua默认返回nil此时可以给table指定元表来扩展该行为给用户提示并返回指定的值。重要函数setmetatabletablemetatable:将metatable指定为普通表table的元表。getmetatable(table)获取普通表的元表。__index元方法当用户对table进行访问访问的数组索引或者key不存在系统就会自动调用元表的__index元方法。该重写的方法可以是一个函数也可以是另一个表。如果重写的__index元方法是函数且有返回值则直接返回如果没有返回值则返回nil。emp{北京,name张三,上海,age22,广州,deptIT} -- 声明一个元表 meta {} -- 将table与元表相关联 setmetatable(emp,meta) -- 有返回值的情况 meta.__index function (tab,key) return 访问..key..的值不存在 end -- 或者无返回值的情况 meta.__index function (tab,key) print(访问..key..的值不存在) end print(emp.x) print(emp[2]])__index 元方法是另一个table的情况emp{北京,name张三,上海,age22,广州,deptIT} -- 声明一个元表 meta {} -- 将table与元表相关联 setmetatable(emp,meta) -- 再定义一个普通表 other {} other[5] 成都 other[6] 重庆 -- 指定元表为另一个普通表 meta.__index other -- 在原始表中找不带会到元表指定的普通表中查找 print(emp[6]) -- 重庆__newindex元方法当为table中一个不存在的索引或key赋值时会自动调用元表的__newindex元方法。重写该方法可以是一个函数也可以是另一个表。如果重写__newindex元方法是函数且有返回值则直接返回无返回值就返回nil。emp{北京,name张三,上海,age22,广州,deptIT} -- 声明一个元表 meta {} -- 将原始表与元表关联 setmetatable(emp,meta) -- 无返回值情况 function meta.__newindex(tab,key,value) print(新增的key..key..value..value) -- 将新增的key-value加入到原始表 rawset(tab,key,value) end emp.x 青岛 print(emp.x)emp{北京,name张三,上海,age22,广州,deptIT} -- 声明一个元表 meta {} -- 将原始表与元表关联 setmetatable(emp,meta) -- 定义一个普通表 other {} meta.__newindex other emp.x 大连 print(emp.x) -- nil print(other.x) -- 大连运算符元方法如果要为一个表扩展、-、、等运算功能可重写对应的元方法。比如要扩展运算功能可重写__add元方法。这样当一个table在进行加法运算时就会自动调用其元表的__add元方法emp{北京,name张三,上海,age22,广州,deptIT,32 ,11} -- 声明一个元表 meta { __add function (tab,num) for k,v in pairs(tab) do if type(v) number then -- 若value是数值类型就做加法 tab[k] vnum end end -- 返回变化过的table return tab end } -- 将原始表与元表关联 setmetatable(emp,meta) empsum emp 5其他的运算符元方法还有 减法、乘法等可以在Lua官网查询__tostring元方法直接输出一个table输出的是table的内存地址如果要输出其内容可重写__tostring元方法emp{北京,name张三,上海,age22,广州,deptIT,32 ,11} -- 声明一个元表 meta { __add function (tab,num) for k,v in pairs(tab) do if type(v) number then -- 若value是数值类型就做加法 tab[k] vnum end end -- 返回变化过的table return tab end, __tostring function (tab) str for k,v in pairs(tab) do str str.. ..k..:..v end return str end } -- 将原始表与元表关联 setmetatable(emp,meta) print(emp)__call元方法当把一个table以函数形式来使用时会调用重写的__call元方法。该用法可以简化对table的操作将对table的操作与函数直接结合。emp{北京,name张三,上海,age22,广州,deptIT,32 ,11} -- 声明一个元表 meta { __add function (tab,num) for k,v in pairs(tab) do if type(v) number then -- 若value是数值类型就做加法 tab[k] vnum end end -- 返回变化过的table return tab end, __tostring function (tab) str for k,v in pairs(tab) do str str.. ..k..:..v end return str end, __call function (tab,num,str) for k,v in pairs(tab) do if type(v) number then tab[k] vnum elseif type(v) string then tab[k] v..str end end return tab end } -- 将原始表与元表关联 setmetatable(emp,meta) newemp emp(3,-haha) for k,v in pairs (newemp) do print(k..:..v) end元表单独定义可以将元素单独定义为一个文件。文件中仅可定义一个元表且一般文件名与元表名称相同。若一个文件要使用其他文件中定义的元表需要使用require 元表文件名 即可。如果想扩展该元表而不想修改元表文件可以在用户自己文件中重写其对应功能的元方法即可。-- 声明一个元表 meta { __add function (tab,num) for k,v in pairs(tab) do if type(v) number then -- 若value是数值类型就做加法 tab[k] vnum end end -- 返回变化过的table return tab end, __tostring function (tab) str for k,v in pairs(tab) do str str.. ..k..:..v end return str end, __call function (tab,num,str) for k,v in pairs(tab) do if type(v) number then tab[k] vnum elseif type(v) string then tab[k] v..str end end return tab end }将以上内容保存为meta.lua,需要使用的时候直接引入但后关联就可。-- 导入元表 require meta emp{北京,name张三,上海,age22,广州,deptIT,32 ,11} -- 将原始表与元表关联 setmetatable(emp,meta) -- 重写__index元方法 meta.__index function(tab,key) print(访问的..key..不存咋) end newemp emp(3,-haha) for k,v in pairs (newemp) do print(k..:..v) end面向对象Lua没有类的概念但通过table、function、元表 可以模拟和构造出类这样的功能结构。简单对象的创建通过table与function 可以创建一个简单的Lua对象table为Lua对象赋予属性function 为Lua 对象赋予行为。-- 创建一个名称为animal的对象 animal { name dog, age 3, color black, bark function () print(woof!) end } animal.bark()类的创建通过table、function与元表可以定义类使用一个table作为基础类使用一个function 作为此基础类的new方法在new方法中创建一个空表再为该空表指定一个元表。此元表重写__index 元方法且将基础表指定为重写的__index元方法。由于new中的表是空表所以访问的所有key都会从基础表中查找。-- 创建一个名称为animal的类 Animal { name no_name, age 0 } function Animal:bark(voice) print(self.name..叫了一声..voice) end -- 创建一个无参构造器 function Animal:new() -- 创建一个空表 来存储对象 local obj {} -- 为新表设置元表为AnimalL -- 在新表中找不到key时就会去AnimalL中找到key setmetatable(obj,self) self.__index self return obj end -- 添加一个含参数的构造器 function Animal:new(name,age,type) local obj {} setmetatable(obj,self) self.__index self obj.name name obj.age age obj.type type return obj end animal Animal:new() -- 给对象赋值下面的name、age、type 实际上都加到了新表中而不是AnimalL中 animal.name 旺财 animal.age 3 animal.type 狗 print(animal.name..的年龄是..animal.age..岁了它是一只..animal.type) animal:bark(汪汪) -- 调用带参数的构造器创建对象 animal2 Animal:new(小花,2,猫) print(animal2.name..的年龄是..animal2.age..岁了它是一只..animal2.type) animal2:bark(喵喵) -- 为Animal创建一个子类 Cat Animal:new() Cat.type猫 Cat.eyes 绿眼睛 function Cat:catchMouse() print(self.name..抓住了一只老鼠) end tomcat Cat:new(汤姆,5) print(tomcat.name..的年龄是..tomcat.age..岁了它是一只..tomcat.type..有..tomcat.eyes) tomcat:catchMouse()执行结果如下