优秀网站设计作品,网站设计现状,湖南专业seo公司,织梦免费自适应网站模板文章目录 Lua变量数据类型变量声明其他表示 Lua语法判断逻辑判断#xff08;Lua很特殊#xff0c;这个比较重要#xff09;短路判断 ifif else 循环whileforrepeat 迭代器泛型for迭代器无状态迭代器多状态的迭代器 Lua函数select方法 数组字符索引_G #xff08;不是教程Lua很特殊这个比较重要短路判断 ifif else 循环whileforrepeat 迭代器泛型for迭代器无状态迭代器多状态的迭代器 Lua函数select方法 数组字符索引_G 不是教程推荐有编程基础的人观看本文
文中主要包含了对菜鸟教程中的一些学习理解个人感觉Lua语言和Python很多地方相似
以下大部分代码和表格摘抄自菜鸟教程
function start()Lua变量
数据类型
数据类型描述nil只有值nil属于该类表示一个无效值在条件表达式中相当于false类似与Null或者Nonebooleanfalse和truenumber双精度浮点数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 a1, a1
print(a,b); -- 1 1而非1 2顺带一提Lua语句结束后也可以带分号
其他表示
a 0x11 -- 16进制表示,16117
b 2e10 -- 科学计数法,2*(10^10)
c 5^2 -- 乘方,25
d 5%2 -- 取余(mod),1
e 5//2 -- 整除运算,2 (lua5.3)
f 13 -- 移位符号(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只会返回逻辑值对应的变量的值
再举个例子让我们更好理解 例如anil值对应false所以a and b 返回了nil。而b0 值对应True,a or b返回了0
a nil -- false
d false -- falseB 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
false1
1
上述例子是正常计算都可以得出的现在让我们看几个特殊例子以下例子请抛弃依次执行语句的程序思维,使用更逻辑化,更符合计算机的思维来判断
a nil -- false
d false -- falseB 0 -- true
C 1 -- true
and时两侧都是真值则返回右侧的值
print(B and C)
print(C and B)
and时两侧都是假值则返回左侧的值
print(a and d)
print(d and a)
结果
1
0nil
falseor时两侧都是真值则返回左侧的值
print(B or C)
print(C or B)
or时两侧都是真值则返回右侧的值
print(d or a)
print(a or d)结果
0
1nil
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当前面为假则输出Bif
if(0)
thenprint(0 为 true)
endif else
a 100;
if( a 20 )
thenprint(a 小于 20 )
elseprint(a 大于 20 )
end
print(a 的值为 :, a) --a 大于 20 --a 的值为 : 100循环
while
break 关键字是通用是
while( a 20 )
doa a1
endfor
for i1,10,2 do --- 三个值依次代表起始,结束,步长,步长不输入默认为1print(i)
end repeat
a 10
repeat -- 不同与while for,repeat在循环结束时判断,类似do whileprint(a的值为:, a) --输出10,11,12,13,14,15a a 1
until( a 15 ) --当a16时退出最重要的知识点就是ifwhileforfunction都别忘了加end 迭代器
泛型for迭代器
迭代器类似C#的for eachpython的for in
array {Google, Runoob}for key,value in ipairs(array) -- key,value自定义常量名,ipairs(array)迭代列表
doprint(key, value)
end1 Google
2 Runoob无状态迭代器
function square(iteratorMaxCount,currentNumber)if currentNumberiteratorMaxCountthencurrentNumber currentNumber1return currentNumber, currentNumber*currentNumberend
end
--定义了一个方法square实现循环三次后结束for i,n in square,3,0 --square,3,0代表了迭代方法和它的两个入参,当方法结束主动闭包
doprint(i,n)
end1 1
2 4
3 9多状态的迭代器
如果迭代函数需要接收很多信息为了简化迭代函数的入参不妨将所有的状态信息封装到 table 内将 table 作为迭代器的状态常量因为这种情况下可以将所有的信息存放在 table 内所以迭代函数通常不需要第二个参数。
array {Google, Runoob}function elementIterator (collection)local index 0local count #collection-- 闭包函数return function ()index index 1if index countthen-- 返回迭代器的当前元素return collection[index]endend
endfor element in elementIterator(array)
doprint(element)
endGoogle
Runoob需要注意无论定义什么函数最后都需要该函数return给迭代变量才能在迭代器中最终输出对应的值 Lua函数
几个简单的例子一步到位
----------------------
function f() --同样未用local声明,该函数为全局函数a,b1,2 -- 函数内定义没有local声明也是全局变量print(a,b)
endf() -- 1 2
--------------------
local function f(a,b,n) --local声明后为局部函数c, d a, bprint(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 0local arg{...} -- arg 为一个table局部变量for i,v in ipairs(arg) do result result vendprint(总共传入 .. #arg .. 个数)print(总共传入 .. select(#,...) .. 个数) --select(#,...)来获取可变参数的数量,和直接#arg功能是一样的return result/#arg
endprint(平均值为,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存储了好多奇怪的值其中包括numberstringtable甚至两个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,d123456,[!?] 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