目 录CONTENT

文章目录
Lua

Lua语法

Administrator
2025-05-01 / 0 评论 / 0 点赞 / 21 阅读 / 0 字

lua 下载

http://www.lua.org/

一、第一个 lua 程序 hello world

#!/usr/local/bin/lua print("helloWorld");

lua test.lua

二、注释

单行注释: -- 注释

多行注释:

--[[

 注释内容

--]]

三、标识符

不允许使用特殊字符(@ $ % 等),只允许字母、数字、下划线,区分大小写

四、关键字

一般9约定以下划线开头连接一串大写字母的名字(_VERSION)被保留用于 Lua 内部全局变

五、全局变量

#!/usr/local/bin/lua

print(b) -- 访问一个未定义的全局变量合法,值为 nil

c = 10 print(c)

c = nil -- 若要删除一个变量,将其赋值为 nil

六、Lua 数据类型

nil :无效值 boolean:包含 true / false number:双精度double类型的实浮点数 string:一对 单引号或双引号表示的字符窜 function:函数 userdata:任意存储在变量中的C数据结构 thread:执行的独立线程 table:关联数组 type() :获取某个变量的数据类型

七、Lua 数据类型 - String

#!/usr/local/bin/lua

string1 = "helloworld" -- 字符窜

string2 = [[ i love china i love asia ]] -- 表示一块字符窜

-- print(string1 + 2) -- 字符串与数字相加时,Lua会尝试这个数据字符串转成数字,若失败会报错

string3 = string1..string2 -- 通过 .. 连接字符串

print(#string3) -- #,放在字符窜前,用于计算字符串长度

八、Lua 数据类型 - table

#!/usr/local/bin/lua

-- table 可看做是关联数组,索引可以是数字或字符串

local table1 = {} -- 创建一个空table

local table2 = {"apple", "pear"} -- 创建与初始化一个table

table1["love"] = 1 -- 直接赋值

for k, v in pairs(table2) do print(k, v) end -- 循环table

-- Lua中初始索引为1

九、Lua 数据类型 - function

#!/usr/local/bin/lua

-- 重点1:函数可以存在变量中

function test(n) if n == 1 then return 1 else return 0 end end

print(test(1)) -- 调用函数

test2 = test -- 将函数test存放在test2中

print(test2(1)) -- 相当于调用test函数

-- 重点2:function 可以以匿名函数的方式通过参数传递

function test3(n, func) func(n) end

test3(1, function(x) -- 匿名函数的使用 return x end

十二、Lua 循环

#!/usr/local/bin/lua

-- for 循环 -- var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 "执行体"。exp3 是可选的,如果不指定,默认为1

-- for var = exp1, exp2, exp3 do -- <执行体> -- end

for i = 1, 100, 10 do print(i) end

-- while 循环

x = 0 while (x < 10) do x = x + 5 print(x) end

-- repeat..until 循环

a = 0 repeat print(a) a = a + 5 until(a > 9)

需要注意的是 Lua 中 0 为 true

十三、Lua 函数

1)通过 local 关键字指定为局部函数,否则默认是全局函数

2)函数可返回多个值 return a, b

3)可变参数:

#!/usr/local/bin/lua

-- 计算平均值的函数 function average(...) -- 通过 ... 声明函数的参数可变,可传入不确定的参数个数。 result = 0

local arg = {...}                               -- lua将参数放在arg表中
 
for i, v in ipairs(arg) do
    result = result + v
end
 
return result / #arg

end

print(average(1, 2, 3, 4, 5))

十四、运算符

1)不等于 ~=,^ 幂运算,如 a = 10 , a ^ 2 = 100

2)支持 and or not 判断,如 if (a and b)

3)连接两个字符串 .. ,如 a .. b

4)获取字符串或table的长度,如 # "Hello" = 5

十五、迭代器

#!/usr/local/bin/lua

-- 重点1:无状态迭代器,避免创建闭包花费的额外代价

function square(max, current) if current < max then current = current + 1 return current, current * current end end

for i, n in square, 3, 0 -- 调用迭代器 do print(i, n) end

-- 重点2:多状态迭代器

array = {"Lua", "Php"}

function iter(collection) local index = 0 local count = #collection

return function ()                                        -- 闭包函数 
    index = index + 1
    if index <= count then
            return collection[index]                  -- 返回迭代器当前元素
    end
end

end

for el in iter(array) do print(el) end

十六、Lua 模块与包

1)基本使用

定义一个模块 module.lua:

#!/usr/local/bin/lua

module = {} -- Lua 的模块是由变量、函数等元素组成的表

module.constant = "这是一个常量" -- Lua 定义包中一个常量

function module.func1() -- 模块外可访问的函数 print("这是一个公有函数") end

local function func2() -- 私有函数,只能本程序内部使用 print("这是一个私有函数") end

function module.func3() -- 让私有函数在外部可以访问 func2() end

return module -- 返回这个模块

定义一个调用模块的 lua 文件 useModule.lua :

#!/usr/local/bin/lua

local m = require("module") -- 引入模块

print(m.constant) -- 获取模块的值

m.func1()

执行 lua useModule.lua 可见 module 模块的值被引入

2)加载机制

require 用于搜索lua文件的路径存放在 package.path 这个全局变量中。Lua 启动后,会以环境变量 LUA_PATH 的值初始化这个环境变量。如果没有找不到该环境变量,使用编译时的默认路径初始化。

如果找到目标文件,调用 package.loadfile 加载模块,否则就找 C 程序库,从 package.cpath 获取搜索文件路径,搜索类似 .so 或 .dll 文件,找到通过 package.loadlib 加载

3)C包

Lua 与 C 可以很好地结合,可使用 C 为 Lua 写包。 local path = "/usr/local/lua/lib/libluasocket.so"

-- loadlib 函数提供动态链接功能,第一个参数是库的绝对路径,第二个参数是库中的初始化函数

local f = assert(loadlib(path, "luaopen_socket"))

f() -- 打开 C 包的库

十七、Lua 元表的使用

#!/usr/local/bin/lua

-- 重点1:创建元表

mytable = {} mymetatable = {} setmetatable(mytable, mymetatable) -- 把mymetatable设置为mytale的元表 getmetatable(mytable) -- 返回mymetatable

-- 或者直接写成一行创建元表 mytable = setmetatable({}, {})

-- 重点2:__index 元方法

other = { foo = 3 }

table = setmetatable({}, { __index = other })

print(table.foo) -- 通过键访问表时,如果键没有值,寻找元表对应的 __index 方法获取

table2 = setmetatable({ foo = 4 }, { __index = other })

print(table.foo) -- 返回3而不返回4,说明 __index中若有访问的键对应的值,优先级要高于表中的键值

table3 = setmetatable({}, { __index = function(table3, key) if key == 'key2' then return "ok" else return nil end end })

print(table3.key2) -- 演示 __ index 中使用函数返回

2)__newindex 元方法

#!/usr/local/bin/lua

-- __newindex 元方法

emptyTable = {}

table = setmetatable({key1 = "a"}, {__newindex = emptyTable})

print(table.key1) -- 如果键值存在直接返回

table.key2 = "b" -- 键值不存在则调用元表__newindex方法,将key2的属性赋值给 emptyTable

print(table.key2) -- nil print(emptyTable.key2) -- "b"

3)为表添加运算符

#!/usr/local/bin/lua

-- 该函数求出table中最大的键

function maxTableKey(table) local max = 0 for k, v in pairs(table) do if max < k then max = k end end return max end

-- 两表相加

mytable = setmetatable({1, 2, 3}, {__add = function (mytable, newtable) for i = 1, maxTableKey(newtable) do table.insert(mytable, maxTableKey(mytable) + 1, newtable[i]); -- 插入newtable的元素到mytable表中 end return mytable -- 返回插入后的表 end })

testtable = {4, 5, 6}

mytable = mytable + testtable -- 自动调用元表的 __add 方法

for k, v in ipairs(mytable) do print(v) end

4)__call 元方法

#!/usr/local/bin/lua

table = setmetatable({1, 2, 3}, {__call = function (table, n) print("call me "..n) end })

print(table(100)) -- 当元表当做函数被使用时,调用__call方法

5)__tostring 元方法

#!/usr/local/bin/lua

table = setmetatable({}, { __tostring = function () return "i am tostringing" end })

print(table) -- 打印一个table变量时会调用__tostring元方法

十八、Lua 协程

Lua 协程与线程类似,拥有独立的堆栈、独立的局部变量、独立的指令指针

一个具有多线程的程序可以运行几个线程,而协程需要彼此协作运行。在任一指定时刻,只有一个协同程序在运行,且这个正运行的协程只有在明确被挂起的时候才被挂起。

coroutine.create() 创建 coroutine , 返回 coroutine,参数是一个函数 coroutine.resume() 重启 coroutine,和 create 配合使用 coroutine.yield() 挂起 coroutine coroutine.status() 查看 coroutine 状态:dead \ suspend \ running coroutine.warp() 作用与 create 相同,调用返回的函数就进入 coroutine

coroutine.running() 返回正在运行的协程与布尔值,true代表当前是主协程

#!/usr/local/bin/lua

co = coroutine.create(function(i) print(i) end )

coroutine.resume(co, 1) -- 输出1

print(coroutine.status(co)) -- 输出dead

#!/usr/local/bin/lua

co = coroutine.wrap(function(i) print(i) end )

co(1) -- 输出1

#!/usr/local/bin/lua

co = coroutine.create(function() -- create 创建一个 coroutine for i = 1, 10 do print(i) if i == 3 then print(coroutine.status(co)) -- 查看coroutine状态 print(coroutine.running()) -- 查看正在运行的coroutine end

 coroutine.yield()                              -- 挂起coroutine
 end

end )

coroutine.resume(co) -- 重启coroutine , 输出1 coroutine.resume(co) -- 重启被挂起的coroutine,输出2 coroutine.resume(co) -- 功能同上,输出3

print(coroutine.status(co)) print(coroutine.running()) -- true 代表是主协程

-- 最终输出:

1 2 3 running thread: 0x2106bb8 false suspended thread: 0x2100018 true

#!/usr/local/bin/lua

function foo(a) print("foo_out", a) return coroutine.yield(2*a) -- yield的参数将返回给resume end

co = coroutine.create(function(a, b) print("first ", a, b)

    local r = foo(a + 1)
 
    print("second ", r)
 
    local r, s = coroutine.yield(a + b, a - b)
 
    print("third ", r, s)
 
    return b, "over"

end )

print(coroutine.resume(co, 1, 10)) -- 第一次调用,将1,10传入给create的a b 参数,直到第5行函数挂起,返回2*a

print(coroutine.resume(co, "r")) -- 第二次调用,由于协程已经产生,重启协程并将参数 r 赋值给第5行被挂起的断点 coroutine.yield ,因而 r = "r" 即此时 coroutine.yield 将 return "r" 使得第11行 local r = "r"

print(coroutine.resume(co, "x", "y")) print(coroutine.resume(co, "x", "y"))

-- 输出: --[[ --first 1 10 --foo_out 2 --true 4 --second r --true 11 -9 --third x y --true 10 over --false cannot resume dead coroutine --]]

二十、Lua 面向对象

Lua 使用表描述对象的属性,Lua 的函数用来表示方法,类可通过表+函数模拟出来。

1)简单创建类

#!/usr/local/bin/lua

Shape = {area = 0} -- Shape 作为类的元表

function Shape:new (o, side) -- 声明一个类,相当于 __ construct() 类的构造方法 o = o or {}

setmetatable(o, self) -- 这里的self指的是Shape

self.__index = self -- 当访问o.area,因为o中没有area,因此会访问Shape中的area

side = side or 0

self.area = side * side -- 声明新的类属性 self.hello = 1

return o

end

function Shape:printArea() -- 声明类的成员方法 print("Area is ", self.area) end

-- 创建对象

shaper = Shape:new(nil, 10)

shaper:printArea() -- 访问方法

print(shaper.hello) -- 访问成员属性

2)继承

#!/usr/local/bin/lua

Shape = { area = 1 }

function Shape:new (o, side) o = o or {}

setmetatable(o, self)

self.__index = self

side = side or 0

self.area = side * side

return o

end

function Shape:printArea() print(self.area) end

-- 继承

Square = Shape:new()

function Square:new(o, side) o = o or Shape:new(o, side) -- 使用 Shape 表作为父类

setmetatable(o, self)

self.__index = self

return o

end

-- 使用继承类

square = Square:new(nil, 10)

square:printArea()

0

评论区