【Lua学习笔记】Lua入门

在这里插入图片描述

文章目录

  • Lua变量
    • 数据类型
    • 变量声明
    • 其他表示
  • Lua语法
    • 判断
      • 逻辑判断(Lua很特殊,这个比较重要)
        • 短路判断
      • if
      • if else
    • 循环
      • while
      • for
      • repeat
    • 迭代器
      • 泛型for迭代器
      • 无状态迭代器
      • 多状态的迭代器
  • Lua函数
    • select方法
  • 数组
    • 字符索引
    • _G

(不是教程,推荐有编程基础的人观看本文)

文中主要包含了对菜鸟教程中的一些学习理解,个人感觉Lua语言和Python很多地方相似

以下大部分代码和表格摘抄自菜鸟教程

function start()

Lua变量

数据类型

数据类型描述
nil只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)(类似与Null或者None)
booleanfalse和true
number双精度浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序(那你为啥叫线程?)
tableLua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

变量声明

a = 5               -- 全局变量
local b = 5         -- 局部变量

在Lua中,使用local显示声明该变量为局部变量,而不声明的都是全局变量。

a               -- nil
a = 5               -- number
a = false         -- bool
a = ""         -- string,单双引号都可以,支持转义字符,print出空字符串而非nil
在lua中字符串尾部没有\0,而且\0即使在字符串中也不代表结束且不计入长度
我们也可以用16进制来定义字符串
s = string.char(0x30,0x31)
n = string.byte(s,2)  --转为Ascii码,第一个字符是从1开始的而非0
print(s,n)     --结果: 01  49
a,b,c = 1,"a"         -- 多重赋值
print(a, b, c)         -- 1  a  nil
a = nil			 -- nil,回收变量
local multilineString = [[
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.
]]
print(multilineString)    -- 按格式输出括号内字符
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.

不管定义整形还是浮点型,在Lua中都是number。而没有赋值的变量都是nil。有趣的是,即使赋值了空字符串依然是string类型,看来Lua中nil应当和C差不多,代表了基址未赋值。

Lua 对多个变量同时赋值,不会进行变量传递,仅做值传递:

a, b = 0, 1
a, b = a+1, a+1
print(a,b);               --> 1   1而非1	  2

顺带一提,Lua语句结束后也可以带分号

其他表示

a = 0x11    -- 16进制表示,16+1=17
b = 2e10    -- 科学计数法,2*(10^10)
c = 5^2		-- 乘方,25
d = 5%2		-- 取余(mod),1
e = 5//2		-- 整除运算,2 (>=lua5.3)
f = 1<<3	-- 移位符号(>=lua5.3),二进制表示下移位:1 = 00000001左移三位(000)00001000 = 8
a,b = "abc","def"
c= a..b  --字符串连接,"abcdef"
print(#c) --#输出变量长度(可以是字符串或者表),6
-- 其他语法例如tostring(number),tonumber(string)都是很常规的
n = tonumber("a")   --nil,需要注意的是lua和cpp不同,单个字符也不会转为ASCII码

Lua语法

判断

逻辑判断(Lua很特殊,这个比较重要)

Lua认为false和nil为假,true和非nil为真,所以0代表也是真。
唯一需要注意的是Lua中不等于为 ~=
与或非分别是 and or not
让我们看看下面的例子:

a = nil -- false
b = 0  -- true
print(a and b)
print(a or b)
print(not a)

nil
0
true

可以看到,在Lua中常规的逻辑判断并不会返回True或者False,只有在not判断下才会返回True和False,而and和or只会返回逻辑值对应的变量的值

再举个例子让我们更好理解
(例如a=nil,值对应false,所以a and b 返回了nil。而b=0 值对应True,a or b返回了0)

a = nil -- false
d = false -- false

B = 0   -- true
C = 1   -- true
and时一真一假输出结果是false的一方
print(a and C) --逻辑判断值返回了逻辑符号左右值中的对应真值和假值
print(C and d)
or时一真一假输出结果是true的一方
print(a or C)
print(C or d)

结果:
nil
false

1
1
上述例子是正常计算都可以得出的,现在让我们看几个特殊例子
以下例子请抛弃依次执行语句的程序思维,使用更逻辑化,更符合计算机的思维来判断
a = nil -- false
d = false -- false

B = 0   -- true
C = 1   -- true
and时两侧都是真值,则返回右侧的值
print(B and C)
print(C and B)
and时两侧都是假值,则返回左侧的值
print(a and d)
print(d and a)
结果:
1
0

nil
false

or时两侧都是真值,则返回左侧的值
print(B or C)
print(C or B)
or时两侧都是真值,则返回右侧的值
print(d or a)
print(a or d)

结果:
0
1

nil
false

为什么是这样的?也许从程序的思维来看,我们需要执行语句,然后判断。但是实现一个逻辑门判断,有时只需要逻辑符号和其中一个值就够了

接下来用T代表真,F代表假,?代表任意bool
print(F and ?)
在进行and运算的时候,如果第一个值就为false,那输出值一定为false,?是什么都不影响了,所以结果一定为false,输出F即可
print(T and ?)
在进行and运算的时候,如果第一个值为true,我们依然无法确定输出值,此时我们需要知道?是true还是false
但是最后的运算结果一定是由?决定的,如果?为true运算就是true,问号为false运算就是false,所以and左值为真时,输出的结果一定是右值
因此该语句会输出 ?
print(T or ?)
同理,or运算中如果左值为true,结果一定为true,因此输出T即可
print(F or ?)
or运算中如果左值为false,最后结果则是由?是true还是false决定,因此输出结果一定是右值
上述语句输出 ? 

现在再回头看看刚才的例子,是不是能理解了?

短路判断

基于上述的原理我们可以进行短路判断
a = nil -- false
b = 0  -- true
print(b > 10 and "yes" or "no")

输出:
no

所以所谓短路判断,前面应当是正常的判断语句,最后加上and A or B,其中AB都是true值
【T and A or B = A, F and A or B =B】
当前面为真则输出A,当前面为假则输出B

if

if(0)
then
    print("0 为 true")
end

if else

a = 100;
if( a < 20 )
then
   print("a 小于 20" )
else
   print("a 大于 20" )
end
print("a 的值为 :", a)  --a 大于 20 
					    --a 的值为 :    100

循环

while

break 关键字是通用是

while( a < 20 )
do
   a = a+1
end

for

for i=1,10,2 do  --- 三个值依次代表起始,结束,步长,步长不输入默认为1
    print(i)
end 

repeat

a = 10
repeat  -- 不同与while for,repeat在循环结束时判断,类似do while
   print("a的值为:", a) --输出10,11,12,13,14,15
   a = a + 1
until( a > 15 ) --当a=16时退出

最重要的知识点就是if,while,for,function都别忘了加end


迭代器

泛型for迭代器

迭代器类似C#的for each,python的for in

array = {"Google", "Runoob"}

for key,value in ipairs(array)  -- key,value自定义常量名,ipairs(array)迭代列表
do
   print(key, value)
end

1  Google
2  Runoob

无状态迭代器

function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end
--定义了一个方法square实现循环三次后结束

for i,n in square,3,0  --square,3,0代表了迭代方法和它的两个入参,当方法结束主动闭包
do
   print(i,n)
end

1    1
2    4
3    9

多状态的迭代器

如果迭代函数需要接收很多信息,为了简化迭代函数的入参,不妨将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。

array = {"Google", "Runoob"}

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

for element in elementIterator(array)
do
   print(element)
end

Google
Runoob

需要注意:无论定义什么函数,最后都需要该函数return给迭代变量,才能在迭代器中最终输出对应的值


Lua函数

几个简单的例子,一步到位

----------------------
function f()  --同样未用local声明,该函数为全局函数
	a,b=1,2   --  函数内定义没有local声明也是全局变量
	print(a,b)
end

f()		-- 1  2
--------------------
local function f(a,b,n)  --local声明后为局部函数
    c, d = a, b
    print(c, d,n)
end
f(1,2)		-- 1  2  nil
-------多返回值--------------------
function f(a,b,c)
	return a,b,c
end
local i,j =f(1,2)
print(i,j)		-- 1  2
--------可变参数---------------
function average(...)  --使用...可以接收任意多参数
   result = 0
   local arg={...}    --> arg 为一个table,局部变量
   for i,v in ipairs(arg) do 
      result = result + v
   end
   print("总共传入 " .. #arg .. " 个数")
   print("总共传入 " .. select("#",...) .. " 个数")   --select("#",...)来获取可变参数的数量,和直接#arg功能是一样的
   return result/#arg
end

print("平均值为",average(10,5,3,4,5,6))
---总共传入 6 个数
---总共传入 6 个数
---平均值为    5.5
-----------
function average(a,...)  --也可以用固定参数+可变参数,但是固定参数一定放在可变参数之前
end
------------------------

select方法

通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select(‘#’, …) 或者 select(n, …)

select(‘#’, …) 返回可变参数的长度。
select(n, …) 用于返回从起点 n 开始到结束位置的所有参数列表。
调用 select 时,必须传入一个固定实参 selector(选择开关) 和一系列变长参数。如果 selector 为数字 n,那么 select 返回参数列表中从索引 n 开始到结束位置的所有参数列表,否则只能为字符串 #,这样 select 返回变长参数的总数。

function cal_sum(...)
    a,b =select(3,...)
    print(select(3, ...))
    print(select("#",...) )
end
cal_sum(1,2,3,nil,5,5)
print(a,b)

3	nil	5	5
6
3	nil

使用select赋值会对变量顺序赋值,而select本身可以获取序号及其后的所有可变参数

数组

Lua中没有传统意义的单一类型的数据结构,只有一种table结构,它能顺序存放里面的所有值,并提供了索引以供访问。

需要注意的是,索引是从 1 开始而非传统的0

function P ()
    return 1;
end
a={1,"ac",{},function() end,P}
print(a[3])
print(a[4])
print(a[5])
print(#a)
a[6] = 1223;
print(a[6])
print(#a)

结果:
table: 00BCA580
function: 00BCCAC8
function: 00BCCC48
5
1223
6

我们发现上述table存储了好多奇怪的值,其中包括number,string,table甚至两个function。

通过输出结果我们发现,对于常见的变量类型,table索引可以直接返回值。而对于table function等非常规类型则返回了存储类型+存储地址。

-- insert用法,没有返回值
table.insert(a, "d") --插入到尾部
print(a[7])
s = table.insert(a, 2, 233) --插入到位置2,其后的元素都会后移一位
print(s)
print(a[2])

d
nil
233
-- remove会有返回值
s = table.remove(a, 1)
print(s)
print(a[1])

1
ac

字符索引

table可以以字符作为索引:

a = {
    a = 1,
    b = "1234",
    c = function()
    end,
    d=123456,
    ["!?"] =123
}
a["abc"]="abc"
print(a["a"])
print(a.a)
print(a["!?"])   -- 这只是个例子,别用奇怪的符号命名
-- print(a.!?)   --打印不了的,符号会报错
print(a.abc)
print(a.def)    --没有这个下标

1
1
123
abc
nil

在这里插入图片描述
在这里插入图片描述

不难发现其实table内是以键值对形式存储的


_G

_G是一个全局table,它储存了所有的全局变量,我们可以通过它来访问任意全局变量

a = 1
b = 2
print(_G["a"])
print(_G.b)

1
2

如果上面的还能理解,以下特性简直就是奇葩了

之前我们往tableA里不是使用table.insert插入了一个值吗?让我们看看怎么实现的

table.insert(table, 1, "aa") 
- lua内有一个全局变量,它的名字就叫table,它的类型是table
- 我们可以直接使用table.insert的原因其实是直接访问了这个名称为table的table的一个字符串索引
- 这个字符串索引的名称是"insert",这个索引对应的值是一个function
- 这个函数实现了往指定table的指定位置插入指定值的功能
print(table[1])
print(_G["table"]["insert"])

输出:
aa
function: 00CE8B48

结束语:别忘了

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/50355.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

13、PHP面向对象2(方法的访问控制、子类继承、常量)

1、类中的方法可以被定义为公有&#xff0c;私有或受保护。如果没有设置这些关键字&#xff0c;则该方法默认为公有。 public定义的方法&#xff0c;可以在类外使用。 protected定义的方法&#xff0c;只能在本类或子类的定义内使用。 private定义的方法&#xff0c;只能在本…

【Java中间件】RocketMQ

RocketMQ 一、MQ概述 Message Queue&#xff0c;是一种提供消息队列服务的中间件。提供了消息生产、存储、消费全过程API的软件系统。 MQ的作用 限流削峰&#xff1a;当用户发送超量请求时&#xff0c;将请求暂存&#xff0c;以便后期慢慢处理。如果不使用MQ暂存直接请求到…

win10系统wps无法启动(打开文档)

我的win10系统中&#xff0c;之前可以顺畅地打开wps&#xff0c;但最近无法打开文档&#xff0c;停留在启动页面&#xff0c;在任务管理器中可以看到启动的wps线程&#xff0c;如果继续双击文档&#xff0c;线程增加&#xff0c;但依然无法打开文档。 wps版本是刚刚更新的15120…

用于提取数据的三个开源NLP工具

开发人员和数据科学家使用生成式AI和大语言模型&#xff08;LLM&#xff09;来查询大量文档和非结构化数据。开源LLM包括Dolly 2.0、EleutherAI Pythia、Meta AI LLaMa和StabilityLM等&#xff0c;它们都是尝试人工智能的起点&#xff0c;可以接受自然语言提示&#xff0c;生成…

3dsmax制作一个机器人

文章目录 建模身子&#xff1a;眼睛&#xff1a;头饰&#xff1a;肩膀手臂腿调整细节 渲染导出objMarmoset Toolbag 3.08渲染给眼睛添加材质&#xff0c;设置为自发光添加背景灯光 建模 身子&#xff1a; 眼睛&#xff1a; 头饰&#xff1a; 肩膀 手臂 腿 调整细节 渲染 导出…

k8s核心概念

一、集群架构与组件 1&#xff0c;相关组件 【1】 master node三个组件 k8s的控制节点&#xff0c;对集群进行调度管理&#xff0c;接受集群外用户去集群操作请求master node 组成&#xff08;四个组件&#xff09;&#xff1a;控制面 API Server&#xff1a;通信kube-Sche…

路由的配置

1、在router中设置路由导航跳转函数,在index.js文件中写这句话&#xff1a; 1.1 只要发生跳转, 就会调用这个函数&#xff1a; 1.2 导航的声明函数 2、访问系统访问控制系统如何形成 3、来一个导航守卫的案例&#xff1a;看看导航守卫的案例&#xff0c;写一个Main.Vue 和login…

结构型设计模式:装饰器模式

设计模式专栏目录 创建型设计模式-单例模式/工厂模式/抽象工厂 行为型设计模式&#xff1a;模板设计模式/观察者设计模式/策略设计模式 结构型设计模式&#xff1a;装饰器模式 C#反射机制实现开闭原则的简单工厂模式 目录 设计模式专栏目录设计模式分类设计模式的设计原则装饰…

Spring Boot——Spring Boot启动原理

系列文章目录 Spring Boot启动原理 系列文章目录一、Spring Boot启动的宏观流程图二、Spring Boot启动流程2.1 初始化new SpringApplication2.1.1Spring Boot入口2.1.2初始化SpringApplication2.1.2.1判断当前应用程序类型2.1.2.2设置应用程序的所有初始化器(initializers)2.1.…

Lab———Git使用指北

Lab———Git使用指北 &#x1f916;:使用IDEA Git插件实际工作流程 &#x1f4a1; 本文从实际使用的角度出发&#xff0c;以IDEA Git插件为基本讲述了如果使用IDEA的Git插件来解决实际开发中的协作开发问题。本文从 远程仓库中拉取项目&#xff0c;在本地分支进行开发&#x…

OpenCvSharp (C# OpenCV) 二维码畸变矫正--基于透视变换(附源码)

导读 本文主要介绍如何使用OpenCvSharp中的透视变换来实现二维码的畸变矫正。 由于CSDN文章中贴二维码会导致显示失败,大家可以直接点下面链接查看图片: C# OpenCV实现二维码畸变矫正--基于透视变换 (详细步骤 + 代码) 实现步骤 讲解实现步骤之前先看下效果(左边是原图,右边…

CSS 瀑布流效果效果

示例 <!DOCTYPE html> <html lang="cn"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>瀑布流效果</title><style>…

Windows安装PyTorch

文章目录 前言CPU版本安装安装步骤测试CPU版PyTorch是否安装成功 GPU版本安装新建一个conda环境安装torch法一&#xff1a;在线安装(建议用法二)法二&#xff1a;下载torch、torchvision后本地安装(建议使用此方法)Jupyter Lab虚拟环境的配置测试是否安装成功 前言 此份文档适…

Java 版 spring cloud +spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

【JavaEE初阶】HTTP请求的构造及HTTPS

文章目录 1.HTTP请求的构造1.1 from表单请求构造1.2 ajax构造HTTP请求1.3 Postman的使用 2. HTTPS2.1 什么是HTTPS?2.2 HTTPS中的加密机制(SSL/TLS)2.2.1 HTTP的安全问题2.2.2 对称加密2.2.3 非对称加密2.2.3 中间人问题2.2.5 证书 1.HTTP请求的构造 常见的构造HTTP 请求的方…

EMO:重新思考高效的基于注意力的移动块模型

文章目录 摘要1、介绍2、方法论:归纳法和演绎法2.1、通用效率模型标准2.2、元移动块2.3、微设计:倒置残余移动块2.4、面向密集预测的EMO宏观设计 3、实验3.1、图像分类3.2、下游任务3.3、额外的消融和解释分析 4、相关工作5、结束语及未来工作 摘要 论文链接&#xff1a;https…

Ubuntu更改虚拟机网段(改成桥接模式无法连接网络)

因为工作需要&#xff0c;一开始在安装vmware和虚拟机时&#xff0c;是用的Nat网络。 现在需要修改虚拟机网段&#xff0c;把ip设置成和Windows端同一网段&#xff0c;我们就要去使用桥接模式。 环境&#xff1a; Windows10、Ubuntu20.04虚拟机编辑里打开虚拟网络编辑器&#…

在Mac上搭建Gradle环境

在Mac上搭建Gradle环境&#xff1a; 步骤1&#xff1a;下载并安装Java开发工具包&#xff08;JDK&#xff09; Gradle运行需要Java开发工具包&#xff08;JDK&#xff09;。您可以从Oracle官网下载适合您的操作系统版本的JDK。请按照以下步骤进行操作&#xff1a; 打开浏览器…

520 · 一致性哈希 II

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; class Solution{private:int n;const int mVirtualNodeCount;map<int, int> mVirtualNodeToMachineIdMap;set<int> mVirtualNodeSet;public:Solution(int n…

SpringBoot房屋租赁系统【附ppt|万字文档(LW)和搭建文档】

主要功能 前台登录&#xff1a; ①首页&#xff1a;公告信息、房屋信息展示、查看更多等 ②房屋信息、房屋类型、我要当房主、公告信息、留言反馈等 ③个人中心&#xff1a;可以查看自己的信息、更新图片、更新信息、退出登录、我的收藏 后台登录&#xff1a; ①首页、个人中心…