目录
- 1. 安装
- 2. 使用
- 3. 数据类型
- 4. 条件判断
- 5. for循环
- 6. 函数
- 7. 全局变量和局部变量
- 8. 字符串操作
- 9. 迭代器函数-pairs ipairs
- 10. table的连接、插入和移除
- 11. 引入文件
- 12. 元表
- 13. 协同程序
- 14. 文件读写
- 15. 垃圾回收
- 16. 类
1. 安装
- 下载:https://github.com/rjpcomputing/luaforwindows/releases
- 在vscode中使用lua编译:
- 2. 使用
- lua和python一样,变量都不需要声明,直接赋值就可以了,但是删除的时候有点区别,lua将对象置为 nil达到删除变量的目的。
- lua不是以缩进区分程序块的,lua以end结束一个程序块。
- lua里只有false和nil是假,其他一概为真。
- lua里只有浮点数,没有整数类型,python里区分int和float。
- lua里多行字符串使用[[和]],lua里字符串和数字会自动转换。
- lua里使用#操作符取长度,lua中字符串拼接使用 ..
- lua里的table和python里的dict比较像,使用方法类似,需要注意的是#取table长度的时候,取到的是最大索引。另外需要注意的一个重要环节是,lua中默认以1为索引的开始,这个区别非常重要,lua里很多默认函数的实现也依赖于这个默认约定,所以学lua的时候最好注意索引的起点。
- 不等号:~=,其他如 and not or 和py一样
- ^ 求幂
3. 数据类型
- type(数据对象) 函数可判断数据的数据类型
- dict 字典
-- 定义list, 以及键值对
table = { key = "value" }
-- 调用
print(table["key"], table.key)
-- 数组
table = { "a", "b", "c", "d", "e" }
-- 注意,索引从1开始,且[1]不等于["1"]
print(table[1])
-- 删除键值对。注意:即便这样删除,后面的数据也不会前移。
table[1] = nil
- 字符串
+ 仅仅对数值相加有效,字符串拼接使用 ..
#str 取得字符串长度 - 多变量同时赋值
a, b = 1, 2
4. 条件判断
if true then
print("真")
elseif false then
print("假")
else
print("其他")
end
5. for循环
-- pairs 获得表的键值对 key,val 分别对应着键和值
-- for 变量列表 in 迭代函数 状态变量 控制变量 do
for key, val in pairs(table) do
print(key .. " " .. val)
end
-- 变量名及其初始值,最大值,步长(可省略)
for i = 1, 10, 1 do
print(i)
end
-- 等同于 do while,但仅在until为 假 时继续重复执行(until 直到…为止)
repeat
..
until true
6. 函数
-- 一般函数 (可返回多变量)
function fact(m)
return m
end
-- 函数作为参数的函数
function printFun(data, fun)
print(fun(data))
end
-- 匿名函数
printFun = function (m)
print(m)
end
-- 可变参数
function printFun(...)
local arg = { ... }
for index, value in pairs(arg) do
print(index, value)
end
end
7. 全局变量和局部变量
- 局部变量的声明:
local data = "value"
- 即便是在函数内声明全局变量,仍旧可在外部访问
- 只要声明局部变量,再次在局部调用时无需重复声明
8. 字符串操作
- string 类静态方法
方法 | 描述 |
upper(str) | 全部大写 |
lower(str) | 全部小写 |
gsub(str, str1, str2, number) | 将str中的str1替换为str2,number为限制替换次数(若传入) |
find(str, str1, number) | 查找str中str1第一次出现的位置,number为开始索引 |
reverse(str) | 翻转字符串 |
format(“%s %.3f %03d”, str, 1.23, 1) | 字符串拼接(同C) |
char(number…) | 将数值们变成ascil字符串 |
byte(str, number) | 将number位的字符变成ascil码 |
gmatch(str, str1) | 返回str中符合正则表达式str1的函数,可用for遍历结果 |
for word in string.gmatch("Hello world!", "l.") do
print(word)
end
9. 迭代器函数-pairs ipairs
- pairs 遍历所有键值对。
- ipairs 仅仅遍历数键,从1开始,一旦缺失立刻终止迭代。
- 自定义迭代函数
-- 状态变量:最值 控制变量:每轮改变的值。当返回为nil时迭代立刻结束
function square(state, control)
if control >= state then
return nil
else
control = control + 1
return control, control ^ 2
end
end
for index, value in square, 9, 0 do
print(index, value)
end
10. table的连接、插入和移除
- table类
静态方法 | 描述 |
concat(table, str) | 返回表的数据集,str为拼接插入值 |
insert(table, index, value) | 插入数据,注意从1开始 |
remove(table, index) | 删除数据,无位置参数时默认最后一位 |
sort(mytable, function) | 从小到大排序,传入参数时 |
table.sort(mytable, function(a, b)
return a > b
end)
11. 引入文件
- require(“module”) 引入lua模块
12. 元表
- 元表可扩展普通表,从而实现诸如表相加的各种功能
-
setmetatable(mytable,mymetatable)
将 mymetatable 设为 mytable 的元表 - 元表元素:__index
- 当 __index 为函数
function(tab, key)
时,访问表不存在的元素时会调用该函数,得到的值为函数返回值 - 当 __index 为另一个表 时,访问普通表不存在的元素时会返回 __index 表中的该键元素
- 添加新键值对时创建:__newindex
- 当 __newindex 为函数
function(tab, key, value)
时,添加新键值对时调用该函数并不再添加,需使用函数rawset(tab, key, value)
手动添加 - 当 __newindex 为另一个表 时,添加新键值对时仅添加到 __newindex 表中
- 元表元素:__add
当 __add 为函数function(tab, meta)
时,加法操作符会调用该函数,meta为新函数,且该行为存在返回值。 - 调用:__call
- 当 __call 为函数
function(tab, arg)
时,表可像函数一样调用,参数为arg - 当 __call 为函数
function(tab, ...)
时,表可接受多个入参
13. 协同程序
- coroutine 类
静态函数 | 描述 |
create(function) | 创建协同 |
resume(coroutine, arg…) | 运行、继续协同 |
wrap(function) | 创建一个可像函数一样调用的协同函数 |
yield() | 将协程挂起 |
status() | 获得协程状态 |
-- 运行方式1
co = coroutine.create(function(a, b)
print(a + b)
end)
coroutine.resume(co, 20, 30)
-- 运行方式2
co = coroutine.wrap(function(a, b)
print(a + b)
coroutine.yield()
print(a - b)
end)
co(20, 30)
- coroutine 类取得返回值
第一个返回值是启动结果,之后的是返回值
co = coroutine.create(function(a, b)
coroutine.yield()
return 50
end)
-- 此时仍未获得返回值
data1, data2 = coroutine.resume(co, 20, 30)
print(data1, data2)
-- 此时获得返回值
data1, data2 = coroutine.resume(co)
print(data1, data2)
- 函数外挂起
function foo()
return coroutine.yield(1)
end
co = coroutine.create(function(a)
-- 将挂起并返回
foo()
-- 结束并返回
return 2
end)
print(coroutine.resume(co))
print(coroutine.resume(co))
14. 文件读写
- 简单模式
-- 读文件
file = io.open("data.txt", "r")
io.input(file)
print(io.read())
io.close(file)
-- 写文件。a为追加,w为重置,在后面加上+表示可读可写
file = io.open("data.txt", "a")
io.output(file)
io.write("123")
io.close(file)
15. 垃圾回收
- collectgarbage 类用于垃圾回收,传入的字符串决定执行的行为
传入字符串 | 描述 |
count | 占用KB |
stop | 停止回收 |
restart | 重启 |
collect | 执行垃圾回收 |
16. 类
- 类的定义类似于js
- 对于类内函数取得类本体,可用self入参,调用时传入类。
或用冒号自动入参self。
-- 常规定义
class = {
name = "liluo",
age = 21,
eat = function(self)
print(self.name .. " eat")
end
}
class.eat(class)
-- 冒号定义
function class:say()
print(self.name .. " say")
end
class:eat()
class:say()
- 构造函数
class = {
name = "liluo",
age = 21
}
function class:new()
local t = {}
setmetatable(t, {
-- 调用一个属性时,如果t不存在,则到基类中查找
__index = self
})
return t
end
c = class:new()
-- 可得到类名
print(c.name)
print(class.name)
-- 即便修改也不会影响原类,因为其本质是在类c中新建加一个变量
c.name = 123
print(c.name)
print(class.name)
构造函数可设基础入参为表
Person = {
name = "liluo",
age = 21
}
function Person:new(o)
local t = o or {}
setmetatable(t, {
-- 调用一个属性时,如果t不存在,则到基类中查找
__index = self
})
return t
end
Student = Person:new({
grade = 3
})
-- stu 的基类是Student,Student的基类是Person
stu = Student:new()
print(stu.name)
print(stu.grade)
继承
require("Class")
--类的继承
SubClass = {z = 0}
--声明新的属性Z
--两步完成类Class的继承
setmetatable(SubClass, Class)
--设置类型是class
SubClass.__index = SubClass --设置表的索引为自身
--构造方法,习惯性命名new()
function SubClass:new(x, y, z)
local t = {} --初始化对象自身
t = Class:new(x, y) --将对象自身设定为父类,相当于C#里的base
setmetatable(t, SubClass) --将对象自身元表设定为SubClass
t.z = z --新属性赋值
return t
end
--定义一个新的方法
function SubClass:go()
self.x = self.x + 10
end
--重定义父类的方法,相当于override
function SubClass:test()
print(self.x, self.y, self.z)
// base
Class.test(self)
end
重写
require("Class")
require("SubClass")
local a = Class:new() -- 首先实例化父类,并调用父类方法
a:plus()
a:test()
a=SubClass:new() -- 然后实例化子类对象
a:plus() --重写
a:go() --新增
a:test() --重写