基本语法 标识符 Lua 标识符用于定义一个变量。
Lua 是一个区分大小写 的编程语言。
最好不要 使用下划线加大写字母 的标识符(比如 _VERSION),因为Lua的保留字也是这样的。
Lua 不允许使用特殊字符 如 @ , $ , 和 % 来定义标识符。
1 2 3 name = "Jerry" _temp = 1 Abc = true
关键词 以下列出了 Lua 的保留关键词,保留关键字不能作为常量或变量或其他用户自定义标示符:
and
break
do
else
elseif
end
false
for
function
if
in
local
nil
not
or
repeat
return
then
true
until
while
goto
一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。
变量 lua默认变量是全局变量
Lua 是动态类型语言,变量无需声明类型 ,但实际存储时会区分以下类型:
类型
示例
特点
nil
local x
未赋值的默认值
boolean
local b = true
仅 true/false 两个值
number
local n = 3.14
不区分整数和浮点数
string
local s = "Lua"
不可变,采用高效哈希存储
table
local t = {}
唯一数据结构,功能强大
function
local f = print
一等公民,可存储在变量中
类型检测:
1 2 3 print (type (undefined_var)) print (type (1 == 1 )) print (type (2 ^100 ))
变量作用域规则 全局变量
直接赋值创建(无需声明)
生命周期持续到脚本结束
存储在 _G 全局表中
1 2 playerName = "阿尔萨斯" print (_G ["playerName" ])
局部变量(推荐)
使用 local 关键字声明
作用域限定在声明块内(代码块/函数/控制结构)
优先访问局部变量
1 2 3 4 5 do local itemCount = 5 print (itemCount) end print (itemCount)
常见作用域示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 local MAX_LEVEL = 100 function CreatePlayer () local defaultHP = 200 return { hp = defaultHP } end for i = 1 , 3 do local temp = i * 2 print (temp) end
闭包中的变量
1 2 3 4 5 6 7 8 9 10 11 function MakeCounter () local count = 0 return function () count = count + 1 return count end end local c1 = MakeCounter()print (c1()) print (c1())
多次赋值 1 2 3 4 5 6 7 8 9 10 11 local x, y = 10 , 20 x, y = y, x local a, b, c = 1 , 2 print (c) function GetCoords () return 10 , 20 end local posX, posY = GetCoords()
字符串 表示方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 local s1 = 'Hello' local s2 = "World" local s3 = [[ 这是 多行 字符串 ]] local s4 = "Line1\nLine2\tTabbed"
字符串连接 1 2 3 4 5 6 local name = "Alice" local greeting = "Hello, " .. name .. "!" local parts = {"This" , "is" , "a" , "sentence" }local sentence = table .concat (parts, " " )
字符串函数 基础函数
函数
示例
结果
说明
string.len()
string.len("Lua")
3
字符串长度
string.lower()
string.lower("Lua")
“lua”
转小写
string.upper()
string.upper("Lua")
“LUA”
转大写
string.reverse()
string.reverse("Lua")
“auL”
反转字符串
string.rep()
string.rep("a", 3)
“aaa”
重复字符串
子字符串操作
1 2 3 4 5 6 7 8 9 local s = "Programming in Lua" print (string .sub (s, 5 , 8 )) print (s:sub (-3 )) print (string .find (s, "in" )) print (s:find ("Lua" ))
字符串格式化
1 2 3 4 5 6 7 8 print (string .format ("Pi = %.2f" , math .pi )) local date = string .format ("%04d-%02d-%02d" , 2023 , 5 , 20 ) print (string .format ("%-10s|%5d" , "Lua" , 5 ))
常用格式说明符
说明符
示例
输出示例
说明
%.nf
%.2f
“3.14”
浮点数,保留n位小数
%nd
%04d
“0012”
整数,至少n位数字(不足补0)
%ns
%10s
“ Hello”
字符串,至少n个字符宽度(默认右对齐)
%-ns
%-10s
“Hello “
字符串,左对齐
%e
%.2e
“3.14e+00”
科学计数法
%g
%.4g
“3.142”
自动选择%f或%e的更紧凑形式
%%
"50%%"
“50%”
百分号转义
运算符
运算符类型
运算符
示例
说明
优先级
算术运算符
+
5 + 3 → 8
加法
4
-
7 - 2 → 5
减法
4
*
3 * 4 → 12
乘法
3
/
10 / 2 → 5.0
除法(始终返回浮点数)
3
// (Lua 5.3+)
10 // 3 → 3
整除(向下取整)
3
%
10 % 3 → 1
取模
3
^
2^3 → 8
幂运算(优先级高于乘除)
2
- (一元)
-5 → -5
负号
5
关系运算符
==
5 == 5 → true
相等比较(不自动转换类型)
6
~=
5 ~= 3 → true
不等比较
6
<
3 < 5 → true
小于
6
>
5 > 3 → true
大于
6
<=
3 <= 3 → true
小于等于
6
>=
5 >= 5 → true
大于等于
6
逻辑运算符
and
true and false → false
逻辑与(短路求值)
7
or
true or false → true
逻辑或(短路求值)
8
not
not true → false
逻辑非
5
连接运算符
..
"Hello".."World" → “HelloWorld”
字符串连接(会强制数字转字符串)
1
长度运算符
#
#"Lua" → 3
获取字符串长度/数组元素个数(忽略非连续数字键)
5
位运算符 (Lua 5.3+)
&
5 & 3 → 1
按位与
4
`
`
`5
3` → 7
~
~5 → -6
按位非
5
<<
1 << 2 → 4
左移
4
>>
8 >> 1 → 4
右移
4
特殊运算符
:
obj:method()
方法调用语法糖(自动传递self)
-
[]
tbl[key]
表索引访问
-
条件语句 if-then-else 基础结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 if 条件 then end if score >= 90 then print ("优秀" ) else print ("及格" ) end if temperature > 30 then print ("炎热" ) elseif temperature > 20 then print ("舒适" ) elseif temperature > 0 then print ("凉爽" ) else print ("寒冷" ) end
条件表达式特点:
Lua 中只有 false 和 nil 视为假,其他值都为真
包括 0、"" 和 {} 都视为真值
支持短路求值
1 2 3 4 5 local name = username or "匿名用户" local value = config and config .settings and config .settings.volume or 50
循环语句 while循环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 local i = 1 while i <= 5 do print ("计数:" , i) i = i + 1 end local found = false while not found do local num = math .random (10 ) if num == 7 then print ("找到7了!" ) found = true end end
repeat-until 循环 1 2 3 4 5 6 7 8 9 10 11 12 13 local input repeat print ("请输入yes继续:" ) input = io .read () until input == "yes" local x = 10 repeat x = x + 1 print (x) until x > 10
for循环 数值for循环 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 for i = 1 , 5 do print (i) end for i = 10 , 1 , -2 do print (i) end for x = 0 , 1 , 0.2 do print (string .format ("%.1f" , x)) end
泛型for循环 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 local colors = {"红" ,"绿" ,"蓝" }for i, color in ipairs (colors) do print (i, color) end local player = {name="Alice" , level=30 , class="Mage" }for k, v in pairs (player) do print (k..": " ..v) end function square (max) local i = 0 return function () i = i + 1 if i <= max then return i, i*i end end end for num, sq in square(3 ) do print (num, sq) end
pairs 和 ipairs对比 :
ipairs (Indexed Pairs)
特点:
顺序遍历 :从索引 1 开始,按 连续数字索引 依次遍历(1, 2, 3…)
终止条件 :遇到第一个 nil 值时停止
忽略非数字键 :不遍历字符串键或其他类型的键
性能略高 :对连续数字索引的遍历比 pairs 稍快
1 2 3 for index, value in ipairs (table ) do end
示例:
1 2 3 4 local fruits = { "apple" , "banana" , "cherry" }for i, fruit in ipairs (fruits) do print (i, fruit) end
注意:
如果 table 有空洞(如 { "a", nil, "c" }) ,ipairs 会在第二个元素停止遍历 。
pairs
特点:
全遍历 :遍历 table 的 所有键值对 (包括数字、字符串等任意类型的键)
无序性 :遍历顺序不确定(Lua 不保证顺序)
无终止条件 :即使有 nil 也会继续遍历
更通用 :适用于所有类型的 table
语法:
1 2 3 for key, value in pairs (table ) do end
适用场景:
遍历 非连续索引的 table (如 { "a", [3]="c", key="value" })
需要访问所有键值对的场景
示例:
1 2 3 4 local data = { "a" , [3 ] = "c" , name = "Lua" , version = 5.4 }for k, v in pairs (data) do print (k, v) end
循环控制语句 break
1 2 3 4 5 6 7 for i = 1 , 100 do if i > 5 then break end print (i) end
return (在循环中使用)
1 2 3 4 5 6 7 8 function find (tbl, value) for i, v in ipairs (tbl) do if v == value then return i end end return nil end
特殊用法与技巧 多条件组合
1 2 3 4 5 6 7 8 9 if (score > 90 ) and (attendance >= 0.8 ) then print ("优秀学生" ) end if 10 <= x and x <= 20 then print ("x在10到20之间" ) end
模拟switch-case
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 local action = "save" if action == "new" then createNew() elseif action == "save" then saveFile() elseif action == "load" then loadFile() else defaultAction() end local actions = { new = createNew, save = saveFile, load = loadFile } (actions[action] or defaultAction)()
循环性能优化
1 2 3 4 5 6 7 8 9 10 11 12 local tbl = {1 ,2 ,3 ,4 ,5 }local len = #tblfor i = 1 , len do end local print = print for i = 1 , 1000 do print (i) end
常见错误与陷阱 浮点数循环 :
1 2 3 4 for x = 0 , 1 , 0.1 do print (x) end
修改迭代表 :
1 2 3 4 local t = {1 ,2 ,3 }for i,v in ipairs (t) do table .insert (t, v*2 ) end
误用break :
1 2 3 4 5 6 7 8 while true do for i=1 ,10 do if condition then break end end end
nil值处理 :
1 2 3 4 5 local t = {1 ,nil ,3 }print (#t) for i=1 ,#t do print (t[i]) end
函数 定义与调用 1 2 3 4 5 6 7 8 9 10 11 12 function greet (name) return "Hello, " .. name end local greet = function (name) return "Hello, " .. name end print (greet("Alice" ))
参数 传递规则
参数数量灵活 :可接受多于或少于声明参数的数量
不足补nil ,多余忽略
支持可变参数 (vararg)
1 2 3 4 5 6 function test (a, b) print (a, b) end test(1 ) test(1 , 2 , 3 )
可变参数(…) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function sum (...) local total = 0 local args = {...} for i, v in ipairs (args) do total = total + v end return total end print (sum(1 , 2 , 3 )) function sum (...) local total = 0 for i = 1 , select ("#" , ...) do total = total + select (i, ...) end return total end
多返回值 1 2 3 4 5 6 7 8 9 function getDimensions () return 1024 , 768 end local w, h = getDimensions()print (w, h) local width = getDimensions()
闭包 1 2 3 4 5 6 7 8 9 10 11 function makeCounter () local count = 0 return function () count = count + 1 return count end end local c1 = makeCounter()print (c1()) print (c1())
函数作为参数 1 2 3 4 5 6 7 8 9 10 11 12 function map (tbl, fn) local result = {} for i, v in ipairs (tbl) do result[i] = fn(v) end return result end local numbers = {1 , 2 , 3 }local squared = map(numbers, function (x) return x*x end )print (table .concat (squared, "," ))
尾调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function foo (n) if n <= 0 then return end print (n) return foo(n-1 ) end function bar (n) if n <= 0 then return end print (n) bar(n-1 ) end function endless () print ("Running..." ) return endless() end
表 表(Table)是 Lua 中唯一 的数据结构,却可以模拟数组、字典、对象等多种数据结构
创建表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 local t1 = {}local colors = {"红" , "绿" , "蓝" }local person = { name = "Alice" , age = 25 , profession = "程序员" } local mixed = { "元素1" , "元素2" , key1 = "值1" , key2 = "值2" }
访问元素:
1 2 3 4 5 6 7 8 9 10 print (colors[1 ]) print (person["name" ]) print (person.age) local key = "age" print (person[key])
作为数组 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 local arr = {"a" , "b" , "c" }print (#arr) for i = 1 , #arr do print (arr[i]) end for index, value in ipairs (arr) do print (index, value) end
⚠️ 注意:Lua数组索引从1 开始,且遇到nil会中断长度计算
作为字典 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 local dict = { name = "Alice" , age = 25 , [1 ] = "数字键1" , ["1" ] = "字符串键1" } for key, value in pairs (dict) do print (key, value) end if dict.name then print ("name存在" ) end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 local t = {}local mt = { __index = function (table, key) return "默认值" end , __newindex = function (table, key, value) rawset (table , key, value.."已修改" ) end } setmetatable (t, mt)print (t.a) t.b = "测试" print (t.b)
常用元方法:
元方法
触发时机
示例
__index
访问不存在的键
t.key
__newindex
给不存在的键赋值
t.key = value
__add
+ 运算
t1 + t2
__call
表作为函数调用
t()
__tostring
转换为字符串
tostring(t)
操作函数
函数
描述
示例
table.insert(t, [pos,] value)
插入元素
table.insert(t, 1, "x")
table.remove(t, [pos])
删除元素
table.remove(t, 1)
table.concat(t, [sep])
连接数组元素
table.concat(t, ",")
table.sort(t, [comp])
排序
table.sort(t, function(a,b) return a>b end)
table.unpack(t)
返回数组所有元素
a,b,c = table.unpack(t)
实用代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function deepCopy (orig) local copy = {} for k, v in pairs (orig) do if type (v) == "table" then v = deepCopy(v) end copy[k] = v end return copy end function merge (t1, t2) local res = {} for k, v in pairs (t1) do res[k] = v end for k, v in pairs (t2) do res[k] = v end return res end function tableToString (t) local result = {} for k, v in pairs (t) do table .insert (result, tostring (k).."=" ..tostring (v)) end return "{" ..table .concat (result, ", " ).."}" end
面向对象 Lua 本身没有内置的面向对象系统,但通过表和元表可以灵活实现各种 OOP 模式
原型模式(最常用) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 local Person = {name = "unnamed" , age = 0 } function Person:new (name, age) local obj = { name = name or self .name, age = age or self .age } setmetatable (obj, {__index = self }) return obj end function Person:introduce () print ("我是" ..self .name..",今年" ..self .age.."岁" ) end local p1 = Person:new("Alice" , 25 )p1:introduce()
继承实现 单继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 local Animal = { name = "未知生物" , sound = "..." } function Animal:new (name) local obj = {name = name or self .name} setmetatable (obj, {__index = self }) return obj end function Animal:makeSound () print (self .name.."发出声音:" ..self .sound) end local Cat = Animal:new() Cat.sound = "喵喵" function Cat:makeSound () print (self .name.."优雅地叫:" ..self .sound) end local cat = Cat:new("小花" )cat:makeSound()
多继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 local function multiInherit (...) local classes = {...} local obj = {} setmetatable (obj, { __index = function (table, key) for _, class in ipairs (classes) do local value = class[key] if value then return value end end end }) return obj end local Flyable = { altitude = 0 } function Flyable:fly () self .altitude = self .altitude + 100 print (self .name.."飞到" ..self .altitude.."米高空" ) end local Bird = Animal:new()Bird = multiInherit(Bird, Flyable) local bird = Bird:new("信天翁" )bird:makeSound() bird:fly()
私有成员实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 local function createClass () local privateData = {} local MyClass = {} function MyClass:new (name) local obj = {name = name} privateData[obj] = { secret = math .random (1000 ) } setmetatable (obj, {__index = self }) function obj:getSecret () return privateData[self ].secret end return obj end return MyClass end local SecretClass = createClass()local obj = SecretClass:new("test" )print (obj:getSecret()) print (obj.secret)