lua 基础语法(上)

六种基本数据类型详解

1. nil (空值)

nil 类型只有一个值,就是 nil。它代表一个无效或不存在的值。

  • 默认值 :一个全局变量在首次被赋值前,其默认值就是 nil
  • 删除变量 :将一个变量赋值为 nil,相当于删除这个变量。
  • 逻辑假 :在条件判断中,nil 被视为"假"。
2. boolean (布尔值)

boolean 类型只有两个值:truefalse

  • 逻辑判断 :在 Lua 中,只有 falsenil 被视为"假" 。所有其他值,包括数字 0、空字符串 "",在条件表达式中都被视为"真"。这一点与其他许多编程语言不同,需要特别注意。
3. number (数字)

number 类型用于表示数值。

  • 不区分精度:Lua 不区分整数和浮点数,所有数字默认都是双精度浮点数。
  • 多种表示 :支持十进制、十六进制(如 0xFF)和科学计数法(如 2e3 代表 2000)。
4. string (字符串)

string 类型用于表示文本。

  • 不可变性:字符串一旦创建,其内容是不可改变的。
  • 引号 :可以使用单引号 '...' 或双引号 "..." 来定义,两者等价。
  • 拼接 :使用两个点 .. 作为连接操作符,例如 "Hello" .. " World"
  • 多行字符串 :使用 [[...]] 可以方便地定义多行字符串,并且会保留其中的所有字符,不进行转义。
5. table (表)

table 是 Lua 中唯一的数据结构,功能极其强大和灵活,可以看作是"关联数组"。

  • 多功能性:它可以被用作数组、字典(哈希表)、对象、模块等。
  • 创建 :使用构造表达式 {} 来创建一个空表。
  • 索引
    • 数组 :当用作数组时,索引默认从 1 开始,而不是 0。
    • 字典 :可以使用任意非 nil 值作为键(key)。
  • 访问 :对于字符串键,t["key"]t.key 两种写法等价,后者更简洁。
6. function (函数)

在 Lua 中,函数是一种"一等公民"(First-class Citizen),这意味着函数可以像普通变量一样被赋值、作为参数传递和作为返回值。

  • 定义 :可以使用 function 关键字定义命名函数,也可以使用匿名函数(function(...) ... end)并将其赋值给变量。
  • 闭包:Lua 完美支持闭包,即函数可以捕获并持有其定义时所在作用域的变量。

单行注释

单行注释以两个连续的短横线 -- 开头,从 -- 开始直到行尾的所有内容都会被 Lua 解释器忽略。

使用场景:

  • 对单行代码进行简短说明。

  • 临时注释掉某一行代码。

    -- 这是一个单行注释
    print("Hello") -- 这也是一个单行注释,位于代码行尾
    -- print("这行代码被注释掉了,不会执行")

📄 多行注释 (块注释)

多行注释,也称为块注释,用于注释掉大段的代码或编写详细的说明。它以 --[[ 开头,以 ]] 结尾。

基本语法:

复制代码
--[[
  这是一个多行注释。
  可以包含很多行文本,
  用于详细解释复杂的代码逻辑。
]]
print("Hello")

💡 进阶技巧:处理特殊情况

1. 注释内容中包含 ]]

如果你的注释内容中恰好包含了 ]] 字符串,会导致注释提前结束,引发语法错误。为了解决这个问题,Lua 允许你在注释的起始和结束标记中添加任意数量的等号 = 来配对。

示例:

复制代码
--[=[
  这是一个多行注释,
  注意看下面这行,它包含了 ']]' 字符串,但不会导致注释结束。
  local str = "这是一个 ]] 字符串"
--]=]
2. 快速开关多行注释

这是一个非常实用的技巧。如果你想快速地将一大段多行注释变为可执行代码,或者反过来,可以在 --[[ 前面再加一个短横线,变成 ---[[

  • --[[ ... ]] 是一个多行注释,内部代码不会执行
  • ---[[ ... ]] 中,--- 被视为一个单行注释,而 [[ ... ]] 则变成了一个多行字符串(在 Lua 中,多行字符串的语法是 [[...]]),内部代码会被执行

示例:

复制代码
---[[
  print("这行代码会被执行,因为外层是多行字符串,不是注释")
--]]

函数声明

这是最常见和直观的声明方式,使用 function 关键字。

复制代码
-- 全局函数
function sayHello(name)
    print("Hello, " .. name .. "!")
end

-- 局部函数 (推荐)
local function sayGoodbye(name)
    print("Goodbye, " .. name .. "!")
end

sayHello("Alice")    -- 输出: Hello, Alice!
sayGoodbye("Bob")    -- 输出: Goodbye, Bob!

匿名函数赋值

函数可以不被命名,而是作为一个值(匿名函数)直接赋值给一个变量。这种方式在需要动态创建函数或作为回调时非常有用。

复制代码
-- 将匿名函数赋值给一个局部变量
local myPrint = function(content)
    print("[日志] " .. content)
end

-- 调用
myPrint("这是一个测试") -- 输出: [日志] 这是一个测试

函数核心特性

参数 (Arguments)
  • 参数数量不匹配 :Lua 对参数数量非常宽容。如果调用时提供的参数少于定义,不足的参数会被自动赋值为 nil。如果提供的参数多于定义,多余的参数会被直接忽略。

  • 可变参数 (Varargs) :使用三个点 ... 可以让函数接收任意数量的参数。这些参数可以在函数体内通过 {...} 构造成一个表(数组)来遍历和处理。

    -- 可变参数示例
    local function addAll(...)
    local args = {...} -- 将所有参数放入一个表中
    local sum = 0
    for i, v in ipairs(args) do
    sum = sum + v
    end
    return sum
    end

    print(addAll(1, 2, 3)) -- 输出: 6
    print(addAll(10, 20, 30, 40)) -- 输出: 100

返回值 (Return Values)
  • 多重返回值 :这是 Lua 的一大特色。一个函数可以同时返回多个值,调用者可以使用多重赋值来接收它们。

    • 如果接收变量少于返回值数量,多余的返回值会被丢弃。
    • 如果接收变量多于返回值数量,多余的变量会被赋值为 nil
  • 默认返回 :如果函数执行完毕没有遇到 return 语句,它会默认返回 nil

    -- 多重返回值示例
    local function getUserInfo()
    return "Alice", 25, "Engineer"
    end

    -- 接收所有返回值
    local name, age, job = getUserInfo()
    print(name, age, job) -- 输出: Alice 25 Engineer

    -- 只接收第一个返回值
    local onlyName = getUserInfo()
    print(onlyName) -- 输出: Alice

作用域 (Scope)

和变量一样,函数也遵循作用域规则。

  • 全局函数 :默认情况下,使用 function funcName() 声明的函数是全局的,可以在任何地方被调用。
  • 局部函数强烈建议 使用 local function funcName() 来声明函数。这可以将函数限制在当前的代码块内,避免污染全局命名空间,是模块化编程的最佳实践。

在 Lua 中,变量声明的核心在于理解其动态类型作用域机制。与许多静态类型语言不同,Lua 的变量声明非常灵活,但也因此需要开发者格外注意,以避免潜在的错误。

核心特性:动态类型

Lua 是一种动态类型语言,这意味着:

  • 变量本身没有类型 ,只有它所持有的才有类型。

  • 无需在声明时指定变量的类型。

  • 同一个变量可以在程序运行过程中被赋予不同类型的值。

    local myVar = 10 -- myVar 现在是 number 类型
    myVar = "Hello, Lua!" -- 现在 myVar 变成了 string 类型
    myVar = true -- 现在 myVar 变成了 boolean 类型

📝 声明方式:全局与局部

Lua 中的变量根据其作用域分为两种:全局变量和局部变量。

局部变量 (Local Variables)

使用 local 关键字声明的变量是局部变量。它的作用域仅限于声明它的那个代码块 (例如函数内部、if 语句、for 循环或 do...end 块)。

复制代码
local x = 10
local name = "Alice"
local t = {1, 2, 3}
全局变量 (Global Variables)

如果不使用 local 关键字,直接通过赋值创建的变量就是全局变量。全局变量在整个 Lua 环境中都是可见的,可以被任何地方访问和修改。

复制代码
globalVar = "I am global" -- 这是一个全局变量

⚖️ 局部变量 vs. 全局变量

强烈推荐使用局部变量,原因如下:

  1. 避免命名冲突:局部变量的作用域是隔离的,可以防止不同模块或函数之间因使用相同变量名而互相干扰。
  2. 性能更优:Lua 访问局部变量的速度比访问全局变量更快。
  3. 防止内存泄漏 :局部变量在超出其作用域后,会很快被垃圾回收器(GC)回收。而全局变量会一直存在于全局环境表 _G 中,可能导致内存无法及时释放。
  4. 提高代码可读性:将变量的作用域限制在必要的最小范围内,使代码逻辑更清晰,易于理解和维护。
示例:作用域对比
复制代码
local globalCounter = 0 -- 这是一个局部变量,但在文件顶层,作用域是整个文件

function increase()
    local localCounter = 0 -- 这是一个真正的局部变量,只在函数内有效
    localCounter = localCounter + 1
    globalCounter = globalCounter + 1
    print("函数内 localCounter:", localCounter) -- 输出: 1
    print("函数内 globalCounter:", globalCounter) -- 输出: 1
end

increase()
-- print(localCounter) -- 错误!localCounter 在此处不可见
print("函数外 globalCounter:", globalCounter) -- 输出: 1,值被保留了
相关推荐
wjs20241 小时前
ASP 发送电子邮件
开发语言
li1670902701 小时前
第二十五章:C++11(下)
c语言·开发语言·数据结构·c++
lsx2024061 小时前
DOM 改变节点
开发语言
时空系1 小时前
第8篇:结构模板——自定义数据类型 Rust中文编程
开发语言·网络·rust
yuweiade1 小时前
GO 快速升级Go版本
开发语言·redis·golang
lly2024061 小时前
SOAP Body 元素
开发语言
咸鱼2.03 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录91710 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
周杰伦fans11 小时前
AutoCAD .NET 二次开发:深入理解 EntityJig 的工作原理与正确实现
开发语言·.net