Redis基础知识(学习笔记21–Lua 脚本语言2)

4.2 迭代器

Lua提供了两个迭代器pairs(table) 与 ipairs(table)。这两个迭代器通常会应用于泛型for循环中,用于遍历指定的table。这两个迭代器的不同是:

  • ipairs(table):仅会迭代指定table中的数组元素。
  • pairs(table) :会迭代整个table元素,无论是数组元素,还是key-value。

4.3 模块

模块是Lua中特有的一种数据结构。从 Lua 5.1 开始,Lua加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

模块主要由 table 组成。在 table 中 添加相应的变量、函数,最后文件返回该 table 即可。如果其它文件中需要使用该模块,只需通过 require 将该模块导入即可。

4.4 元表与元方法

元表,即 Lua 中普通 table 的元数据表,而元方法则是元表中定义的普通表的默认行为。 Lua 中的每个普通 table 都为其定义一个元表,用于扩展该普通 table 的行为功能。例如,对于 table 与数值相加的行为, Lua 中是没有定义的,但用户可通过 为其指定元表来扩展这种行为;再如,用户访问不存在的 table 元素, Lua 默认返回的是 nil,但用户可能并不知道发生了什么。此时可以通过为该 table 指定元素来扩展该行为:给用户提示信息,并返回用户指定的值。

(1)重要函数

元表中有两个重要函数:

  • setmetatable(table,metatable)::将metatable指定为普通table的元表。
  • getmetatable(table):获取指定普通表 table 的元表。
(2)__index 元方法

当用户在对 table 进行读取访问时,如果访问的数组索引或key 不存在,那么系统就会自动调用元表的 __index 元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的__index 元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回nul。

(3)__newindex元方法

当用户为 table 中一个不存在的索引或key赋值时,就会自动调用元表的__newindex 元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的__newindex元方法是函数,且有返回值,则直接返回;如果没有,则返回nil。

(4)运算符元方法

如果要为一个表扩展加号(+)、减号(-)、等于(==)、小于(

例如,如果要为一个table扩展加号(+)运算功能,则可以重写该table元表的__add元方法,而具体的运算规则,则是定义在该重写的元方法中的。这样,当一个table在进行加法(+)运算时,就会自动调用其元表的__add元方法。

类似于加法操作的其它操作,Lua中还有:

元方法 说明 元方法 说明
__add 加法,+ __band 按位与,&
__sub 减法,- __bor 按位或,|
__mul 乘法,* __bxor 按位异或,~
__div 除法,/ __bnot 按位非,~
__mod 取模,% __shl 按位左移,
__pow 次幂,^ __shr 按位右移,>>
__unm 取反,- __eq 等于,==
__idiv 取整除法,// __it 小于,
__concat 字符串连接,… __lt 大于,>
__len 字符串长度,#    
 (5)__tostring 元方法

 直接输出一个table,其输出的内容为类型与table的存放地址。如果想让其输出table中的内容,可重写__tostring元方法。

(6)__call元方法

 当将一个table以函数形式来使用时,系统会自动调用重写的__call元方法。该用法主要时可以简化对table的相关操作,将对table的操作与函数直接结合。

(7)元表单独定义

为了便于管理和复用,可以将元素单独定义为一个文件。该文件中仅可定义一个元表,且一般文件名与元表名称相同。

若一个文件要使用其它文件中定义的元表,只需使用 require”元表文件名“ 即可将元表导入使用。

如果用户想扩展该元表而又不想修改元表文件,则可在用户自己文件中重写其相应功能的元方法即可。

5.面向对象

Lua 中没有类的概念,但通过table、function 与元表可以模拟和构造出具有类这样功能的结构。

 (1)简单对象的创建

Lua 中通过table 与 function可以创建出一个简单Lua对象:table为Lua对象赋予属性,通过function为Lua对象赋予行为,即方法。

(2)类的创建

Lua 中使用table 、function与元表可以定义出类:使用一个表作为基础类,使用一个function作为该基础类的new()方法。在该new()方法中创建出一个空表,再为该空表指定一个元表。该元表重写__index元方法,且将基础表指定为重写的__index元方法。由于new()中的表是空表,所以用户访问的所有key都会从基础类(表)中查找。

 6.协同线程与协同函数

(1)协同线程

Lua 中有一种特殊的线程,称为coroutine,协同线程,简称协程。其可以再运行时暂停执行,然后转去执行其它线程,然后还可以返回再继续执行没有执行完毕的内容。即可以”走走停停,停停再走走“。

协同线程也称为协作多线程,在Lua中表示独立的执行线程。任意时刻只会有一个协程执行,而不会出现多个协程同时执行的情况。

协同线程的类型为thread,其启动、暂停、重启等,都需要通过函数来控制。下表是用于控制协同线程的基本方法。

 方法 描述 
 create(function) 创建一个协同线程实例,即返回的是thread类型。参数是一个function。其需要通过resume()来启动协同线程的执行。 
 resume(thread,…) 启动指定的协同线程的执行,使其 从开始处或前面挂起处开始执行。可以向create()的内置函数传递相应的参数。如果内置函数具有返回值,resume()会全部接收并返回。
 running()  返回正在运行的协同线程实例,即thread类型值。
yield()   挂起协同线程,并将协同线程设置为挂起状态。resume()可从挂起处重启被挂起的协同线程。
status(thread)  查看协同线程的状态。状态有三种:运行态running,挂起态suspended,消亡态dead。 
colse()  关闭协同线程 
wrap(function)   创建一个协同线程,返回的是function类型。一旦调用该函数就会创建并执行一个协同线程实例。

 示例 1 ,无返回值

示例 2 ,有返回值

(2)协同函数

协同线程可以单独创建执行,也可以通过协同函数的调用启动执行。使用coroutine的wrap()函数创建的就是协同函数,其类型为function。

由于协同函数的本质就是函数,所以,协同函数的调用方式就是标准的函数调用方式。只不过,协同函数的调用会启动其内置的协同线程。

示例如下:

也可以通过resume的方式开始挂起的协程。

7. 文件IO

Lua 中提供了大量对文件进行IO操作的函数。这些函数分为两类:静态函数和实例函数。所谓静态函数是指通过io.xxx()方法对文件进行操作的函数,而实例函数是通过Lua中面向对象方式操作的函数。

7.1 常见静态函数

(1)io.open()

【格式】io.open(filename [,mode])

【解析】以指定模式打开指定文件,返回要打开文件的句柄,就是一个对象。其中模式mode有三种,但同时还可配合两个符号使用:

  • r:只读,默认模式。
  • w:只写,写入内容会覆盖文件原有内容。
  • a:只写,以追加方式写入内容。
  • +:增加符,在r+、w+、a+均变为了读写。
  • b:二进制表示符。如果要操作的文件为二进制文件,则需要变为rb、wb、ab。
(2)io.input()

【格式】:io.input(file)

【解析】:指定要读取的文件。

(3)io.output()

【格式】:io.output(file)

【解析】:指定要写入的文件。

(4)io.read()

【格式】:io.read([format])

【解析】:以指定格式读取io.input()中指定的输入文件。其中format格式有:

  • *I:从当前位置的下一个位置开始读取整个行,默认格式。
  • *n:读取下一个数字,其将作为浮点数或整数。
  • *a:从当前位置的下一个位置开始读取整个文件。
  • number:这是一个数字,表示要读取的字符的个数。
(5)io.write()

【格式】:io.write(data)

【解析】:将指定的数据data写入到io.output()中指定的输出文件。

示例1

示例2

7.2 常见实例函数

(1)file:read()

这里的file使用的是io.open()函数返回的file,其实际就是Lua中的一个对象。其用法与io.read()的相同。

示例:

(2)file:write()

用法与io.write()相同。

示例:

 注意写入的字符串前面的 n 表示换行。

(3)file:seek()

【格式】file:seek(|whence[,offset])

【解析】该函数用于获取或者设置文件读写指针的当前位置。位置从1开始计数,除文件最后一行外,每行都有行结束符,其会占两个字符位置。位置0表示文件第一个位置的前面位置。

当seek()为无参时会返回读写指针的当前位置。参数whence的值有三种,表示将指针定位的不同位置。而offset则表示相对于whence指定位置的偏移量,offset的默认值为0,为正表示向后偏移,为负表示向前偏移。

  • set:表示将指针定位到文件开头处,即0位置处。
  • cur:表示指针保持当前位置不变,默认值。
  • end:表示将指针定位到文件结尾处。

 

学习笔记–参阅特别声明

1.【Redis视频从入门到高级】

【https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】

千百度
© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容