参考自: 菜鸟教程Lua
tab1 = {key1 = "value1", key2 = "value2"}
print(tab1.key1)
tab1.key1 = nil -- value1
print(tab1.key1) -- nil
type(X) == "nil" -- true
type(X) == nil -- false
boolean 类型只有两个可选值:true(真) 和 false(假)
Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true
print(type(true)) --boolean
print(type(false)) --boolean
print(type(nil)) --nil
if false or nil then
print("至少有一个是 true")
else
print("false 和 nil 都为 false") -- 结果
end
if 0 then
print("数字 0 是 true") -- 结果
else
print("数字 0 为 false")
end
print(type(2)) --number
print(type(2.2)) --number
print(type(0.2)) --number
print(type(2e+1)) --number
print(type(0.2e-1)) --number
print(type(7.8263692594256e-06)) --number
string1 = "this is string1"
string2 = 'this is string2'
string3 = [[
菜鸟教程
]]
print("2" + 6) --8
print("2" + "6") --8
print("2 + 6") -- 2 + 6
print("-2e2" * "6") -- -1200
print("error" + 1) -- error: attempt to perform arithmetic on a string value
print("a" .. 'b') --ab
print(157 .. 428) --157428
len = "www.runoob.com"
print(#len) --14
print(#"www.runoob.com") --14
print(#"你好") --4 一个汉字两个字节
-- 创建一个空的 table
tab1 = {}
-- 数组,索引自增数字
tab2 = {"apple", "pear", "orange", "grape"}
print(tab2[1]) -- apple
-- 字典,索引字符串
tab3 = {key1 = 100, key2 = "value2"}
print(tab3.key1) -- 100
print(tab3["key1"]) --100
-- 遍历
for key,val in pairs(tab3) do
print(key .. " : " .. val)
end
-- key1 : 100
-- key2 : value2
for key,val in pairs(tab2) do
print(key .. " : " .. val)
end
-- 1 : apple
-- 2 : pear
-- 3 : orange
-- 4 : grape
-- 接上文
-- table 值的修改与添加
tab2[2] = nil
tab2["key"] = "value"
tab2[100] = "芒果"
tab2.key = "new value"
for key,val in pairs(tab2) do
print(key .. " : " .. val)
end
--[[
1 : apple
2 : pear
3 : orange
4 : grape
1 : apple
3 : orange
4 : grape
key : new value
100 : 芒果 --]]
-- 定义阶乘函数
function fact(n)
if n == 1 then
return n
else
return n*fact(n-1)
end
end
print(fact(5))
print(type(fact))
-- 直接赋值function变量
fact2 = fact
print(fact2(5))
-- 传递function 变量
function testFun(tab,fun)
for k,v in pairs(tab) do
fun(k,v)
end
end
tab = {key1 = "val1", key2 = "val2"}
function f1(k,v)
print(k..":"..v)
end
function f2(k,v)
print(k.." "..v)
end
testFun(tab,f1)
testFun(tab,f2)
-- 匿名函数
testFun(tab,
function(k,v)
print(k.."-"..v)
end
)
在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西
线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停
a = 5 -- 全局变量
a = "Hello"
local b = 20
-- 局部变量的销毁是在所语句块结束
function test()
c = 5
local d = 10
end
test()
print(c) -- 5
print(d) -- null
do
local a = 10
b = 11 -- 覆盖局部变量
print(a,b) -- 10 11
end
print(a,b) -- Hello 11
-- 多个变量同时赋值
a, b = 10, 20
a, b, c = 10, 20, "Hello"
print(a,b,c) -- 10 20 Hello
-- 交换两个变量的值
a, b = b, a
print(a,b) -- 20 10
-- 特殊情况
a, b = 10, 20, 30
print(a,b) -- 10 20
a, b, c = 10, 20
print(a,b,c) -- 10 20 nil
-- 接收返回的多个值
function test()
return 40, 50
end
a = test()
print(a) -- 40
a,b = test()
print(a,b) -- 40 50
Lua 有三种循环
while 循环,for 循环,repeat until (do while)
--[[
while(condition) do
statements
end
--]]
a = 1
while (a <= 20) do
if (a%2 == 1) then
print(a)
end
a = a + 1
end
--[[
for var = start,end,step do
statements
end
--]]
-- 数值for循环
for i = 1,10,2 do
print(i)
end
for i = 20,1,-3 do
print(i)
end
-- 泛型for循环
tab = {key1 = "val1", key2 = "val2"}
for k,v in pairs(tab) do
print(k,v)
end
-- repeat until
a = 1
repeat
print(a)
a = a + 1
until(a > 10)
-- 循环嵌套
for i = 1,10 do
for j = 1,i do
print(i)
end
end
for i = 1,10 do
j = 1
while (j <= i) do
print(i)
j = j + 1
end
end
-- if
if (0) then
print(0)
end
-- 判断变量是否为空
if (b) then
print("b不为空")
else
print("b为空")
end
-- if else
a = 100
if (a <= 50) then
print("a <= 50")
elseif (a <= 100) then
print("a <= 100")
elseif (a <= 150) then
print("a <= 150")
else
print("上面三种情况都不满足")
end
--[[
[local] function function_name( arg1, argt2, arg3..., argn)
function_body
[return value1, value2, value3..., valuen]
end
-]]
local function max (num1, num2)
if(num1 > num2) then
return num1
else
return num2
end
end
print(max(1,10)) -- 10
-- 函数可以作为数据赋值 可以作为参数传递
myprint = function(param)
print("这是打印函数"..param)
end
myprint(100) -- 这是打印函数100
function add(num1,num2,printFun)
result = num1 + num2
-- 调用传递的函数参数
printFun(result)
end
-- myprint 函数作为参数传递
add(2,5,myprint) -- 这是打印函数7
-- lua里面的函数可以返回多个值
function test()
return 40, 50, 60
end
-- 可变参数
function average(...)
res = 0
local arg = {...} --> arg 为一个表,局部变量
for k,v in pairs(arg) do
res = res + v
end
print(res/#arg)
end
average(1,2,3,4,5) -- 3
-- 算术运算符
a = 21
b = 10
c = a + b
print("a b 的和 ", c ) -- 31
c = a - b
print("a b 的差 ", c ) -- 11
c = a * b
print("a b 的积 ", c ) -- 210
c = a / b
print("a b 的商 ", c ) -- 2.1
c = a % b
print("a 对 b 求余数 ", c ) -- 1
c = a^2
print("a 的2次幂 ", c ) -- 441
c = -a
print("a 的相反数 ", c ) -- -21
-- 关系运算符
a = 21
b = 10
if( a == b ) then
print("a 等于 b" )
end
if( a ~= b ) then
print("a 不等于 b" )
end
if ( a < b ) then
print("a 小于 b" )
end
if ( a > b ) then
print(" a 大于 b" )
end
-- 逻辑运算符
a = true
b = true
print(a and b)
print(a or b)
print(not a)
-- # 取得table的最大数字索引
tab = {key1 = 12, key2 = 13}
print(#tab) -- 0
tab[1] = 123
tab[2] = 456
tab[4] = 789
print(#tab) -- 4
for k,v in pairs(tab) do
print(k,v)
end
--1 123
--2 456
--4 789
--key1 12
--key2 13
-- 字符串的定义
str1 = "Lua"
print("\"字符串 1 是\"",str1)
str2 = 'runoob.com'
print("字符串 2 是",str2)
str3 = [["Lua 教程"]]
print("字符串 3 是",str3)
-- 转义字符
-- \n 换行 \\ 代表一个反斜杠
-- \" 代表双引号 \' 代表单引号
str = 'Hello\nWorld My name is \'Micheal\''
--Hello
--World My name is 'Micheal'
print(str)
path = "C:\\Users\\10849\\Desktop\\LuaScripts"
-- C:\Users\10849\Desktop\LuaScripts
print(path)
-- 格式控制
string1 = "Lua"
string2 = "Tutorial"
number1 = 10
number2 = 20
-- 基本字符串格式化
print(string.format("基本格式化 %s %s",string1,string2))
-- 日期格式化
date = 2; month = 1; year = 2014
print(string.format("日期格式化 %02d/%02d/%03d", date, month, year))
-- 十进制格式化
print(string.format("%.4f",1/3))
-- 模式匹配
for word in string.gmatch("Hello Lua user", "%a+") do
print(word)
end
-- Hello
-- Lua
-- user
-- 一维数组
array = {"Lua", "Tutorial"}
for i= 0, 2 do
print(array[i])
end
-- 可以以负数为索引
array = {}
for i= -2, 2 do
array[i] = i *2
end
for i = -2,2 do
print(array[i])
end
-- 二维数组
array = {{"a","b"},{"c","d"},{"e","f"},{"h","i"}} -- 4*2
print(array[1][2])
for i = 1, 4 do
for j = 1, 2 do
print(array[i][j])
end
end
-- 初始化数组
array = {}
for i=1,3 do
array[i] = {}
for j=1,3 do
array[i][j] = i*j
end
end
-- 访问数组
for i=1,3 do
for j=1,3 do
print(array[i][j])
end
end
array = {"Lua","C#","Java"}
for k,v in pairs(array) do
print(k,v) -- Lua C# Java
end
array[2] = nil
for k,v in ipairs(array) do
print(k,v) -- Lua
end
--[[
for 变量列表 in 迭代函数,状态变量,控制变量 do
-- 循环体
end
-- 1.调用迭代函数,把状态变量和控制变量当作参数传递给迭代函数,状态变量只会在第一次调用时赋值
-- 2.如果迭代函数的返回值为nil,退出for循环
-- 如果不是nil的话,把返回值赋值给变量列表,并执行循环体
--]]
function square(state,control)
if(control >= state) then
return nil
else
control = control + 1
return control, control*control
-- 第一个返回值会传递给控制变量
end
end
for i,j in square,9,0 do
print(i,j)
end
tab = {}
tab[1] = "Lua"
tab["name"] = "lee"
newtab = tab
newtab[1] = "C#"
print(tab[1])
tab = nil
print(tab) -- nil
print(newtab.name) -- lee 仍然有值,只有没有变量引用了,给内存才会被回收
mytable = {"Lua","C#","Java","C++","C","abc","ABC"}
print(table.concat(mytable,",",2,4) ) -- C#,Java,C++
--插入
table.insert(mytable,"Javascript" )
print(mytable[#mytable]) -- Javascript
table.insert(mytable,2,"Boo")
print(mytable[2],mytable[3]) -- Boo C#
--删除
table.remove(mytable,2)
print(mytable[2]) -- Boo 被删除,还是C#
--排序
fruits = {"banana","orange","apple","grapes","Apple"}
print("排序前")
for k,v in ipairs(fruits) do
print(k,v)
end
table.sort(fruits)
print("排序后")
for k,v in ipairs(fruits) do
print(k,v)
end
-- 排序后
-- 1 Apple
-- 2 apple
-- 3 banana
-- 4 grapes
-- 5 orange
-- 最大值
function table_maxn(t)
local mn=nil;
for k, v in pairs(t) do
if(mn==nil) then
mn=v
end
if mn < v then
mn = v
end
end
return mn
end
tbl = {[1] = 2, [2] = 6, [3] = 34, [26] =5}
print("tbl 最大值:", table_maxn(tbl))
print("tbl 长度 ", #tbl)
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义常量
module.constant = "这是一个常量"
-- 定义函数
module.func1 = function()
print("这是一个公有函数")
end
local function func2()
print("这是一个私有函数!")
end
function module.func3()
func2()
end
return module
-- test_module.lua 文件
require("module")
print(module.constant) -- 这是一个常量
module.func1() -- 这是一个公有函数
-- module.func2() local无法访问
module.func3() -- 这是一个私有函数
-- 别名变量 m
local m = require("module")
print(m.constant)
m.func1()
m.func3()
Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法
例如,使用元表我们可以定义Lua如何计算两个table的相加操作 a+b
当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫*"__add"*的字段,若找到,则调用对应的值
“__add” 等即时字段,其对应的值(往往是一个函数或是table)就是元方法
setmetatable(table,metatable) 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败
getmetatable(table) 返回对象的元表(metatable)
-- 返回第一个表,即普通表
mytable = setmetatable(mytable,mymetatable)
-- 返回元表
print(getmetatable(mytable)) --table: 00A894C8
print(mymetatable) -- table: 00A894C8
-- 直接赋值定义
mytable = setmetatable({"Lua","Java","C#","C++"},{__metatable="lock"})
-- 使用__metatable可以保护元素,禁止用户访问元表中的成员或者修改元表
print(getmetatable(mytable)) -- lock
-- __index 元方法
-- 当访问一个不存在的索引的时候起作用
mytable = {"Lua","Java","C#","C++"}
-- 方法1
mymetatable = {
__index = function (table, key)
if(key >= 10) then
return "Javascript"
end
end
}
-- 方法2
newtable = {}
newtable[7] = "Javascript"
newtable[8] = "PHP"
newtable[9] = "C"
mymetatable = {
__index = newtable
}
-- 输出测试
mytable = setmetatable(mytable,mymetatable)
print(mytable[1])
print(mytable[10])
-- __newindex
-- 对表的数据进行修改,给表添加新的键值对的时候起作用
mytable = {"Lua","Java","C#","C++"}
-- 方式1
mymetatable = {
__newindex = function (tab, key, value)
print("我们要修改的key为:"..key.."将这个key值改为:"..value)
rawset(tab,key,value)
end
}
mytable = setmetatable(mytable,mymetatable)
mytable[1] = "C#" -- 不会输出
mytable[5] = "Lua" -- 我们要修改的key为:5将这个key值改为:Lua
print(mytable[1]) -- C#
print(mytable[5]) -- Lua
-- 方式2
-- 新数据添加进 newtable 中
newtable = {}
mymetatable = {
__newindex = newtable
}
mytable = setmetatable(mytable,mymetatable)
mytable[5] = "Lua"
print(mytable[5]) -- nil
print(newtable[5]) -- Lua
-- 为表添加操作符 __add
mytable = {"Lua","Java","C#","C++"}
mymetatable = {
__add = function(tab, newtab)
local mi = 0
-- 寻找最大索引
for k,v in pairs(tab) do
if(k > mi) then
mi = k
end
end
for k,v in pairs(newtab) do
mi = mi + 1
table.insert(tab,mi,v)
end
return tab
end
}
mytable = setmetatable(mytable,mymetatable)
newtable = {"PHP","Python"}
-- 一个实现元表即可,影响新表的元素顺序
v1 = mytable + newtable -- 必须有返回值
v2 = newtable + mytable
for k,v in pairs(v1) do
print(k,v)
end
for k,v in pairs(v2) do
print(k,v)
end
-- __call __tostring
mytable = {"Lua","Java","C#","C++"}
mymetatable = {
__call = function(tab,arg1,arg2,arg3)
print(arg1,arg2,arg3)
return "Lua"
end,
__tostring = function (mytable)
local str = ""
for k,v in pairs(mytable) do
str = str..v..","
end
return str
end
}
mytable = setmetatable(mytable,mymetatable)
v = mytable(123,12,1) -- 可以没有返回值
print(v) -- 123 12 1
print(mytable) -- Lua,Java,C#,C++,PHP,Python,
Lua I/O 库用于读取和处理文件,分为简单模式和完全模式
简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作
完全模式(complete model) 使用外部的文件句柄来实现,它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法
简单模式在做一些简单的文件操作时较为合适。但是在进行一些高级的文件操作的时候,简单模式就显得力不从心。例如同时读取多个文件这样的操作,使用完全模式则较为合适
打开文件操作语句: file = io.open (filename [, mode])
模式 | 描述 |
---|---|
r | 以只读方式打开文件,该文件必须存在 |
w | 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件 |
a | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾 |
r+ | 以可读写方式打开文件,该文件必须存在 |
w+ | 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件 |
a+ | 与a类似,但此文件可读可写 |
b | 二进制模式,如果文件是二进制文件,可以加上b |
+ | 表示对文件既可以读也可以写 |
模式 | 描述 |
---|---|
“*n” | 读取一个数字并返回它。例:file.read("*n") |
“*a” | 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件 |
“*l” | (默认) 读取下一行,在文件尾 (EOF) 处返回 nil。例:file.read("*l") |
number | 返回一个指定字符个数的字符串,或在 EOF 时返回 nil。例:file.read(5) |
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 设置默认输入文件为 test.lua
io.input(file)
-- 输出文件第一行
print(io.read())
-- 关闭打开的文件
io.close(file)
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 设置默认输出文件为 test.lua
io.output(file)
-- 在文件最后一行添加 Lua 注释
io.write("-- test.lua 文件末尾注释")
-- 关闭打开的文件
io.close(file)
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 输出文件第一行
print(file:read())
-- 关闭打开的文件
file:close()
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 在文件最后一行添加 Lua 注释
file:write("--test")
-- 关闭打开的文件
file:close()
file:seek(optional whence, optional offset): 设置和获取当前文件位置,成功则返回最终的文件位置(按字节),失败则返回nil加错误信息
file:flush(): 向文件写入缓冲中的所有数据
io.lines(optional file name): 打开指定的文件filename为读模式并返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时,将返回nil,并自动关闭文件
local function add(a,b)
assert(type(a) == "number", "a 不是一个数字")
assert(type(b) == "number", "b 不是一个数字")
return a+b
end
add(10) -- b 不是一个数字
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count")) -- 20.9560546875
mytable = nil
print(collectgarbage("count")) -- 20.9853515625
print(collectgarbage("collect")) -- 0
print(collectgarbage("count")) -- 19.4111328125
Person = { name = "lee", age = 99 }
-- 当通过 : 调用的时候,系统会自动传递当前的table给self,
-- 当通过 . 来调用方法的时候,self不会自动赋值,我们必须通过第一个参数来传递当前的table
-- a.eat(a)
-- a:eat()
function Person:eat()
print(self.name.."在吃饭")
print(self.name.."的年龄是"..self.age)
end
function Person:new(o)
local t = o or {} -- 如果o不为空,则 t = o,否则 t = {}
--调用一个属性的时候,如果t中不存在,那么会在__index 所指定的table中查找
-- setmetatable( t, { __index = self }) -- 方法1
-- 方法2
setmetatable(t,self)
self.__index = self
return t
end
person1 = Person:new()
person2 = Person:new() -- person2 与 person1 没有关系
person1.name="leenew" -- 新表定义了,再次访问时,不再采用元表的数据
person1:eat()
person1.weight = 100
print(person1.weight) -- 可以增加新的字段
-- 继承,构建新类 Student
Student = Person:new()
Student.grade=1
stu1 = Student:new()
stu1:eat() -- Student没有,访问的是Person的
print(stu1.grade) -- Student有的,访问的是Student里的