Lua语言
1. 数据类型
数据类型 | 描述 |
---|---|
nil | 只有值为 nil 属于该类,表示一个无效值(在条件表达式中相当于 false) |
boolean | false or true |
number | 双精度类型的实浮点数 |
string | 双引号或单引号表示 |
function | 由 C 或 Lua 编写的函数 |
userdata | 表示任意存储在变量中的 C 数据结构 |
thread | 表示执行的独立线路,用于执行协同程序 |
table | Lua 中的表其实是一个”关联数据”, 数组的索引可以是数字或字符串 |
- nil
- boolena
- number
- string
- 可以使用两个方括号”[[]]” 来表示一块字符串
- 字符串链接使用两个点好 ..
- 计算字符串的长度使用 #
html = [[
<html>
<head></head>
<body>
<a href="http://domob.cn">Domob</a>
</body>
</html>
]]
print(html)
len = "pemako.cn"
print(#len)
- function
-- function_test.lua
function factoriall(n)
if n == 0 then
return 1
else
return n * factoriall(n - 1)
end
end
print(factoriall(5)) – 120
- table
- 不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始
local tb1 = {"apple", "pear", "orange"}
for k, v in pairs(tb1) do
print(k … " : " … v)
end
– 1 : apple
– 2 : pear
– 3 : orange
-
userdata
<p>userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用</p>
-
thread
<p>在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。
线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停
2. Lua 变量
-
全局变量
<p>Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显示声明为局部变量</p>
-
局部变量
<p>局部变量的作用于为从生命位置开始到所在语句块结束</p> <p>变量的默认值均为 <code class="highlighter-rouge">nil</code></p>
-
表中的域
-
赋值语句
<ul> <li>Lua 可以对多个变量同时赋值,变量列表和值列表的各个元素使用逗号分开,复制语句右边的值会依次赋值给左边的变量</li> <li><code class="highlighter-rouge">x, y = y, x</code> – 交换 x y 的值</li> <li>当变量的个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> a. 变量的个数 > 值的个数 按变量个数补足 nil
b. 变量的格式 < 值的格式 多余的值会被忽略
<ul>
<li>多值赋值经常用来交换变量,或将函数调用返回给变量</li>
</ul>
索引
<ul>
<li><code class="highlighter-rouge">t[i]</code></li>
<li><code class="highlighter-rouge">t.i</code> 当索引为字符串类型时的一种简化写法</li>
</ul>
3. Lua 循环
while
for
repeat...until
重复执行循环,知道指定的条件为真时为止- 循环嵌套 可以在循环内嵌套一个或多个循环语句(while for do..while)
4. Lua 流程控制
if 表达式
then
-- 在表达式为 true 时执行的语句
end
5. Lua 函数
optional_function_scope function function_name( argument1, argument2..., argumentn)
function_body
return result_params_comma_separated
end
-- optional_function_scope 默认不写为全局函数 加上 local 为局部函数
-- Lua 可以返回多个返回值,每个值已逗号隔开
- 可变参数
可变参数使用三个点(…) 便是函数有可变参数。Lua 将函数的参数放在一个叫 arg 的表中,#arg
便是传入参数的个数
function average(...)
result = 0
local arg = {...}
for i,v in ipairs(arg) do
result = result + v
end
<span class="nb">print</span><span class="p">(</span><span class="s2">"总共传入"</span><span class="o">..</span> <span class="o">#</span><span class="n">arg</span> <span class="o">..</span> <span class="s2">"个数"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">result</span><span class="o">/#</span><span class="n">arg</span>
end
print("平均值为:", average(1,2,3,4))
– 总共传入4个数
– 平均值为: 2.5
6. Lua 运算符
- 算术运算符:
+
-
*
/
%
^
- 关系运算符:
==
~=(不等于)
>
<
>=
<=
- 逻辑运算符:
and
or
not
- 其它运算符:
..(链接两个字符串)
#(返回字符串或表的程度)
7. Lua 字符串
- 单引号字符串
- 双引号字符串
- [[和]]间的字符串
- 字符串操作
- string.upper(argument)
- string.lower(argument)
- string.gsub(mainString, findString, replaceString, num)
- string.strfind(str, substr,[init,[end]])
- string.reverse(arg)
- string.format(…)
- string.len(arg)
- string.rep(string, n)
- string.char(arg) 和 string.byte(arg[,int])
string.gsub("aaaaa", "a", "z", 3) -- 把字符串aaaaa 中的 a 替换为z 天幻3次
string.gsub("aaaaa", "a", "z") -- 把字符串aaaaa 中的 a 替换为z 全部替换
– 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引)
string.find("Hello Lua user", "Lua", 1) – 7 9 (分别为开始位置和结束位置的索引)
string.format("the value is:%d", 4) – the value is:4
string.rep("abcd", 2) – abcdabcd
– char 将整数数字转换成字符并连接,byte 转换字符为整数值(可以指定某一个字符,默认第一个字符)
string.char(97,98,99,100) – abcd
string.byte("ABCD", 4) – 68
string.byte("ABCD") – 65
8. Lua 数组
Lua数组可以为一维数组或多维数组,数组的索引值可以使用整数表示,数组的大小不固定。
-- 一维数组
array = {"Lua", "Tutorial"}
for i=1, #array do
print(array[i])
end
–Lua
–Tutorial
– 多维数组
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
– 1 2 3 2 4 6 3 6 9
9. Lua 迭代器
-
无状态的迭代器
<p>无状态迭代器的典型的简单的例子是 <code class="highlighter-rouge">ipairs</code>, 他遍历数组的每一个元素</p>
t = {"Lua","Python", "PHP", "Java"}
for k, v in pairs(t) do
print(k, v)
end
- 多状态的迭代器
array = {"Lua", "Tutorial"}
function elementIterator (collection)
local index = 0
local count = #collection
– 闭包函数
return function ()
index = index + 1
if index <= count
then
– 返回迭代器的当前元素
return collection[index]
end
end
end
for element in elementIterator(array)
do
print(element)
end
– Lua
– Tutorial
10. Lua table
table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数字、字典等。
Lua table 使用关联型数组,你可以用任意类型的值来作数组的索引,但这个值不能是 nil。
Lua table 是不固定大小的,你可以根据自己需要进行扩容。
Lua也是通过table来解决模块(module)、包(package)和对象(Object)的。 例如string.format表示使用”format”来索引table string。
-
Table 操作
<ul> <li>table.concat(table[,sep[,start[,end]]])</li> </ul>
-- concat 链接两个 table 和 PHP 中的 implode 函数很类似
-- table.concat() 函数列出参数中指定 table 的数组部分从 start 位置到 end 位置的所有元素,元素间已指定的分隔符(sep)隔开
> language = {"Lua", "Python", "PHP", "Java"}
> print(table.concat(language))
LuaPythonPHPJava
> print(table.concat(language, ','))
Lua,Python,PHP,Java
> print(table.concat(language, ',', 1, 2))
Lua,Python
- table.insert(table[,[pos,]value])
-- 在 table 数组部分指定位置(pos)插入值为 value 的元素,默认从末尾插入
> language = {"Lua", "Python", "PHP", "Java"}
> table.insert(language, "Golang")
> print(language[5])
Golang
> table.remove(language)
> print(language[5])
nil
> print(language[1])
Lua
> table.remove(language,1)
> print(language[1])
Python
- table.remove(table[,pos])
- table.sort(table[,comp])
11. Lua 模块与包
Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua,文件代码格式如下:
- 定义模块
-- 文件名 utils.lua
-- 定义一个名为 utils 的模块
utils = {}
– 定义一个常量
utils.constant = "这是一个常量"
– 定义一个函数
function utils.func1()
io.write("这是一个共有函数!n")
end
local function func2()
print("这是一个私有函数!")
end
function utils.fun3()
func2()
end
return utils
- 加载模块 require
require("utils") -- 或者使用 require "utils"
-- 别名导入 local u = require("utils")
print(utils.constant)
-- print(u.constant) 使用别名
utils.fun3()
12. Lua 元表(Metatable)
Lua table 无法对两个 table 进行操作,因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。
对指定的表设置元表
setmetatable(table, metatable):
对指定的 table 设置元表(metatable),如果元表中存在__metatable
值,setmetatable
会失败-
getmetatable(table):
返回对象的元表(metatable
) __index
元方法
当你通过健来访问 table 的时候,如果这个健没有值,那么 Lua 就会寻找该 table 的 metatable(假定有 metatable)中的__index
健。如果__index
包含一个表格,Lua 会在表格中查找相应的健。
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
> other = { foo = 3}
> t = setmetatable({}, {__index = other})
> t.foo
3
> t.bar
nil
如果 __index
包含一个函数的话,Lua 就会调用那个函数,table 和健会作为参数传递给函数。__index
元房费查看表中元素是否存在,如果不存在,返回结果为 nil, 如果存在则由__index
返回结果。
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metablevalue"
else
return nil
end
end
})
print(mytable.key1, mytable.key2)
– value1 metablevalue
– 上面的代码可以简写为
mytable = setmetatable({key1="value1", {__index = {key2 = "metatablevalue"}} })
Lua 查找一个元素时的规则
- 在表中查找,如果找到,返回该元素,找不到则继续
- 判断该表是否有元表,如果没有元表,返回 nil, 有元表则继续
- 判断元表有没有 __index 方法,如果__index 方法为 nil,则返回 nil; 如果 __index 方法是一个表,则重复i, ii, iii; 如果 __index 方法是一个函数,则返回该函数的返回值
__newindex
元方法
__newindex
元方法用来对表更新,__index
则用来对表访问。当你给表的一个缺少的索引赋值,解释器就会查找__newindex
元方法;如果存在则调用这个函数而不进行赋值操作。
mymetatable = {}
mytable = setmetatable({key1 = "vlaue1"}, { __newindex = mymetatable })
print(mytable.key1) -- value1
mytable.newkey = "新值2"
print(mytable.newkey, mymetatable.newkey) -- nil 新值2
mytable.key1 = "新值1"
print(mytable.key1, mymetatable.key1) -- 新值1 nil
以上实例中表设置了元方法 __newindex,在对新索引(newkey)赋值时(mytable.newkey = “新值2”),会调用元方法,而不进行赋值。而如果对已存在的索引健(key1),则会进行赋值,而不调用元方法 __newindex。
__add
方法
进行两个表相加操作。
-- 计算表中最大值,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<span class