..
(相对于java语言的+)#变量名
,1个汉字占3个字符长度,1个英文占1个字符长度tostring()
tonumber()
转换失败值为nil
function 函数名(...)
...函数体
end
函数名 = function(...)
...函数体
end
function可以当作参数传递,允许匿名定义。
函数的构造式:function(param) end
function fun(...)
-- ...就是变长参数,需要用一个表存起来再用
arg = {...}
print(arg[1])
end
function F1()
return function()
print("123")
end
end
变量名 = {1,"abc",{},function() end}
注意:下标从1开始(java从0开始)
变量名 = {
字符串a = 1,
字符串b = "1234",
字符串c = function()
end,
字符串d = 123456
}
print(变量名["字符串a"])
print(变量名.字符串a)
table.insert(变量名,(可选)位置,值)
table.remove(变量名,位置)
说明:全局表是lua里一个特殊的table叫做_G
,这个表存储了所有的全局变量。
本地变量不会存入大_G表中。
Lua认为false和nil为假,true和非nil为真(包括0)。要于c语言做区分
操作符 | 描述 | 实例 |
---|---|---|
+ | 加法 | A + B 输出结果 30 |
- | 减法 | A - B 输出结果 -10 |
* | 乘法 | A * B 输出结果 200 |
/ | 除法 | B / A 输出结果 2 |
% | 取余 | B % A 输出结果 0 |
^ | 乘幂 | A^2 输出结果 100 |
- | 负号 | -A 输出结果 -10 |
// | 整除运算符(>=lua5.3) | 5//2 输出结果 2 |
操作符 | 描述 | 实例 |
---|---|---|
== | 等于,检测两个值是否相等,相等返回 true,否则返回 false | (A == B) 为 false。 |
~= | 不等于,检测两个值是否相等,不相等返回 true,否则返回 false | (A ~= B) 为 true。 |
> | 大于,如果左边的值大于右边的值,返回 true,否则返回 false | (A > B) 为 false。 |
< | 小于,如果左边的值大于右边的值,返回 false,否则返回 true | (A < B) 为 true。 |
>= | 大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false | (A >= B) 返回 false。 |
<= | 小于等于, 如果左边的值小于等于右边的值,返回 true,否则返回 false | (A <= B) 返回 true。 |
注意:lua中不等于为~=,java中不等于为!=
操作符 | 描述 | 实例 |
---|---|---|
and | 逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B。 | (A and B) 为 false。 |
or | 逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B。 | (A or B) 为 true。 |
not | 逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。 | not(A and B) 为 true。 |
注意:Lua中不支持三目运算符,但是可以使用and和or来模拟三目运算符(x>y) and x or y
操作符 | 描述 | 实例 |
---|---|---|
… | 连接两个字符串 | a…b ,其中 a 为 "Hello " , b 为 “World”, 输出结果为 “Hello World”。 |
# | 一元运算符,返回字符串或表的长度。 | #“Hello” 返回 5 |
从高到低的顺序:
^
not - (unary)
* / %
+ -
..
< > <= >= ~= ==
and
or
--[ 0 为 true ]
if(0)
then
print("0 为 true")
end
lua中使用 then … end表示一个代码块
Lua 语言提供了以下几种循环处理方式:
循环类型 | 描述 |
---|---|
while 循环 | 在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。 |
for 循环 | 重复执行指定语句,重复次数可在 for 语句中控制。 |
repeat…until | 重复执行循环,直到 指定的条件为真时为止 |
循环嵌套 | 可以在循环内嵌套一个或多个循环语句(while do … end;for … do … end;repeat … until;) |
判断条件为 true 时会重复执行循环体语句。
while(condition)
do
statements
end
for 循环语句可以重复执行指定语句,重复次数可在 for 语句中控制。
Lua 编程语言中 for语句有两大类::
for var=exp1,exp2,exp3 do
<执行体>
end
var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 “执行体”。exp3 是可选的,如果不指定,默认为1。
--打印数组a的所有值
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
i
是数组索引值,v
是对应索引的数组元素值。ipairs
是Lua提供的一个迭代器函数,用来迭代数组。
实例:
days = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
for i,v in ipairs(days) do print(v) end
repeat…until 循环语句不同于 for 和 while循环,for 和 while 循环的条件语句在当前循环执行开始时判断,而 repeat…until 循环的条件语句在当前循环结束后判断。(相当于java中的do while循环)
repeat
statements
until( condition )
数学库中提供了三个取整函数:floor、ceil和modf。
floor:向负无穷取整
ceil:向正无穷取整
modf:向零取整
dep:弧度转角度
abs:绝对值
cos、sin:三角函数
max:最大值
min:最小值
modf:把整数和小数分离,返回两个参数
random:随机数
pow:幂运算
sqrt:开方
时间:
Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
以上代码也可以直接写成一行:
mytable = setmetatable({},{})
以下为返回对象元表:
getmetatable(mytable) -- 这会返回 mymetatable
这是 metatable 最常用的键。
概念:当子表中 找不到某一个属性时,会到元表中的 __index指定的表去找索引
我们可以在使用 lua 命令进入交互模式查看:
meta = {
age = 17,
__tostring = function(t)
return "我的名字是" .. t.name
end,
__call = function( mytable,canshu1 )
print(mytable.name)
print(canshu1)
end,
-- __len = function(mytable)
-- return #mytable.name
-- end
}
meta.__index = meta
mytable = {
name = "qimeile"
}
setmetatable(mytable,meta)
print(mytable.age)
如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})
print(mytable.key1,mytable.key2)
实例输出结果为:
value1 metatablevalue
实例解析:
mytable 表赋值为 {key1 = “value1”}。
mytable 设置了元表,元方法为 __index。
在mytable表中查找 key1,如果找到,返回该元素,找不到则继续。
在mytable表中查找 key2,如果找到,返回 metatablevalue,找不到则继续。
判断元表有没有__index方法,如果__index方法是一个函数,则调用该函数。
元方法中查看是否传入 “key2” 键的参数(mytable.key2已设置),如果传入 “key2” 参数返回 “metatablevalue”,否则返回 mytable 对应的键值。
我们可以将以上代码简单写成:
mytable = setmetatable({key1 = “value1”}, { __index = { key2 = “metatablevalue” } })
print(mytable.key1,mytable.key2)
总结
Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:
- 1.在表中查找,如果找到,返回该元素,找不到则继续
- 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
- 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。
- 使用
rawget(表名,属性名)
函数:只会在自己身上查找这个属性变量,不会继续查找元表。
__newindex 元方法用来对表更新,__index则用来对表访问 。
当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到newindex所指的表中,不会修改自己
以下实例演示了 __newindex 元方法的应用:
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
以上实例执行输出结果为:
value1
nil 新值2
新值1 nil
以上实例中表设置了元方法 __newindex,在对新索引键(newkey)赋值时(mytable.newkey = “新值2”),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。
以下实例使用了 rawset 函数来更新表:
mytable = setmetatable({key1 = “value1”}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, “"”…value…“"”)
end
})
mytable.key1 = “new value”
mytable.key2 = 4
print(mytable.key1,mytable.key2)
以上实例执行输出结果为:
new value "4"
总结:
rawset(表名, 属性名, 值)
函数:修改自身,不会修改元表中__newindex索引指向的表。以下实例演示了两表相加操作:
– 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
– 自定义计算表中最大键值函数 table_maxn,即返回表最大键值
function table_maxn(t)
local mn = 0
for k, v in pairs(t) do
if mn < k then
mn = k
end
end
return mn
end– 两表相加操作
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table_maxn(newtable) do
table.insert(mytable, table_maxn(mytable)+1,newtable[i])
end
return mytable
end
})secondtable = {4,5,6}
mytable = mytable + secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
以上实例执行输出结果为:
1 1
2 2
3 3
4 4
5 5
6 6
__add 键包含在元表中,并进行相加操作。 表中对应的操作列表如下:(注意:是两个下划线)
模式 | 描述 |
---|---|
__add | 加,对应的运算符 ‘+’. |
__sub | 减,对应的运算符 ‘-’. |
__mul | 乘,对应的运算符 ‘*’. |
__div | 除,对应的运算符 ‘/’. |
__mod | 取余,对应的运算符 ‘%’. |
__unm | 取负,对应的运算符 ‘-’. |
__pow | 幂,对应的运算符 ‘^’. |
__concat | 拼接,对应的运算符 ‘…’. |
__eq | 等于,对应的运算符 ‘==’. |
__lt | 小于,对应的运算符 ‘<’. |
__le | 小于等于,对应的运算符 ‘<=’. |
__idiv | 向下取整除法,对应的运算符 ‘//’. |
__len | 取长度,对应的运算符 ‘#’. |
注意:如果要用条件运算符比较两个对象,这两个对象的元表一定要一致,才能准确调用方法
__call 元方法在 Lua 调用一个值时调用。以下实例演示了计算表中元素的和:
meta = {
__tostring = function(t)
return "我的名字是" .. t.name
end,
__call = function( mytable,canshu1 )
print(mytable.name)
print(canshu1)
end
}
mytable = {
name = "qimeile"
}
setmetatable(mytable,meta)
mytable(12)
以上实例执行输出结果为:
qimeile
12
__tostring 元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容:
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "表所有元素的和为 " .. sum
end
})
print(mytable)
以上实例执行输出结果为:
表所有元素的和为 60
meta = {
__tostring = function(t)
return "我的名字是" .. t.name
end }
mytable = {
name = "qimeile"
}
setmetatable(mytable,meta)
print(mytable)
以上实例执行输出结果为:
我的名字是qimeile
表是一切复杂数据的基础:数组、二维数组、字典、类等等
#
:长度获取-- 将表当作一个类来使用
Student = {
name = "qimeile",
sex = "男",
age = 25,
//内部定义类的函数
speak = function()
-- 想要在表内部函数中 调用表本身的属性或者方法
--一定要指定是谁的 所以要使用 表名.属性 或 表名.方法
print("你好!我叫" .. Student.name)
end
}
//外部定义类的函数
function Student:Up()
print(self.name)
end
insert:插入
remove:默认移除表中最后一个索引的内容,第二个参数可以指定移除的索引
sort:排序,默认升序排序,第二个参数可以传入排序规则
t1 = {3,1,6,4,5}
-- 降序规则
table.sort(t1,function(a,b)
if(a>b) then
return true
end
end)
concat:拼接,用于拼接表中的string和number元素,返回值是string
关键字:require(“脚本路径”)
如果是require加载执行的脚本,再次require加载则不会被执行
Package.loaded[“脚本名”]:通过返回值,判断脚本是否被执行
协程的创建:
coroutine.create()
:(常用方式)协程的本质是一个线程对象
coroutine.resume()
coroutine.wrap()
:返回的协程是一个函数类型
coroutine.yield(返回值)
:协程的挂起,可以有返回值
coroutine.resume()
执行的默认有一个boolean类型的返回值表示协程是否执行成功,用户自定义的返回值从第二个开始coroutine.wrap()
方式创建的则没有默认的boolean类型返回值,用户自定义的返回值从第一个开始coroutine.status(协程对象)
:协程的状态
coroutine.running()
:返回协程编号面向对象的三大特性:封装、继承、多态
print("***********封装**********")
Object = {}
Object.id = math.random(0,12)
function Object:toString()
print(self.id)
end
function Object:new()
local obj = {}
self.__index = self
setmetatable(obj,self)
return obj
end
local a = Object:new()
print("a:" .. a.id)
实现方法:利用_G来根据字符串创建一个新的表(类),元表和__index相关知识点
print("***********继承**********")
function Object:extends(className)
_G[className] = {}
local obj = _G[className]
self.__index = self
-- 子类调用父类的方法
obj.base = self
setmetatable(obj,self)
end
a:extends("a2")
print("a2:" .. a2.id)
概念:相同方法名 子类有不同的处理逻辑。
实现方法:直接重写这个方法
如果保留父类逻辑:加入自定义 base属性,extends方法中赋值
print("***********多态**********")
Object:extends("GameObject")
GameObject.posX = 0
GameObject.posY = 0
function GameObject:Move()
self.posX = self.posX + 1
self.posY =self.posY + 1
print(self.posX)
print(self.posY)
end
GameObject:extends("Player")
function Player:Move()
-- 不要使用self.base:Move()
self.base.Move(self)
end
local p1 = Player:new()
p1:Move()
p1:Move()
local p2 = Player:new()
p2:Move()
**注意:**通过base调用父类方法时,一定记住不要用冒号,通过.
然后自己传入第一个参数 进入父类内部