目录

  • 1. 安装
  • 2. 使用
  • 3. 数据类型
  • 4. 条件判断
  • 5. for循环
  • 6. 函数
  • 7. 全局变量和局部变量
  • 8. 字符串操作
  • 9. 迭代器函数-pairs ipairs
  • 10. table的连接、插入和移除
  • 11. 引入文件
  • 12. 元表
  • 13. 协同程序
  • 14. 文件读写
  • 15. 垃圾回收
  • 16. 类


1. 安装
  1. 下载:https://github.com/rjpcomputing/luaforwindows/releases
  2. 在vscode中使用lua编译:
  3. 2. 使用
  4. lua和python一样,变量都不需要声明,直接赋值就可以了,但是删除的时候有点区别,lua将对象置为 nil达到删除变量的目的。
  5. lua不是以缩进区分程序块的,lua以end结束一个程序块。
  6. lua里只有false和nil是假,其他一概为真。
  7. lua里只有浮点数,没有整数类型,python里区分int和float。
  8. lua里多行字符串使用[[和]],lua里字符串和数字会自动转换。
  9. lua里使用#操作符取长度,lua中字符串拼接使用 ..
  10. lua里的table和python里的dict比较像,使用方法类似,需要注意的是#取table长度的时候,取到的是最大索引。另外需要注意的一个重要环节是,lua中默认以1为索引的开始,这个区别非常重要,lua里很多默认函数的实现也依赖于这个默认约定,所以学lua的时候最好注意索引的起点。
  11. 不等号:~=,其他如 and not or 和py一样
  12. ^ 求幂
3. 数据类型
  1. type(数据对象) 函数可判断数据的数据类型
  2. 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
  1. 字符串
    + 仅仅对数值相加有效,字符串拼接使用 ..
    #str 取得字符串长度
  2. 多变量同时赋值 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. 全局变量和局部变量
  1. 局部变量的声明:local data = "value"
  2. 即便是在函数内声明全局变量,仍旧可在外部访问
  3. 只要声明局部变量,再次在局部调用时无需重复声明
8. 字符串操作
  1. 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
  1. pairs 遍历所有键值对。
  2. ipairs 仅仅遍历数键,从1开始,一旦缺失立刻终止迭代。
  3. 自定义迭代函数
-- 状态变量:最值 控制变量:每轮改变的值。当返回为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的连接、插入和移除
  1. 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. 引入文件
  1. require(“module”) 引入lua模块
12. 元表
  1. 元表可扩展普通表,从而实现诸如表相加的各种功能
  2. setmetatable(mytable,mymetatable) 将 mymetatable 设为 mytable 的元表
  3. 元表元素:__index
  • 当 __index 为函数 function(tab, key) 时,访问表不存在的元素时会调用该函数,得到的值为函数返回值
  • 当 __index 为另一个表 时,访问普通表不存在的元素时会返回 __index 表中的该键元素
  1. 添加新键值对时创建:__newindex
  • 当 __newindex 为函数 function(tab, key, value) 时,添加新键值对时调用该函数并不再添加,需使用函数 rawset(tab, key, value) 手动添加
  • 当 __newindex 为另一个表 时,添加新键值对时仅添加到 __newindex 表中
  1. 元表元素:__add
    当 __add 为函数 function(tab, meta) 时,加法操作符会调用该函数,meta为新函数,且该行为存在返回值。
  2. 调用:__call
  • 当 __call 为函数 function(tab, arg) 时,表可像函数一样调用,参数为arg
  • 当 __call 为函数 function(tab, ...) 时,表可接受多个入参
13. 协同程序
  1. 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)
  1. 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)
  1. 函数外挂起
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. 文件读写
  1. 简单模式
-- 读文件
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. 垃圾回收
  1. collectgarbage 类用于垃圾回收,传入的字符串决定执行的行为

传入字符串

描述

count

占用KB

stop

停止回收

restart

重启

collect

执行垃圾回收

16. 类
  1. 类的定义类似于js
  2. 对于类内函数取得类本体,可用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()
  1. 构造函数
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()  --重写