加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Lua 学习笔记

发布时间:2020-12-14 22:07:26 所属栏目:大数据 来源:网络整理
导读:Lua 脚本 一、Lua 简介 1.1 lua 解释器,luac 编译器 lua 参数: -i ? 进入交互模式 -e 执行单语句 -l 加载库文件? example: lua -i -l math -e "print(math.sin(20))" lua -i -e "_PROMPT='lua'" 1.2. lua 解释器模式下, 执行文件 ?dofile("example.lua");
Lua 脚本 一、Lua 简介 1.1 lua 解释器,luac 编译器 lua 参数: -i ? 进入交互模式 -e 执行单语句 -l 加载库文件? example: lua -i -l math -e "print(math.sin(20))" lua -i -e "_PROMPT='lua>'" 1.2. lua 解释器模式下, 执行文件 ?dofile("example.lua"); 该模式下接受一个完整的程序块 chunk 1.3. 注释 1) 行注释 --这是注释 2) 块注释 --[[ 这里被注释了 --]] 或 --[[ 这里被注释了 ]] 在 --[[ 多加一个减号。就变成了行注释 ---[[ 这里没有注释,会报错 --]] 1.4. 命令行参数table表,解释器在运行的时候会把所有的命令行参数作 为值,创建一个名称为arg的table。脚本名称位于索引0上,它的第一个 参数位于索引1上,脚本之前的所有参数位于负数索引上 1.5. = 输出 lua> = math.sin(3) -->0.14112000805987 1.6. 环境变量 1)LUA_INIT? lua解释器在执行之前会先检查LUA_INIT环境变量,如果该环境变量存 在,则将解释器会先执行该 环境变量所标识的值。该值可以是一个lua语 句,也可以是一个以 @file.lua 的lua 文件 2) LUA_PATH 1.7. 全局变量 lua 中全局变量不需要声明,直接使用一个没有声明的变量。则认为该 变量为全局变量。全局变量若不用了,最后赋值为nil,全局变量的生命周期 为 ??? 所有的全局变量都是存储在一个table表中 1.8. lua 动态类型语言。没有类型定义的语法。变量值"自带"了类型信息 1.9. 词法规范 1) 标识符,以任意字母、数字和下划线组成,且不能以数字开头。 注意:Lua 中的字母,由locale 区域设置决定。可以是拉丁字母或者 其它语系的字母 2)保留标识符,lua 中通常将以一个下划线开头并后跟大写字母的标识 符作为哑变量。 例如_VERSION _PROMPT 3)Lua 中的保留关键字。 and break do else elseif end false for function if in local nil not or repeat return then true until while ? 4)Lua 区分大小写 1.10 Lua 的所有标准库都是用C写的 1.11 misc tonumber() ? 只能处理 纯数字的字符串 tonumber("123c") nil tonumber("-123") -123 tonumber("+123") 123 二、类型与值 2.1. lua 中的变量类型 ? bool number string nil userdata(自定义类型) function table thread type(1) 输出类型的函数。--> number? 该 函数输出的永远是字符串。 print(type(type(x))) ?无论x 为任何类型的值,输出都为string 2.2. nil 类型只有一个值 nil ? ?只有false 和 nil 才为false,其它都为 ture.注意:0和空字符串都 ? 为ture 2.3. lua 中的数值类型 number。 在lua 中没有整型,整型和浮点型都用number.number 可以表示任何 32位整数。 b = 3.1415 ? ?<===> 0.31415e1 可以通过修改luaconfig.c文件中定义来修改用long 或 float 来表示 一个number ??? 2.4. string类型 1)lua 中的字符串是不能修改的,如果要修改一个字符串,则需要重新 创建一新的字符串。lua 自动管理字串串内存的释放 字面字符串, 使用 单引号,或双引号括起来的字符串。 'hello world' ? "do go go" string.gsub("one string","one","another") 注意:lua 能高效的处理长字符串 2).. 字符串连接符 print(10..20) a = 10 b = "hello" c = a .. b print(c) 10hello ? TODO:字符串的各种使用 ??? 3)字符 &;ddd> 十进制 ?一次读3个数字,或者遇到非数字终止 转义字符,? 同C语言中的差不多。 str = "hellonworld!" 2.5 table 表 Lua 中唯一的数据结构机制 1.特点: a.无大小限制 b.关联式数组 c.key 值可以是number 也可以是 string,并且不需要key值为同 一类型。 d.使用之前必须构造。 注意:table表变量不同于number和string 可以直接使用,table必须使用构造表达式{} ?构造之后才可以使用。 e:只有table的变量和 该变量的引用没有固定的关联性。也就是说 表单a 作为值,给b赋值赋值之后,a=nil b 也不会为空。可以将table 表单理解为在动态内存中分配的一个空间, a = {} a[3] = 4 a["3"] = 3 b = a a = nil --表单b依然是原来的值? 2. 当table 没有任何引用时,Lua垃圾回收器会自动回收table所占 内存。当table的 key 值为 字符串时,可以使用 Lua 提供了语法糖简 便的来表示。例如 ? a["name"] ?<==> a.name 3. #长度操作符 #长度操作符,返回数组或线性表最大索引值。 长度操作符是根据 nil 来界定table大小的。因此当table中 间有nil值时,通过#操作符获得的长度将是错误的。 4. table 最多正数 key值 table.maxn(a) 可以获得 table的最多正索引数 2.6 userdaata结构 自定义类型,它可以将任意类型的C语言数据都存储到Lua 变量中。 它用于表示,一种由应用程序或C语言库所创建的新类型。 三、操作符和表达式 3.1. 算数操作符 二元: + - * / % : 和C 语言中的取模不同,这里支持实数 【****】 例如 3.141592653 % 0.01 == 3.14 ^(指数) ? ?3^0.5 ? 右结合 【*】? 一元: - 3.2. 逻辑表达式 二元: and 或 or 与 一元 not 非 example:? 1) not 运算符永远返回ture 或 false print(not nil) -->ture print(not false) -->ture 2) and or 表达式返回的结果: 终止该表达式的那个操作数结果 a and b --> 如果 a 为 真 ?b 为 假, 返回 b,a 假 返回 a ;a 真 b假 返回 b a ?or b -->同上 3) a and b or c 类型 a ? b:c 前提 b 必须为真,否则 a =ture b = false 则返回 c? 3.3. 关系表达式 < 小于 > 大于 <= 小于等于 >= 大于等于 ~= 不等于 1)关系运算符永远只返回true false 2)只有 number 和 string 才有 相等测试以外的运算 3)不同类型的值,不知允许做相等性测试 4) nil 等于 nil 5) table、userdata 和函数,只比较引用,并且不能做非相等性比较 6) string 类型的值在比较傲时,采用字母次序进行比较。这依赖于 解释器的区域设置。 example: 2 < "15" 非法表达式 "2" < "15" false a = {} a.x = 1 a.y = 0 b = {} b.x = 1 b.y = 0 c = a a == b false 只做引用比较 b == c false 只做引用比较 a == c ture 只做引用比较 3.4 运算符的优先级问题 ^ > 一元操作符 > 算数操作符 > .. > 关系操作符 ? > and > or .. 和 ^ 右结合 其他的都是 左结合 3.5 table 构造式 1. 空构造式 a = {} 2. 记录风格构造式 ?下标从 1开始 a = {"Sunday","Monday","Thuesday","Wednesday",? "Thursday","Friday","Saturday"} 3. 列表风格式构造式 a = { x = 3,y = 4,z = 5} 字段名称为标识符,也就是字符串 4. 二者混合风格 a = { x = 3,z = 5,{color="blue",px=1},-- key == 1 {color="red",-- key == 2 {color="green",px=1} -- key == 3 } 这种情况下,没有指定key , 从第一没有指定Key值得value开始 key 从 1 开始累加,如果指定的key 值与默认的重复,丢弃指定的 以上三种构造式,key 值都不允许使用 算数运算符,也不允许 出现负数。运行符(+ - * / 等等)也不能用 a = {} 5. 包含运算的构造式 [] s = 3 a = {["+"] = "add",1,2,[s] = 3} 注意:当默认的table下标 同 构造式中指定的下标冲突时,解释 器只认默认的下标。如过在构造式中,指定了两个相同的key 值,则第 二个key值所代表的值,会覆盖掉第一个值 example: a = {1,3,[1] = 10} print(a[1]) --> 1 注意不是 10 a = {x= 3,x = 5} print(a.x) --> 5 注意和上面的区别 --综合应用 example: local str = "" local i = 10 b = { 1,? [i] = 10,? 4,5,6,? [i] = 50,? [i-3] = 7,? [i-2] = 8,? [i-1] = 9 } for i = 1,10 do str = str .. " " .. b[i] end print(str) --> 1 2 3 4 5 6 7 8 9 50 3.6 位运算 ??? 四、语句和控制结构 4.1 赋值语句 1. 单个变量赋值 a = 12 str = "Hello" .. " " .. "World" 2. 多重赋值 【***】 将多个值,赋给多个变量; 解释器先对等号右边的表达式求值,然后 在依次赋值 多重赋值的执行效率并不比 普通的单个变量赋值要快。多重赋值主要 用在函数返回多个值时。 在赋值的时候,解释器总是会让右边的值个数等于左边变量的个数。当 值多余变量个数时,多余的值会被丢弃;当值得个数少于变量个数时,缺少 的值,会用nil替代 a = 1 b = 2 a,b = b,a -- 这样可以交换两个变量的值 a,b,c = 1,3 a,2 --> c = nil 4.2 分支语句 if end if else end if elseif else end 4.3 循环语句 循环语句 终止语句 break。? 需要特别注意的是,在循环的时候是不要修改 控制变量的值,这样会 导致不可以预测的结果。 ?【***】 1. for for 循环有两种形式,一种是 数字型for ; 一种是 泛型for 1) 数字型for for var = initValue,endValue,step do ... end 说明:? a) step 可以省略,默认步长为 1; b) 起始值和终止值,都是闭合的 [initValue,endValue] c) 如果不希望设置一个上限,可用 math.huge 常量,这样 会导致无限循环 d) initValue,step 可以是表达式,但是该表达 式只会计算一次。 example: local i = 2 --不声明就会使用一个全局的 i for i = 1,-- 最后执行 i * 100,-- 先计算 这部分 i * 2 -- 再计算 这部分 do? print(i) end 等价于 for ?i = 1,200,4 do print(i) end 2) 泛型for 泛型for 是通过迭代器来实现的,Lua 基础库中提供了几种常用的 迭代器。? a) ipairs 迭代数组 ??? for i,v in ipairs(a) do? print(v) end b) pairs 迭代table for k in pairs(t) do print(k) -- 打印t 中所有的Key值 end for k,v in pairs(t) do print(k,v) -- 打印t 中所有的元素 end ipairs 和 pairs 的区别: ??? c) io.lines 迭代文件每一行 d)string.gmatch 迭代字符串中单词 2. while while condition do ... end 3. repeat repeat ... until condition 这种结构类似于C 中的 do ..while() 4.4 变量作用域和 程序块 1. 局部变量 使用local声明的变量,为局部变量 作用域:声明的程序块、函数体、控制结构的执行体 注意:Lua 中在同一个程序块中允许相同名称而作用域不同的变量,应尽量使用局部变量;多余的全局变量会使程序混乱;并且程序也 会浪费内存空间;还有访问全局变量的速度要比访问局部变量的要 慢。 local foo = foo -->将全局变量的foo值赋给局部变量foo 这样做的目的,当前全局foo改变时,不影响当前程序快;还有访问 速度要快 2. 全局变量 全局变量被赋nil 值后,消失 3. do end do end 可以显示的表示一个程序块 4.5 break 、return 【***】 1)这两个语句,不同于 中的 break 和 return 。由于Lua 语法构造的 原因,bread/return 都必须处在结束(break为循环体的结束位置、return? 为函数的结束,或者 break的结束位置)的位置,后面不允许有其他语句。 example: function foo()? while ture do break print("Hello World!") -- 不合法 end return print("return") -- 不合法 end 2)没有函数的结束处都有默认的return 语句,所以在没有返回值的 情况下不需要t添加return语句 3) do return / break end 可以解除 第一条的限制 example: function foo()? while ture do do break end print("Hello World!") -- 合法 end do? return end print("return") -- 合法 end 五、函数和模块 5.1.函数 1. 函数定义 -- 全局函数声明 function funcName(argList...) ... -- 完成特定工作的一系列语句 end -- 局部函数声明, 并且只能在定义的时候声明 local function funcName(argList...) ... -- 完成特定工作的一系列语句 end 说明:声明为局部的函数,只能在声明时的那个块内调用 2. 函数的调用 func() 当函数值只有一个参数,且这个参数是字面字符串,或者table构造 式时,可以不使用圆括号。 -- 参数用两个中括号括起来的,[[字面字符串,可以写成多行]] print [[ a mutil-line? message]] print "hello world" print ("hello world") -- table 构造式做参数的时候可以省略 圆括号 func{x=1,y=2} 3. 参数 1)形参列表 2) 实参列表 在函数调用的时候,允许实参列表的参数个数同形参列表的个数不同, 解释器会自动调整个数。规则:多了丢弃、少了nil替代 3) 具名实参 使用具名实参的必要条件: a) 只有一个参数 b) 使用Lua 特殊的函数调用语法 rename{} 大括号 原理:具名实参,实际上是利用table的特性来实现的。table的 列表风格式构造式,可以指定table中字段的名称。 example: -- 矩形? function rect(arg) return arg.x,arg.y,arg.width,arg.height end a = {rect{x=1,y = 2,width= 10,height = 10}} for i,v in ipairs(a) do print(i,v) end 4) 变长参数 ... a) 变长参数的使用 ... b) 变长参数值得获取 使用时直接使用 ... 3个点就可以了。类似于 aa)不包含 nil 变长参数的遍历 for i,v in ipairs{...} do end 这种遍历方法,当传入的值中包含了 nil 值时,遍历 的结果会达不到预期要求。这时需要 select bb) 包含nil值得遍历 当变长参数中包含了空值时,可以使用select 函数来 获得该数组的最多key 值,然后挨个遍历 do local count = select("#",...) for i = 1,count do if not a[i] then --注意判断nil? print(a[i]) end end end 说明:select 函数的用法 select 第一个参数是selector,必须提供。并且 selector 只能是 数组下标,或者字符串"#": 当"#"时,返回字符数组最大下标; 当 n 时,返回下标为n 以及n之后的参数值 ? c) 作为参数返回 return ... d) 赋值 local a,c = ... 4. 返回值 1) 多重返回值 Lua 具有多重返回值。 注意:只有当函数的调用处在赋值语句的最末尾时, 才会有多个返回值 --假设 foo() 返回两个值 a,b = foo() -- a,b 为返回的两个值 a,b = 1,foo() -- 丢弃了一个值 a,b = foo(),1 -- 只接受了一个值 2) 强制要求只返回一个返回值 一对圆括号可以强制使,返回的多个值,只返回一个作为其他表 达式的参数。 print(foo()) -->1 2 print( (foo()) ) -->1 3) table 可以接受所有的返回值 a = {foo()} a = {foo(),1} --但这种情况也只接受一个返回值,原理 同第一个,除非在末尾调用 5. 参数返回相关 【***】 1) 使多重返回值,只返回第一个值 (foo()) 小括号? 2) 接受多个返回值,并返回多个值 unpack{foo()} unpack(table) 接受一个table 并返回table 中的所有值

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读