LUA学习(二) 类型、表达式等基础要点

由于lua是一门动态类型语言,所以对于lua的变量,是不需要提前声明类型的。lua的变量在使用时才会确定它的类型。

lua支持的类型有以下几种:nil、boolean、 number、string、userdata、function、thread 和 table。使用type函数可以用来测试变量的类型,如:

t = 10
print(type(t))  -- number
t = "hello world"
print(type(t))  -- string
t = type
print(type(t))  -- function
t = nil
print(type(t))  -- nil
t = false
print(type(t))  -- boolean
t = {a, b, c}
print(type(t))  -- table
通过以上的代码可以看出,t的类型并不是固定的,实际的类型需要使用时才能确定。

nil:

空类型。只有一个值nil。每一个声明但是未定义的变量都会等于默认值nil。对一个变量赋值为nil,相当于删除这个变量。


boolean:

布尔类型,有两个值,false和true。在lua中,所有值都可以作为控制语句的条件进行判断,但是只有nil和false会认定为假。其余都认为是真。注意:0及空串也会被认为是真。

t=""  --或是t = 0
if t then
	print(true)
else
	print(false)
end
以上语句执行结果为true。
只有当t=nil或是false时,才会打印false。


Numbers:

表示数字。注意:并不是表示整数。在lua中,numbers类型的变量可以处理任何长度的数字,不论是整数,还是负数,还是小数。

t = -1
print(t)   -- -1
t = 0.3e12
print(t)   -- 300000000000.0
t = 0.4    
print(t)   -- 0.4
t = 4.57e-3
print(t)   -- 0.00457
t = 5e+20
print(t)   --5e+20

string:

表示字符串序列。lua中字符串是不可以修改的,如果要修改一个字符串,必须将修改后的字符串存放到一个新的变量中。字符串可以用双引号、单引号或是[[..]]来囊括。如果字符串中存在引号的话,可以使用转义字符‘\'来保证。

\a bell  
\b backspace               -- 后退  
\f form feed                -- 换页  
\n newline                  -- 换行  
\r carriage return          --回车  
\t horizontal tab           --制表  
\v verticaltab  
\\ backslash                -- "\"  
\" doublequote             --双引号  
\' single quote             -- 单引号  
\[ leftsquare bracket      --左中括号  
\] right square bracket     -- 右中括号 

[[..]]多用来包含多行的字符串序列,这种形式的字符串属于纯字符串,不会解释其内部可能包括的转义字符。注意:这种形式的[[..]]不能嵌套使用

page = [[  
\t\b\'\'"this is a test  
]]  

io.write(page) 
打印结果如下:\t\b\'\'"this is a test。lua解释器不会解释[[..]]内包含的转义字符等。

lua会在需要时自动转化string和numbers。当string需要进行算术操作时,会转化成numbers。如:

print("10" + 10) 
执行结果为:20.0。string “10”被转化为numbers:10。

如果string不能被转化为numbers时,就会报错。

print("hello" + 1)          -- ERROR(cannot convert"hello")

当lua解释器检测到期望string时,会将numbers变量转化为string。如:

print(10 .. 20)      -->1020 
符号“..”是字符串连接符,会将两段字符串连接到一起。上述代码中,将10与20都转化为了string,然后连接到一起,输出完整的string,1020。

注意:.. 字符串连接符。 当数字作为该符号的参数时,需要以空格间隔,避免出错。

注意:虽然lua会自动转化字符串和数字,但是不能用来直接对比。如:10 == "10" 这样永远都是错的。如果需要对比,需要使用tonumber函数。10 == tonumber("10"),如果不能转换,tonumber会返回nil。


function:

lua中的function类型表示函数变量,它可以像其他类型的变量一样,可以赋值给变量,可以当做其他函数的实参使用,也可以作为函数的返回值。这一点有点像C语言的函数指针。


userdata and threads:

userdata 可以将 C数据存放在 Lua变量中,userdata 在 Lua 中除了赋值和相等比较外 没有预定义的操作。userdata 用来描述应用程序或者使用C实现的库创建的新类型。

线程类型的变量稍后再叙述。

table:

类似于python中的字典,只能通过构造式来构造。最简单的构造函数为{},这种方式会创建一个空表。如:t = {}, t 就是一个空表。

定义方式1:

mytable = { a = 10, b = 11, c = 20, ddd = 30 }   -->等价于 mytable = {}; mytable.a = 10; mytable.b = 11; mytable.c = 20; mytable.ddd = 30
print(mytable["a"])  -- 10
1)、 table 中的每项要求是 key = value 的形式 
2)、 key 只能是字符串, 这里的 a, b, c, ddd 都是字符串,但是不能加上引号 
3)、 通过 key 来访问 table 的值,这时候, a 必须加上引号 
定义方式2:

mytable = { 10, 12, 13 }   
  
print(mytable[1])  -- 10
print(mytable[2])  -- 12
print(mytable[3])  -- 13
 table 中可以出现没有 key 的项,这个时候,lua 会把这个 table 当做一个数组来看待,这个项的key就是它在数组中的下标(从1开始) 

定义方式3:

如果在构造式中,以上两种方式都出现了,类似下面这种:

mytable = { 10, ddd = 30, 12, 13 }  
  
print(mytable[1])  -- 10
print(mytable[2])  -- 12
print(mytable[3])  -- 13
lua解释器,会按照定义方式2的方式解释这个table,“ddd = 30”项在以数字为下标的数组中,被忽略掉了。会跳过这个项,查找符合规则的数组项来填充数组,下标会取下一个连续值。如果要访问"ddd=30"的话,可以使用如下方式:mytable["ddd"],这个值为30。

定义方式4:

在构造式中,显示的指明数组下标:

a={[1]=5,[2]=6,[34]=7} 
print(a[1]) -- 5
print(a[2]) -- 6
print(a[34])  -- 7
这种方式与第一种方式类似,只不过它显示指明的下标不是字符串,而是数字,需要用[]将下标包起来。

注意:lua的构造函数中可以使用分号和逗号。逗号一般被用来分割不同类型的表元素。如:{x=10, y=45;"one","two","three"}
lua中的表中,有显式索引的可以使用显式索引,没有显式索引的则以1、2、3为索引。如:

polyline ={x=10, y=45;"one","two","three";z=3;"bs"},
print(polyline.x) --10
print(polyline.y) --45
print(polyline.z) --3
print(polyline[1]) --one
print(polyline[2]) --two
print(polyline[3]) --three
print(polyline[4]) --bs

注意:表的构建元素没有限制,可以使用字符串,或是数字,或是表达式。而且可以在构建完成后,随意增加删除table内的元素。

function my_api(x)
	return x
end

w = {x=0,y=0, label="console"} 
x = {my_api(0),my_api(1), my_api(2)}  
print(w[1]) 		-->nil
w[1] ="another field"  -->create new elem
x.f = w  
print(w["x"])     --> 0    
print(w[1])       --> another field   
print(x.f[1])     --> another field  
w.x = nil        -- removefield "x" 

table的定义方式很灵活。

另外,利用构造函数嵌套,可以构造复杂的table变量,如:

polyline ={color="blue", thickness=2, npoints=4,  
    {x=0,   y=0},  
    {x=-20, y=0},  
    {x=-10, y=1},  
     {x=0,   y=1}  
}
print(polyline[2].x)     --> -20  

练习示例:

opnames = {["+"] ="add", ["-"] ="sub",  ["*"] = "mul", ["/"] = "div"}  -->显式索引
  
i = 20; s = "-"  
a ={[i+0] = s,[i+1] = s..s,[i+2] = s..s..s}  -->表达式作为下标
   
print(opnames[s])    --> sub  
print(a[22])         --> ---  


算术运算符:

lua的算术运算符,包括 + - * \ ^(加减乘除幂)等。与其他语言一样,不再赘述。


关系运算符:

<   >    <=     >=     ==     ~=(不等于)

这些运算符返回结果false或是true。对于 == 和 ~=,如果两个比较项是不同的类型,则认为两者不相等。注意:nil只和自己相等。当lua通过引用比较userdata、table、function类型的变量时,只有当引用为同一对象时才相等。即便两个比较项内部的数值一样,也不相等。如:

a = {}
a.x = 1; a.y = 0  
b = {}
b.x = 1; b.y = 0 
c =a  
print(a==c)  --true
print(a==b)  --false

Lua 比较数字按传统的数字大小进行,比较字符串按字母的顺序进行,但是字母顺序依赖于本地环境。

当比较不同类型的值的时候要特别注意:

print("0" == 0)     -- false  
print(2 < 15)        -- true  
print("2" < "15")    -- false (alphabetical order!)
为了避免不一致的结果,混合比较数字和字符串,Lua 会报错,比如:2 < "15"


逻辑运算符:

and     or      not

and和or代表与和或的意思,and的优先级比or高。需要注意的一点是,and 和 or 的运算结果不是 true 和 false,而是和它的两个操作数相关。如:

b = 10
print(a and b)       -- 如果 a 为 false,则返回 a,否则返回 b  结果为nil
print(a or b )      -- 如果 a 为 true,则返回 a,否则返回 b  结果为10
这一点与其他语言不同,需要注意。 

利用以上这点,可以很方便的达到某些目的。比如:如果x为false或nil,则给x赋初值为x:

x = x or v

C语言中的三元运算符,a ? b : c,在lua中可以这样实现:(a and b) or c。(如果a为true,则返回b,如果为false或nil,则(a and b)返回a,此时,对于or运算符,前半部分为a,即false或nil,需要返回c。)

not相当于C语言中的取反操作,这个运算符的返回值只有两种,false或是true。

print(not nil)          --> true  
print(not false)        --> true  
print(not 0)            --> false  
print(not not nil)      --> false 


连接运算符:

主要为'..',前面介绍过,主要用来连接两个字符串。

优先级:

^  
not  -  (unary)  
*     /  
+    -  
..  
   
<    >      <=    >=    ~=   ==  
and  
or  





你可能感兴趣的:(Lua)