当前位置: 首页 > news >正文

Lua 零基础入门

Lua

1.Lua是什么?

1.1 Lua的历史

Lua是由Roberto Ierusalimschy、Luiz Henrique de Figueiredo和Waldemar Celes于1993年创建的,当时他们是巴西里约热内卢天主教大学计算机图形技术组(Tecgraf)的成员。在开发Lua之前,他们曾参与过数据描述/配置语言"SOL"(简单对象语言)和"DEL"(数据录入语言)的工作。这两种语言是他们独立开发的两个不同项目的一部分,旨在增强工程应用的交互式图形程序。然而,SOL和DEL缺乏许多控制流结构,因此需要增加完整的编程能力。因此,为了满足这个需求,他们创建了Lua。

在《The Evolution of Lua》中,Lua的作者写道,在1993年,Tcl是Lua的唯一真正竞争者,但Tcl的语法相对较为陌生,且只能在Unix平台上运行,不太适合数据描述。此外,LISP和Scheme的语法也不够友好,Python还处于起步阶段。在Tecgraf的自由、自主的氛围下,他们自然而然地尝试开发自己的脚本语言。考虑到这门语言的潜在用户不一定是专业程序员,因此他们希望语言避免复杂的语法和语义。另外,由于Tecgraf的客户使用各种不同的计算机平台,他们希望新语言的实现能够高度可移植。最后,考虑到Tecgraf的其他产品也需要嵌入脚本语言,他们决定让新语言像SOL一样提供带有C API的库。

1.2 Lua的特点

Lua 作为一种脚本语言具有多种特点,以下是其中一些主要的特点:

  1. 轻量级和可嵌入性:Lua 的核心非常小巧,可以轻松地嵌入到其他应用程序中,作为脚本语言使用。这使得 Lua 在游戏开发、嵌入式系统和其他领域中得到广泛应用。
  2. 简洁清晰的语法:Lua 的语法简洁明了,易于学习和使用。它没有过多的冗余符号,采用基于表达式的语法,没有大括号,使用 end 关键字来结束块,使得代码更加清晰易读。
  3. 动态类型和自动内存管理:Lua 是一种动态类型语言(运行时进行变量类型检查和解析),变量不需要显式声明类型。它还具有自动内存管理,通过垃圾回收机制来管理内存,简化了开发者的工作。
  4. 强大的数据描述能力:Lua 支持多种基本数据类型,包括数字、字符串、布尔值、表(类似于字典或关联数组)、函数等。表是 Lua 中最重要的数据结构之一,可以灵活地表示复杂的数据集合。
  5. 灵活的扩展能力:Lua 提供了丰富的扩展接口,可以通过 C/C++ 编写扩展模块,并与 Lua 脚本进行交互。这种可扩展性使得 Lua 可以与其他语言轻松集成,满足不同应用场景的需求。
  6. 高性能:Lua 的解释器经过优化,执行速度较快,适合用于处理大规模的数据和复杂的逻辑。
  7. 动态代码执行:Lua 支持动态代码执行,可以通过 loadloadfile 函数动态加载并执行 Lua 脚本,灵活性很高。
  8. 适用于嵌入式系统:由于 Lua 的轻量级和可嵌入性,它在嵌入式系统中得到广泛应用,可以用于控制设备、配置参数等任务。

Ps:

1、什么是脚本语言?

脚本语言是一种用于编写脚本的编程语言。

脚本是一系列按照特定顺序执行的命令或指令,通常用于自动化任务、配置文件、批处理处理、快速原型开发等场景。脚本语言通常被设计为易于编写和理解,其语法和结构往往更加简单直观。

脚本语言与编译型语言的主要区别在于,脚本语言不需要经过编译成机器代码的过程,而是由解释器逐行解释执行。这使得脚本语言的开发和调试更加快速和灵活,因为开发者可以立即看到代码的效果,而不需要额外的编译步骤。

脚本语言通常用于各种不同的领域,包括:

  1. 自动化任务:例如批处理处理、系统管理任务、自动化测试等。
  2. Web 开发:许多 Web 应用程序的后端和前端都使用脚本语言编写,如 Python、JavaScript、PHP 等。
  3. 游戏开发:脚本语言在游戏开发中也得到广泛应用,用于编写游戏逻辑、AI、用户界面等。
  4. 配置文件:许多软件和系统使用脚本语言编写配置文件,以便用户可以轻松地配置和定制软件的行为。

总的来说,脚本语言是一种简单、灵活且功能强大的编程语言,适用于各种不同的应用场景,能够大大提高开发效率和灵活性。

2、什么是解释性语言,什么是编译性语言?

解释性语言和编译性语言是两种不同类型的编程语言

解释性语言

  • 解释性语言的代码由解释器逐行执行,并在运行时进行解释和执行。
  • 在执行程序时,解释器会逐行读取源代码,并将其转换为计算机可理解的指令,然后立即执行。
  • 由于解释器直接执行源代码,因此解释性语言的开发和调试更加灵活,可以动态地修改和查看代码的效果。
  • 常见的解释性语言包括 Lua、Python、Ruby、JavaScript、PHP 等。

编译性语言

  • 编译性语言的代码需要先经过编译器将源代码转换为机器代码(或者中间代码),然后再由计算机执行。
  • 编译器在编译阶段将源代码转换为目标代码,这个目标代码是针对特定硬件平台的可执行文件或者中间代码。
  • 一旦编译完成,生成的可执行文件可以在没有编译器的情况下独立运行,而不需要再次编译源代码。
  • 编译性语言的执行速度通常比解释性语言更快,因为代码已经被预先转换为机器代码。
  • 常见的编译性语言包括 C、C++、Java等。

2. 解释器的安装

2.1 下载压缩包

https://www.lua.org/download.html
lua-5.4.6.tar.gz

2.2 解压

tar -xzf lua-5.4.6.tar.gz
lua-5.4.6

2.3 安装

cd lua-5.4.6  //进入目录
make //编译
sudo make install //安装

2.4 确认安装结果

lua -v
Lua 5.4.6

ps. lua 在线模拟器

https://wiki.luatos.com/

3.基本语法

3.1 第一个Lua 程序

3.1.1 交互式编程

Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。

Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:

$ lua
$ Lua 5.4.6  Copyright (C) 1994-2023 Lua.org, PUC-Rio
> 

在命令行中,输入以下命令:

> print("Hello World!")

接着我们按下回车键,输出结果如下:

> print("Hello World!")
Hello World!
>
3.1.2 脚本式编程

我们可以将 Lua 程序代码保存到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:

vim hello.lua
print("Hello world!")

终端运行

$ lua hello.lua
hello world!

3.2 注释

3.2.1 单行注释

两个减号是单行注释:

--
3.2.2 多行注释
--[[多行注释多行注释
]]--

3.3 标识符

在 Lua 中,标识符是用于命名变量、函数、以及其他用户定义的东西的名称。Lua 中的标识符遵循以下规则:

  1. 标识符可以由字母、数字和下划线 _ 组成。
  2. 标识符必须以字母(包括大小写)或下划线 _ 开始,不能以数字开头。
  3. Lua 是大小写敏感的,因此 myVariableMyVariable 是两个不同的标识符。
  4. Lua 的关键字(例如 ifthenelsewhilefunction 等)不能用作标识符。
  5. Lua 中允许使用 UTF-8 编码的字母作为标识符,因此也可以使用非拉丁字母作为标识符。

例如,以下是一些合法的 Lua 标识符:

  • myVar
  • _count
  • table1
  • 变量名

而以下是一些不合法的 Lua 标识符:

  • 3abc(以数字开头)
  • if(关键字)
  • my-variable(包含连字符 -
  • #table(包含特殊字符 #

注意:

最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的

3.4 关键字

andbreakdoelse
elseifendfalsefor
functionifinlocal
nilnotorrepeat
returnthentrueuntil
whilegoto

4.数据类型

Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型描述
nil用于表示空或未初始化的值。
boolean只有两个值,true 和 false,用于表示逻辑值。
number用于表示数值,包括整数和浮点数。
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
table是 Lua 中最重要的数据结构,用于表示数组、字典、集合等复杂数据结构

5.变量

5.1 动态类

Lua 是一种动态类型语言,变量的类型是根据赋给它们的值自动确定的。

a = 1;

5.2 全局变量

在默认情况下,变量总是认为是全局的

全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。

> print(b)
nil
> b=10
> print(b)
10

如果你想删除一个全局变量,只需要将变量赋值为nil。

b = nil
print(b)      --> nil

这样变量b就好像从没被使用过一样。换句话说, 当且仅当一个变量不等于nil时,这个变量即存在。

5.3 局部变量

如果想使用局部变量,在变量前加 local 关键字

局部变量的作用域通常是从声明处到当前语句块结束。

local c = 10 -- 这是一个局部变量

5.4 多重赋值

a,b =  1,2
print(a,b)
1  2
a,b,c =  1,2
print(a,b)
1  2  nil

5.5 数值型变量

-- 整型
a = 1-- 浮点型
b = 2.1-- 科学计数法
c = 1e3-- 十六进制
d = 0x11print(a,b,c,d)
1	2.1	1000.0	17
-- 获取字符 'A' 的 ASCII 码值
asciiValue = string.byte('A')-- 输出 ASCII 码值
print(asciiValue)  -- 输出 65

5.6 字符串型变量

字符串由一对双引号或单引号来表示

a = "hello"
b = 'world'print(a,b) -- hello	world

支持在字符串中插入转义字符

c = "hello\nworld"
print(c) -- helloworld

长字符串

d = [[hello
world
!]]print(d)

获取字符串长度(#)

a = "hello world"
print(#a)  --11

字符串合并(…)

a = "hello"
b = "world"
c = a..b
print(c) -- helloworld

数值字符可以和数值直接进行运算

a = "10" + 1
print(a) -- 11.0

tostring() 和 tonumber()

a = tostring(10)
print(type(a))  --stringb = tonumber("10")
print(type(b))  --number-- 转换失败 nil
c = tonumber("abc")
print(type(c)) --nil

6.运算符

Lua 和 C 中的对比:

赋值运算符:

  • Lua: = (单等号)
  • C: =

算术运算符:

  • Lua: +, -, *, /, %
  • C: +, -, *, /, %

关系运算符:

  • Lua: ==, ~=, <, <=, >, >=
  • C: ==, !=, <, <=, >, >=

逻辑运算符:

  • Lua: and, or, not
  • C: &&, ||, !

位运算符:

  • Lua: &, |, ~, <<, >>
  • C: &, |, ~, <<, >>

连接运算符:

  • Lua: ..(用于连接字符串)
  • C: +(用于连接字符串)

其他运算符:

  • Lua: #(取长度)、:(用于对象方法调用)
  • C: sizeof(取大小)

7. 控制流语句

7.1 选择语句

7.1.1 if then else
if condition then-- 当 condition 为 true 时执行这里的代码
else-- 当 condition 为 false 时执行这里的代码
end
-- 定义一个变量
local temperature = 25-- 判断温度是否超过 20 度
if temperature > 20 thenprint("天气很热,建议穿短袖")
elseprint("天气不算太热,可以穿长袖")
end
7.1.2 if then elseif then end
if condition1 then-- 当 condition1 为 true 时执行这里的代码
elseif condition2 then-- 当 condition1 不满足,而 condition2 为 true 时执行这里的代码
else-- 当上述条件都不满足时执行这里的代码
end
-- 定义一个变量
local hour = 15-- 判断当前时间段
if hour < 12 thenprint("现在是上午")
elseif hour >= 12 and hour < 18 thenprint("现在是下午")
elseprint("现在是晚上")
end
7.1.3 三目运算符
local result = condition and value1 or value2--如果 condition 为 true,则返回 value1,否则返回 value2
-- 定义一个变量
local score = 85-- 使用三元运算符判断成绩是否及格
local result = score >= 60 and "及格" or "不及格"-- 输出结果
print("成绩:" .. score .. ",考试结果:" .. result)
ps: 无 switch/case

注意:Lua 中没有直接的 switch/case 语句。但你可以使用多个 if-elseif-else 结构来模拟类似的行为:

local choice = 2
if choice == 1 then-- 处理选择 1 的情况
elseif choice == 2 then-- 处理选择 2 的情况
elseif choice == 3 then-- 处理选择 3 的情况
else-- 处理其他情况
end

7.2 循环语句

7.2.1.for 循环
7.2.1.1 数值型for 循环
for var = startValue, endValue, stepValue do-- 循环体
end
  • var 是循环变量,它从 startValue 开始递增,直到达到或超过 endValue,每次递增 stepValue
  • startValueendValuestepValue 是可选的,默认值分别为 1、endValue、1。
  • 循环体会在每次迭代时执行,循环结束后,循环变量 var 的值会保留在循环作用域中(追踪循环结束时的变量值利用循环变量的最终值进行后续操作利用循环变量的最终值进行条件判断)。
for i = 1, 5 doprint("数值型 for 循环,第 " .. i .. " 次迭代")
end
7.2.1.2 泛型 for 循环
for index, value in ipairs(iterable) do-- 循环体
end
  • iterable 是一个可迭代的对象,例如数组或表。
  • 在每次迭代时,indexvalue 分别表示当前元素的索引和值。
  • ipairs() 函数用于迭代数组类型的表,它返回三个值:迭代函数、表、初始值。
local fruits = {"apple", "banana", "orange"}
for index, fruit in ipairs(fruits) doprint("泛型 for 循环,第 " .. index .. " 个水果是 " .. fruit)
end
7.2.2 while 循环
while condition do-- 循环体
end

while 循环会在 condition 为 true 时执行循环体,直到 condition 为 false 才停止循环。

local j = 1
while j <= 5 doprint("while 循环,第 " .. j .. " 次迭代")j = j + 1
end
7.2.3 repeat until 循环
repeat-- 循环体
until condition

repeat until 循环会先执行一次循环体,然后检查 condition,如果 condition 为 true,则继续执行循环体,直到 condition 为 false 才停止循环。

local k = 1
repeatprint("repeat until 循环,第 " .. k .. " 次迭代")k = k + 1               -- lua 没有 k++ 也可以 k += 1 
until k > 5

8.函数

8.1 函数定义

optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)function_bodyreturn result_params_comma_separated
end
  • optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local
  • function_name: 指定函数名称。
  • argument1, argument2, argument3…, argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
  • function_body: 函数体,函数中需要执行的代码语句块。
  • result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。
--函数返回两个值的最大值 
function max(num1, num2)if (num1 > num2) thenresult = num1;elseresult = num2;endreturn result;
end

8.2 函数调用

函数调用可以通过函数名加上一对圆括号来完成,可以传入函数定义中所需的参数。

-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))

8.3 多返回值

在 Lua 中,函数可以返回多个值。调用函数时,可以使用逗号分隔多个返回值。

function f()return 1, 2, 3
endlocal a, b, c = f()
print(a, b, c) -- 输出: 1 2 3

8.4 匿名函数

匿名函数在 Lua 中是一种特殊的函数,它们不需要显式地命名,通常用于一次性的、简单的操作或作为其他函数的参数。

local double = function(x)return x * 2
endprint(double(5)) -- 输出: 10

8.5 函数作为参数和返回值

在 Lua 中,函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。

function applyFunction(func, value)return func(value)
endprint(applyFunction(double, 5)) -- 输出: 10

8.6 变长参数

在 Lua 中,函数可以接受变长参数,可以通过 ... 表示。可以使用 select() 函数获取变长参数的值

function sum(...)local result = 0for i = 1, select("#", ...) doresult = result + select(i, ...)endreturn result
endprint(sum(1, 2, 3, 4, 5)) -- 输出: 15
ps : select

在 Lua 中,select 是一个用于操作可变数量参数的函数。它可以用于获取可变参数的数量和值。

select 函数的一般形式为:

select(index, ...)

其中:

  • index 是一个索引值,用于选择可变参数列表中的参数。
  • ... 是可变参数列表。

select 函数有两种主要用法:

  1. 获取可变参数的数量

    index 的值为 "#" 时,select 函数返回可变参数的数量。

    示例:

    luaCopy codelocal count = select("#", 1, 2, 3, 4, 5)
    print(count)  -- 输出: 5
    
  2. 获取可变参数的值:

    index 的值为一个整数时,select 函数返回可变参数列表中对应索引位置的参数值。

    示例:

    luaCopy codelocal value = select(3, "a", "b", "c", "d")
    print(value)  -- 输出: c
    

    在这个示例中,select(3, "a", "b", "c", "d") 返回可变参数列表中第 3 个参数的值,即 "c"

需要注意的是,select 函数只能用于处理从 1 开始的索引位置,而不支持负数索引。如果 index 大于可变参数的数量,select 函数返回 nil

8.数组

数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。在 Lua 中,数组不是一种特定的数据类型,而是一种用来存储一组值的数据结构。实际上,Lua 中并没有专门的数组类型,而是使用一种被称为 “table” 的数据结构来实现数组的功能。Lua 数组的索引键值可以使用整数表示,数组的大小不是固定的。在 Lua 索引值是以 1 为起始。

-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}-- 访问数组元素
print(myArray[1])  -- 输出 10
print(myArray[3])  -- 输出 30
print(myArray[-1])  -- 输出 50

要计算数组的长度(即数组中元素的个数),你可以使用 # 操作符:

local myArray = {10, 20, 30, 40, 50}-- 计算数组长度
local length = #myArrayprint(length) -- 输出 5

一维数组可以用 for 循环出数组中的元素

-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}-- 循环遍历数组
for i = 1, #myArray doprint(myArray[i])
end

9.table(表)

在 Lua 中,table 是一种用来保存多个值的数据结构,它类似于其他编程语言中的数组、列表、字典或哈希表。table 是 Lua 中最重要的数据结构之一,也是 Lua 的核心之一。

9.1 数字下标

数字下标的表是 Lua 中常见的数据结构,通常用来表示数组或列表。在这样的表中,键是从 1 开始的整数索引,对应的值可以是任意类型的 Lua 值。

9.1.1 元素组成

在 Lua 的数字下标表中,每个元素可以是任何 Lua 支持的数据类型,包括但不限于:

数字(number):整数或浮点数。

字符串(string):任意长度的文本字符串。

布尔值(boolean):true 或 false。

表(table):嵌套的表,用来表示更复杂的数据结构。

函数(function):可执行的代码块。

线程(thread):Lua 的协程,用于实现轻量级并发。
用户数据(userdata):C 语言中的数据类型,通常由 Lua 扩展库创建。
这意味着你可以将任何 Lua 支持的数据类型存储在数字下标表中的元素中。例如,你可以创建一个包含字符串、数字和表的数组,或者将函数作为数组的元素,以及其他更复杂的数据组合。

local myArray = {10, "hello", true, {20, 30}, function() print("This is a function") end}
9.1.2 元素访问

在 Lua 中,数组的索引从 1 开始,所以第一个元素的索引是 1,第二个元素的索引是 2,以此类推。

print(myArray[1])  -- 输出: 10
print(myArray[2])  -- 输出: hello
print(myArray[3])  -- 输出: true
print(myArray[4][1])  -- 输出: 20
myArray[5]()  -- 输出: This is a function

如果在数字下标表中某个索引位置没有存储任何值,Lua 会返回 nil

print(myArray[5])  --输出: nil 
9.1.3 添加元素

以下是几种常见的往数字下标表中添加元素的方法:

①直接赋值

可以直接通过索引赋值的方式往表中添加元素。

luaCopy codelocal myArray = {10, 20, 30}-- 直接赋值给新的索引位置
myArray[4] = 40
②使用 table.insert() 函数

可以使用 table.insert() 函数往数组末尾添加新元素。

luaCopy codelocal myArray = {10, 20, 30}-- 使用 table.insert() 函数往数组末尾添加新元素
table.insert(myArray, 40)
ps:table.insert()

table.insert (table, [pos,] value)

在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.

luaCopy codelocal myArray = {10, 20, 30}-- 使用 table.insert() 函数往数组第二个位置添加新元素
table.insert(myArray,2, 40)--myArray = {10, 40,20, 30}
③使用 # 操作符

可以使用 # 操作符来获取数组长度,然后在长度加一的位置赋值。

luaCopy codelocal myArray = {10, 20, 30}-- 在数组长度加一的位置赋值
myArray[#myArray + 1] = 40
9.1.4 删除元素
①使用 table.remove() 函数

table.remove() 函数用于删除数组中的元素。它接受两个参数:数组和要删除的元素的索引。删除元素后,后续的元素会向前移动填补空缺。如果不指定索引,则默认删除数组的最后一个元素。

luaCopy codelocal myArray = {10, 20, 30, 40}
table.remove(myArray)  -- 删除最后一个元素
luaCopy codelocal myArray = {10, 20, 30, 40}
table.remove(myArray, 2)  -- 删除索引为 2 的元素

第二个元素 20 将被删除,数组变成 {10, 30, 40}

ps:table.remove() 返回值

table.remove() 函数在删除元素后会返回被删除的元素的值。如果指定了要删除的元素的索引,则返回该索引位置上的元素值;如果没有指定索引,则默认删除数组的最后一个元素,并返回该元素的值。

local myArray = {10, 20, 30, 40}
local removedValue = table.remove(myArray, 2)  -- 删除索引为 2 的元素
print(removedValue)  -- 输出: 20
local myArray = {10, 20, 30, 40}
local removedValue = table.remove(myArray)  -- 删除数组的最后一个元素
print(removedValue)  -- 输出: 40
②将要删除的元素赋值为 nil

直接将要删除的元素的位置赋值为 nil,这会将该位置上的元素删除,但不会改变数组的长度或索引。

luaCopy codelocal myArray = {10, 20, 30, 40}
myArray[2] = nil  -- 删除索引为 2 的元素

在这个示例中,第二个元素 20 将被删除,数组变成 {10, nil, 30, 40}
注意:虽然元素被删除了,但数组长度仍然保持不变。

9.2 键值对

local myTable = {key1 = "value1", key2 = "value2"}
9.2.1 键值组成

在 Lua 中,表的键(key)和值(value)可以是任何类型的 Lua 值,包括但不限于:

  1. 字符串(string):可以作为键和值的类型,字符串是 Lua 中最常见的数据类型之一。
  2. 数字(number):同样可以作为键和值的类型,包括整数和浮点数。
  3. 布尔值(boolean):可以作为键和值的类型,表示逻辑上的真(true)和假(false)。
  4. 表(table):可以作为值的类型,允许嵌套表以构建复杂的数据结构。
  5. 函数(function):可以作为值的类型,表示可执行的代码块。
  6. 用户数据(userdata):一种特殊的数据类型,通常由 Lua 扩展库创建。
  7. 线程(thread):用于实现轻量级并发的数据类型,通常用于协程。
  8. nil:表示空值或无效值的特殊类型,可以作为键和值的类型。
local myTable = {["name"] = "John",               -- 字符串作为键[42] = "answer",                 -- 数字作为键[true] = "yes",                  -- 布尔值作为键[{}] = "empty table",            -- 表作为键[function() return "key" end] = "computed key",  -- 函数作为键["array"] = {1, 2, 3},           -- 数组作为值["nestedTable"] = {              -- 嵌套表作为值["key1"] = "value1",["key2"] = "value2"},["nilValue"] = nil               -- nil 作为值
}

Lua 中键和值可以不带方括号。当键是字符串或者符合 Lua 变量命名规则的标识符时,可以直接使用键名来定义键值对,而无需使用方括号

local myTable = {name = "John",               -- 字符串作为键age = 30,                    -- 字符串作为键isAdult = true,              -- 字符串作为键hobbies = {"reading", "swimming"}, -- 字符串作为键, 表作为值greet = function() print("Hello, Lua!") end,  -- 字符串作为键, 函数作为值
}
9.2.2 值访问

要访问 Lua 表中的值,可以使用下标(键)来获取对应的值。在 Lua 中,可以使用表的键来访问表中的值,这可以通过使用方括号加上键名或者直接使用键名来完成。

local myTable = {name = "John",age = 30,isAdult = true,hobbies = {"reading", "swimming"},greet = function() print("Hello, Lua!") end,
}-- 使用方括号加上键名来访问表中的值
print(myTable["name"])  -- 输出: John
print(myTable["age"])   -- 输出: 30-- 直接使用键名来访问表中的值
print(myTable.name)     -- 输出: John
print(myTable.age)      -- 输出: 30
9.2.3 添加元素

直接赋值

直接通过赋值操作来向表中添加新元素,如果键不存在,则会创建新的键值对

local myTable = {}  -- 创建一个空表-- 直接赋值给新的键
myTable["name"] = "John"
myTable["age"] = 30
9.2.4 删除元素

将要删除的元素赋值为 nil

local myTable = {name = "John", age = 30, city = "New York"}-- 删除键为 "age" 的整个键值对
myTable["age"] = nil
9.2.5 遍历元素

pairs() 遍历表中所有的键值对

pairs()的使用格式:

for key, value in pairs(table) do-- 在这里处理 key 和 value
end

其中,table 是要迭代的表,keyvalue 分别是每次迭代中表中的键和对应的值。

local myTable = {name = "John", age = 30, city = "New York"}for key, value in pairs(myTable) doprint(key, value)
end

相关文章:

Lua 零基础入门

Lua 1.Lua是什么&#xff1f; 1.1 Lua的历史 Lua是由Roberto Ierusalimschy、Luiz Henrique de Figueiredo和Waldemar Celes于1993年创建的&#xff0c;当时他们是巴西里约热内卢天主教大学计算机图形技术组&#xff08;Tecgraf&#xff09;的成员。在开发Lua之前&#xff0…...

记录DemoApplication.java不变蓝问题

问题 解决方案 一、点击右下角加载 二、右键项目 勾选maven...

22_Scala集合Seq

文章目录 Seq序列1.构建集合2.List集合元素拼接&&集合拼接3.可变Seq&&List3.1 ListBuffer创建3.2 增删改查3.3 相互转化 Appendix1.Scala起别名2.Seq底层3.关于运算符操作: :4.空集合的表示 Seq序列 –Seq表示有序&#xff0c;数据可重复的集合 1.构建集合 …...

机器学习初学者 6 个核心算法!建议收藏,反复观看!

今天再来介绍机器学习算法的基本概念和适用场景&#xff01; 首先&#xff0c;引用一句英国统计学家George E. P. Box的名言&#xff1a;All models are wrong, but some are useful. 没有哪一种算法能够适用所有情况&#xff0c;只有针对某一种问题更有用的算法。 也就是说&…...

SpringBoot 打包所有依赖

SpringBoot 项目打包的时候可以通过插件 spring-boot-maven-plugin 来 repackage 项目&#xff0c;使得打的包中包含所有依赖&#xff0c;可以直接运行。例如&#xff1a; <plugins><plugin><groupId>org.springframework.boot</groupId><artifact…...

QpushButton绘制圆角矩形并绘制背景颜色

要在QPushButton的paintEvent中绘制按钮的颜色&#xff0c;可以创建一个自定义的QPushButton类&#xff0c;并重写它的paintEvent函数。在paintEvent函数中&#xff0c;可以使用QPainter来绘制按钮的背景颜色。 以下是一个简单的示例代码&#xff0c;演示如何在自定义的QPushB…...

Core Impact 21.5 (Windows) - 高级渗透测试

Core Impact 21.5 (Windows) - 高级渗透测试 Fortra | Core Security Penetration testing software, Release Feb 2024 请访问原文链接&#xff1a;Core Impact 21.5 (Windows) - 高级渗透测试&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&…...

【Web前端】定位_浮动_音视频

1、定位 1.1想对定位 相对定位&#xff0c;使用relative&#xff0c;参考点是标签之前的位置&#xff0c;不是相对于父节点、同级节点或浏览器。相对定位通过left、right进行水平偏移&#xff0c;通过top、bottom进行垂直偏移Ieft:表示相对于原本位置的左外边界右移的距离rig…...

【Osek网络管理测试】[TG4_TC3]LimpHome状态下的睡眠中断

🙋‍♂️ 【Osek网络管理测试】系列💁‍♂️点击跳转 文章目录 1.环境搭建2.测试目的3.测试步骤4.预期结果5.测试结果1.环境搭建 硬件:VN1630 软件:CANoe 2.测试目的 验证DUT在LimpHome状态下的睡眠中断是否正确 分析:在跛脚运行状态下,满足睡眠条件后,进入到NM…...

【QT教程】QT6硬件数据库编程 QT硬件数据库

QT6硬件数据库编程 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C扩展开发视频课程 免费QT视频课程 您可以看免费1000个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免…...

unaipp推荐算法的汽车租赁系统zaxzu 微信小程序hbuiderx

随着现代汽车租赁管理的快速发展&#xff0c;可以说汽车租赁管理已经逐渐成为现代汽车租赁管理过程中最为重要的部分之一。但是一直以来我国传统的汽车租赁管理并没有建立一套完善的行之有效的汽车租赁管理系统&#xff0c;传统的汽车租赁管理已经无法适应高速发展&#xff0c;…...

STM32单片机中C语言的一些隐藏bug

必须类型一致的判断才能正常 double a-0.4; if(a < -0.2){print("低电平"); }这段代码可能未必如你所愿的运行. < 小于号的判断一定要类型一致, 尤其是牵扯到双精度类型的判断… 一定要保证符号 两边的数据类型一致才有可能得到你想要的结果. 代码里 -0.4 默认…...

车载测试到底怎么样?真实揭秘!

什么是车载智能系统测试&#xff1f; 车载智能系统&#xff0c;是汽车智能化重要的组成部分&#xff0c;由旧有的车载资通讯系统结合联网汽车技术所演进而来&#xff0c;随着软硬件技术的不断进步&#xff0c; 让车载智能系统拥有强大的运算能力及多元化的应用功能。 车载智能…...

RustGUI学习(iced)之小部件(八):如何使用svg部件显示矢量图形?

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第八篇,主要讲述svg矢量图形部件的使用,会结合实…...

gitlab设置保护分支

gitlab设置保护分支方法 进入代码仓库首页&#xff0c;找到settings下的repository并点击进入 找到Protected Branches 下的Exoand按钮&#xff0c;并点击展开 可以看到已经存在默认的保护分支&#xff0c;通常是master/main分支&#xff0c;也可以添加新的保护分支 新建保护分…...

五月加仓比特币

作者&#xff1a;Arthur Hayes Co-Founder of 100x. 编译&#xff1a;Liam 编者注&#xff1a;本文略有删减 (以下内容仅代表作者个人观点&#xff0c;不应作为投资决策的依据&#xff0c;也不应被视为参与投资交易的建议或意见&#xff09;。 从四月中旬到现在&#xff0c;当你…...

为什么需要归档和管理合同

归档和管理合同是非常重要的&#xff0c;主要有以下几个原因&#xff1a; 1. 法律合规性&#xff1a;公司需要遵守法律和监管要求&#xff0c;合同是法律文件&#xff0c;涉及公司的权益和责任。归档和管理合同可以确保公司遵守法律法规&#xff0c;合同的内容和执行过程都符合…...

什么是DMA? STM32如何配置DMA?

您好&#xff0c;我们一些喜欢嵌入式的朋友一起建立的一个技术交流平台&#xff0c;本着大家一起互相学习的心态而建立&#xff0c;不太成熟&#xff0c;希望志同道合的朋友一起来&#xff0c;抱歉打扰您了QQ群372991598 一、DMA简介 1、DMA简介 DMA(Direct Memory Access&a…...

交友软件源码-源码+搭建+售后,上线即可运营聊天交友源码 专业语聊交友app开发+源码搭建-快速上线

交友小程序源码是一种可以帮助开发者快速搭建交友类小程序的代码模板。它通常包括用户注册、登录、个人信息编辑、匹配推荐、好友聊天等常见功能&#xff0c;以及与后台数据交互的接口。使用这种源码可以极大地缩短开发时间&#xff0c;同时也可以根据自己的需求进行二次开发和…...

c++多线程2小时速成

简介 c多线程基础需要掌握这三个标准库的使用&#xff1a;std::thread,std::mutex, andstd::async。 1. Hello, world #include <iostream> #include <thread>void hello() { std::cout << "Hello Concurrent World!\n"; }int main() {std::th…...

大模型日报2024-05-09

大模型日报 2024-05-09 大模型资讯 NVIDIA推出VILA视觉语言模型&#xff0c;开启边缘AI 2.0时代 摘要: NVIDIA最新推出的VILA家族视觉语言模型代表了边缘AI 2.0的到来。这些模型具备高级视觉推理能力&#xff0c;能够在低功耗的边缘设备上运行&#xff0c;为各种应用带来更智能…...

QGraphicsView实现简易地图11『指定层级-定位坐标』

前文链接&#xff1a;QGraphicsView实现简易地图10『自适应窗口大小』 提供一个地图初始化函数&#xff0c;指定地图显示的中心点和地图缩放层级 能够让地图显示某一层级的瓦片&#xff0c;并将中心点坐标显示在视图中心。 1、动态演示效果 7级地图-大连-老虎滩 定位到 8级地图…...

UE5 蓝图入门

基础节点创建&#xff1a; 常量&#xff1a; 按住 1 &#xff0c;点击鼠标左键&#xff0c;创建常量 二维向量&#xff1a; 按住 2 &#xff0c;点击鼠标左键&#xff0c;创建二维向量 三维向量&#xff1a; 按住 3 &#xff0c;点击鼠标左键 乘法&#xff1a; 按住 m 键…...

英语单词学习

house of worship:宗教场所 dote: 喜爱 coffin:棺材 coffeine:咖啡因 expedient:权宜的 buster:破坏者 procrastinate: 拖延 gourmet:美食家 expound:阐述 narcissist:自我陶醉 assassinate:暗杀 salvage: 挽救 savage: 凶猛的 ulcer: 溃疡 obituary:讣告 arbitrary:武断的 abu…...

使用Python编写自动化测试代码规范整理

大家好&#xff0c;我们平时在写自动化测试脚本或者性能测试脚本时&#xff0c;需要注意代码规范&#xff0c;提高代码的可读性与维护性&#xff0c;之前给大家分享过pycharm的两个插件&#xff0c;大家可以参考&#xff1a;Pycharm代码规范与代码格式化插件安装 本文中主要从自…...

实验七 SJK数据库定义与操纵

实验题目 实验七 SJK数据库定义与操纵 实验时间 2023.5.17 实验地点 软件工程基础实验室 实验课时 2 实验目的 ​了解并掌握数据库定义与操纵的知识并能熟练应用 实验要求 ​熟练掌握和使用PL-SQL建立数据库基本表&#xff0c;使用PL/SQL developer操作数据库&a…...

Win10环境下yolov8快速配置与测试-详细

0.0 说明 参考黄家驹的Win10 环境下YOLO V8部署&#xff0c;遇到一些问题&#xff0c;并解决实现&#xff0c;记录如下: 斜线字体是原博客中的创作 0.1 参考链接 https://blog.csdn.net/m0_72734364/article/details/128865904 1 Windows10下yolov8 tensorrt模型加速部署 …...

C++面向对象学习笔记一

本文阅读下述文章&#xff0c;顺手记录学习《C面向对象程序设计》✍千处细节、万字总结&#xff08;建议收藏&#xff09;_c面向对象程序设计千处细节-CSDN博客 目录 前言 正文 浅拷贝和深拷贝 向函数传递对象 静态数据成员和静态成员函数 友元 友元函数 1、将非成员函数声明…...

C++容器之vector类

目录 1.vector的介绍及使用1.1vector的介绍1.2vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 空间增长问题1.2.4 vector 增删查改1.2.5vector 迭代器失效问题1.2.6 vector 在OJ中的使用。 2.vector深度剖析及模拟实现2.1 std::vector的核心框架接口…...

什么是MVCC?

MVCC是一种数据库的并发控制策略,就是为了解决多个用户同时访问数据库修改同一数据所造成的问题,如何解决这个问题了? 就是通过创建同一个数据的不同的版本,通过创建时间的不同,最后进行数据合并,其就不用给数据库上锁了,其实数据库的锁,虽然说InnoDB已经非常牛逼了,可以使用行…...

建站网址怎么改/最新黑帽seo教程

.NET牛人应该知道些什么&#xff1f;任何一个使用.NET的人描述线程与进程的区别&#xff1f; 什么是Windows服务&#xff0c;它的生命周期与标准的EXE程序有什么不同 Windows上的单个进程所能访问的最大内存量是多少&#xff1f;它与系统的最大虚拟内存一样吗&#xff1f;这对于…...

wordpress评论验证码插件/免费网站申请域名

...

江苏专业做网站的公司/临沂百度联系方式

1.前言 最近无意中看到了阮一峰大佬的关于数字签名的一个翻译&#xff08;数字签名是什么&#xff1f;&#xff0c;该篇文章的精髓在于评论内容&#xff09;&#xff0c;觉得对数字签名突然没有那么迷茫了&#xff0c;所以决定做一个学习笔记&#xff0c;以便以后回来查阅。 …...

网站如何做关键词优化/杭州网站优化推荐

remote-control 可以让用户通过外部接口控制应用程序音乐, 官方建议的做法是在View显示的时候接收remote-control事件 [c-sharp] view plaincopy - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[UIApplication sharedApplication…...

腾讯的网络营销模式/微博seo排名优化

《《转载》》今天刚刚搞明白这个问题&#xff0c;贴出来希望能给一些和我一样不是很懂的人一些参考&#xff0c;可惜的是我用的方法还不是特别方便&#xff0c;以后有了更好的方法会继续和大家分享的。这里我以一个经典的汉诺塔问题为例来进行说明。【问题描述】有三个塔分别标…...

做进行网站推广赚钱/深圳关键词排名优化系统

如&#xff1a;现有一张表名为trojans&#xff0c;其中others字段很多是重复的&#xff0c; 删除重复的记录语句如下&#xff1a; delete trojans from trojans , (select id from trojans GROUP by others having count(*)>1) as t2 where t2.idtrojans.id 这个语句一次只…...