Lua学习笔记(2)——变量类型与表达式
本文介绍了Lua的变量类型与表达式,着重强调各种类型需要注意的地方。本文介绍了Lua的变量类型与表达式,着重强调各种类型需要注意的地方。
1. Lua类型
1.1 基本类型
Lua是一种动态类型语言,没有类型定义的语法。Lua一共有8种基础类型:nil(空)、boolean(布尔)、number(数字)、string(字符串)、userdata(自定义类型)、function(函数)、thread(线程)、table(表)。
函数type可根据一个值返回其类型名称(字符串),如print(type(print))
,输出“function”;print(type(type(X)))
,输出“string”。(这里不管X有没有定义,type(X)总是返回字符串)
1.2 各类型要注意的地方
关于boolean
在Lua中,false和nil视为“false”,其它值均视为“true”(包括数字0和空字符串)。
关于number
该类型用于表示实数(双精度double),整数也用此类型表示。
关于string
字符串不能像C语言一样直接修改某个字符,必要时应通过string库创建一个新的字符串。字符串可以用一对匹配的单引号或双引号来界定。可以实用类C语言的转义序列。
此外,可以用双方括号
[[内容]]
来界定,其中的换行字符均被忽略,适用于包含一整段的字符串。若在左边的两个方括号间加入任意数量的等号,如[===[
,则字符串右边应该匹配带相同数量等号的方括号,如]===]
,这样做就可以在不加转义的情况下直接嵌入任意内容的字符串。同理注释也可以这样使用,如--[==[
匹配--]==]
。Lua提供运行时的数字与字符串自动转换。如
print("10"+1)
–> 11,print(10 ..20)
–> 1020(“..”是字符串连接符,上例将数字转换成字符串并连接,数字和..之间应该留一个空格)。建议尽量少用自动转换,如有需要可用强制转换。函数
tonumber(x)
尝试将x转换成数字,若失败则返回nil,函数tostring(x)
将x转换成字符串。在字符串前放置“#”可获得字符串的长度,如print(#"length")
–> 6。关于table
Table是一种具有特殊索引方式的数组,可以实用除nil外的其他类型的值作为索引,其增长与删减均通过自动内存管理来完成。Table是一个“对象”,程序仅持有一个对它们的引用,例如可以通过
a = {}
创建一个table并将它的引用存储到a,若再b = a
,则b与a引用同一个table。若table的某个元素没有初始化,其值即为nil,可以通过赋nil来删除table的某个元素。有一种等价写法:
p["age"]
等价于p.age
。注意,p.age和p[age]并不等价。“#”可用于返回一个数组的最后一个索引值(或其大小)。例如
print(a[#a])
打印列表a的最后一个值,a[#a+1] = io.read()
读入一个值并插入到列表a末尾。注意,Lua将nil作为界定数组结尾的标志,当一个数组中间含有nil时,#会认为第一个nil就是结尾,因此应避免对含“空隙”的数组使用#。在Lua中,一般默认table第一个索引为1而不是C语言中的0。
Function、userdata和thread类型留到以后再讲。
2. 表达式
2.1. 算术操作符
常规的操作符有:+加、-减、*乘、/除、^指数、%取模。其中^可用于任意实数,如x ^ (-1 / 3)
计算x的立方根倒数。%可以这样使用:x % 1
结果是x的小数部分,x - x % 0.01
是x精确到小数点后两位的结果。
2.2. 关系操作符
常规关系操作符有:<小于、>大与、<=小于等于、>=大于等于、==相等、~=不等。==和~=可用于任意两个值,若两个值具有不同类型则不相等,有相同类型则作正常比较(nil只与其自身相等)。对于对象则比较它们的引用。
2.3. 逻辑操作符
逻辑操作符有and、or和not。对and(or)来说,若第一个操作数为假(真),就返回第一个操作数,否则返回第二个操作数。如print(4 and 5)
–> 5,print(false or 5)
–> 5。
有一些常用写法:x = x or v,可用在没有设置x的时候,将其设为一个默认值v。另一种写法(a and b) or c
类似a ? b : c
,如max = (x > y) and x or y
。
2.4. 字符串连接符
可用“..”(两个点)来连接两个字符串,若其中任一个为数字,Lua会自动转换,如print(0 ..1)
–> 01。连接字符串只会创建一个新字符串,不会对原操作数进行修改。
Lua运算符优先级顺序如下图所示。

2.5. Table构造式
除了上述直接赋予{}创建空table以外,可以初始化其值,如day = {"S", "M", "T"}
,或者point = {x = 10, y = 20}
(即point.x=10,point.y=20)。以上两种初始化方式可以混用,还可以用分号代替逗号,来将列表部分和记录部分明显地分隔开,如polyline = {color = "blue"; {x = 0, y = 0}, {x = 10, y = 10}, {x = 20, y = 30}},则
print(polyline[2].x)` –> 10。
更加通用的初始化格式,可以在方括号间声明索引值,如opnames={["+"] = "add", ["-"] = "minus"}
。若某些情况真的需要以0作为一个数组的起始索引,可以这样days={[0] = "S", "M", "T"}
。但是不推荐在Lua中以0作为索引起始值,因为大多数内建函数都假设数组起始于索引1。
参考文献:电子工业出版社《Lua程序设计(第2版)》第2-3章