Lua 函数有两种定义形式,核心语法是 function 函数名(参数) ... end,结束必须用 end 界定代码块。
函数声明
-- 方式1:标准定义(全局函数)
function add(a, b)
return a + b -- 返回值,可多个
end
-- 方式2:标准定义(局部函数)
local function add1(a, b)
return a + b -- 返回值,可多个
end
-- 方式3:赋值式定义(更灵活,可定义局部函数)
local sub = function(a, b)
return a - b
end
-- 调用函数(和其他语言一致)
local sum = add(3, 5)
local sum1 = add1(3, 5)
local diff = sub(10, 4)
print(sum, sum1, diff) -- 输出:8 8 6
函数参数
Lua 不检查调用时的参数个数,参数不匹配时会自动补 nil 或忽略多余参数;
参数不匹配
-- 示例:参数个数不匹配
function test(a, b)
print(a, b)
end
test(1) -- 输出:1 nil(第二个参数补 nil)
test(1, 2, 3) -- 输出:1 2(第三个参数被忽略)
默认参数:手动实现(Lua 无原生默认参数)
-- 示例:给参数设置默认值
function greet(name)
-- 如果 name 是 nil,赋值为 "游客"
name = name or "游客"
print("你好," .. name)
end
greet() -- 输出:你好,游客
greet("张三") -- 输出:你好,张三
可变参数:接收任意个数的参数
用 ...(三点)表示可变参数,可通过 {...} 转为 table 遍历,或用 select() 获取参数个数 / 指定参数。
-- 示例1:求和任意个数的数字
function sum(...)
local args = {...} -- 把可变参数转为 table
local total = 0
for _, v in ipairs(args) do
total = total + v
end
return total
end
print(sum(1,2,3)) -- 输出:6
print(sum(10,20,30)) -- 输出:60
-- 示例2:用 select 获取参数信息
function test(...)
print(select("#", ...)) -- 获取参数个数:输出 3
print(select(2, ...)) -- 获取第 2 个及之后的参数:输出 2 3
end
test(1,2,3)
函数值
Lua 函数可以返回多个值,调用时可接收全部或部分返回值,这是和很多语言的重要区别。
-- 定义返回多个值的函数
function get_user()
return "张三", 20, "男" -- 返回 3 个值
end
-- 接收全部返回值
local name, age, gender = get_user()
print(name, age, gender) -- 输出:张三 20 男
-- 只接收部分返回值(多余的会被忽略)
local name_only = get_user()
print(name_only) -- 输出:张三
-- 忽略某个返回值(用 _ 占位)
local _, age_only = get_user()
print(age_only) -- 输出:20
函数的高级用法
函数作为值
Lua 中函数是 “第一类值”,可以赋值给变量、作为参数传递、作为 table 的元素,这是实现回调、闭包的基础。
function add(a, b)
return a + b
end
function sub(a, b)
return a - b
end
-- 1. 函数赋值给变量
local f = add
print(f(4,5)) -- 输出:9
-- 2. 函数作为 table 的元素(模拟对象方法)
local user = {
name = "李四",
say = function(self)
print("我是" .. self.name)
end
}
user:say() -- 输出:我是李四(冒号自动传 self)
-- 3. 函数作为参数(回调函数)
function calculate(a, b, func)
return func(a, b)
end
local result = calculate(10, 5, sub) -- 传入 sub 函数
print(result) -- 输出:5
闭包
闭包是 “可以访问外部作用域变量的函数”,即使外部作用域已结束,闭包仍能访问这些变量,是 Lua 实现私有变量、工厂函数的核心。
-- 示例:工厂函数,生成累加器
function create_counter(init)
local count = init or 0 -- 外部作用域变量
-- 闭包函数:访问外部的 count
return function()
count = count + 1
return count
end
end
-- 创建两个独立的累加器
local counter1 = create_counter(0)
local counter2 = create_counter(10)
print(counter1()) -- 输出:1
print(counter1()) -- 输出:2
print(counter2()) -- 输出:11
print(counter2()) -- 输出:12
递归
函数可以调用自身(递归),需注意设置终止条件,避免死循环。
-- 示例:递归计算阶乘
function factorial(n)
if n == 1 then -- 终止条件
return 1
end
return n * factorial(n-1) -- 递归调用
end
print(factorial(5)) -- 输出:120(5*4*3*2*1)
表方法和对象方法
- 表方法(Table Method)
定义:直接绑定在表上的函数,是 Lua 最基础的 “方法” 形式,本质是 “表的键值对,值为函数”。
- 表是 Lua 最核心的数据结构,任何函数都可以作为表的一个字段(键),这个函数就称为 “表方法”;
- 表方法不强制依赖
self,可独立调用,也可结合self使用。
- 对象方法(Object Method)
定义:模拟面向对象编程时,给 “对象(本质还是表)” 绑定的、依赖 self 访问对象属性的表方法。
- Lua 中 “对象” 是通过表模拟的(表包含属性 + 方法),“对象方法” 就是这个模拟对象的方法;
- 必须依赖
self(指向对象本身),用于访问对象的属性,是表方法的 “面向对象化” 用法。
-- 定义一个工具表,存放通用函数(纯表方法)
local utils = {}
-- 表方法1:无参数,纯功能
utils.print_hello = function()
print("Hello, Lua!")
end
-- 表方法2:有参数,处理外部数据
utils.add = function(a, b)
return a + b
end
-- 调用:只用 . 调用,无需 self
utils.print_hello() -- 输出:Hello, Lua!
print(utils.add(1, 2)) -- 输出:3
把表当作 “对象”,表中既有属性(如 name/age),又有方法(依赖 self 访问属性),这就是 “对象方法”:
-- 把表当作“对象”,包含属性和方法
local person = {
name = "fengfeng",
age = 21
}
-- 定义对象方法:必须接收 self(指向对象本身),访问对象属性
function person:say_hello() -- 定义时用 :,自动加 self 参数
print("我是" .. self.name .. ",今年" .. self.age .. "岁")
end
-- 定义对象方法:修改对象属性
function person:grow_up()
self.age = self.age + 1
print(self.name .. "长大了,现在" .. self.age .. "岁")
end
-- 调用对象方法:用 :,自动传 self(即 person)
person:say_hello() -- 输出:我是fengfeng,今年21岁
person:grow_up() -- 输出:fengfeng长大了,现在22岁