从零开始学 Lua(二)八大基本类型

本文是Lua系列教程的第二部分,主要介绍了Lua的8种基本类型:nil、boolean、number、string、table、function、thread和userdata。通过实例解析了每种类型的特性和用法,如逻辑运算符的短路特性、Lua独有的地板除法以及表作为强大数据结构的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Lua是一种动态类型语言 (Dynamically-typed Language),在Lua中可以直接使用变量而无需声明,并且使用的变量会随着环境自动改变类型。看到这儿,可能你心中会有以下的问题:

Lua中的变量到底是如何自动随环境改变类型的呢?

你不妨带着这个问题接着看下去。

Lua中一共有8种基本类型,不过日常开发中我们只需掌握其中7种即可,这8种分别是:

  • nil (空)
  • boolean (布尔)
  • number (数字)
  • string (字符串)
  • table (表)
  • function (函数)
  • thread (线程)
  • userdata (用户数据)

nil

nil的含义是 “零,空”,用来表示无效值 (non-value)。nil是一种类型,但它只有nil这一个值。这句话初看有些古怪🤔,且看代码:

print(none)   --> nil
print(nil)    --> nil
-- 其中两个减号后直到行末部分为注释,用-->表示输出结果。

第1行我们输出一个在此之前从来没有使用过的变量,结果是nil,说明我们没有给名为none的变量赋过值,注意在Lua中,👉任何没有赋过值的变量默认值都为nil

第2行我们输出nil,发现它的结果也是nil!我们从第1行的输出结果可知,nil是一个特殊的值,用来表示不存在的变量;而第2行的输出结果告诉我们,类型nil的值也是nil。所以才会说nil是一种只有一个nil值的类型。

nil与其他语言 (如C语言) 中的null在拼写上很相近,在上一篇的Lua介绍中我们知道了Lua语言是通过标准C语言实现的,那么作者Roberto为什么特意使用这样一个相近却不同的概念呢?😕

原因有二:

  • nil是一个类型;
  • nil在条件判断中被视为false。

boolean

与其他语言相同,boolean类型具有2个值,true和false。但是在Lua中,除了false和nil之外的所有值都视为真,所以 0 和空字符串 "" 都被视为真。

逻辑运算符

Lua中有三个逻辑运算符:and、or和not。由于 “只有false和nil值为假” 这一特性,使得它们在实际使用中具有无比的灵活性。

and和or运算符具有短路特性,如果and的第一个操作数为false,则直接返回第一个操作数;如果or的第一个操作数为true,则直接返回第一个操作数。且看示例:

print(0 and 5)        --> 5
print(nil and true)   --> nil
print(0 or 5)         --> 0
print(nil or true)    --> true

Lua中有两个惯用写法非常重要✔:

  1. x = x or v 当x不是false时,它的作用是当x未被初始化时,将其默认值设为v,相当于 if not x then x = v end
  2. a and b or c 当b不是false时,他的作用等价于C/C++中的三目运算符 a ? b : c,例如 (x > y) and x or y 返回x与y中的较大者。

number

顾名思义,该类型为数值类型,任何具有数值含义的变量都是number类型,且看示例:

print(type(2))        --> number
print(type(2.33))     --> number
print(type(2.33e23))  --> number
print(type(233^23))   --> number

算术运算符

  1. + :加号;
  2. - :减号、取反;
  3. * :乘号;
  4. / :除号;
  5. // :floor除号,该运算符为Lua独有,👉floor除法会对得到的商向负无穷取整,从而保证结果是一个整数。且看示例:
    print(3 // 2)        --> 1
    print(-9.2 // 2)     --> -5
    
  6. % 取模符号。示例:
    x = 3.1415927
    print(x - x % 0.01)  --> 3.14
    

string

对于Lua的字符串类型,有几点知识点:

  1. Lua中的字符串是不可变值 (immutable value)。不能在原字符串上修改,只能新建字符串来达到修改的目的;
  2. 用长度操作符 # 可以获得字符串的长度:
    print(#"good bye")   --> 8
    
  3. 连接操作符两个点 .. 用来进行字符串的连接:
    print("Hello " .. "World")   --> Hello World
    
  4. 字符串可以使用一对双引号或者单引号:
    a = "a line"
    b = 'another line'
    c = 'left, "inline", right'  -- 在单引号中的双引号不需要转义
    
  5. 多行字符串用一对中括号包围:
    page = [[
    <html>
    <head>
      <title>Just a HTML Page</title>
    </head>
    </html>
    ]]
    
  6. 若多行字符串中存在中括号,可以在包围字符串的中括号对中插入相同数量的等号 =
    table = [==[
    a = {}
    a.[1] = "first"
    a.[2] = "second"
    a.[3] = "third"
    ]==]
    

table

表是Lua中非常强大的数据结构,也是最重要的一个类型。

表由一个个键值对组成,同一个表中存储的值可以有不同类型的索引 (键),也可以有不同类型的值,并且可以按需增长以容纳新的元素。

a = {}
x = "y"
a[x] = 10
print(a[x])    --> 10
print(a.x)     --> nil
print(a.y)     --> 10

上述示例中,第3行代码的作用是添加键值对(“y”, 10),访问表中的元素有两种方法:

  1. 中括号 [] :适用于任何类型的键;
  2. 点号 . :只适用于键为字符串类型,a.name 等价于 a.["name"]

function

到目前为止我们接触最多的函数就是 print 了,函数最显著的特点就是使用时需要带上一对括号 () ,括号中可以传入一些参数,调用一个函数后它也可能会返回一些值。例如:

print(type(1))        --> number
print(type(type(1)))  --> string

可见,函数type的返回值是代表其参数类型的字符串。


thread

虽然Lua中有名为thread (线程) 的类型,但实际上它并不是线程,而是协程 (coroutine)。

虽然协程与线程差不多,都拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。但是线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起 (suspend) 时才会暂停。

那为啥作者要指鹿为马,偏偏给协程取名线程呢?这我真不知道,你问作者吧🤷‍♀️

关于协程,我会在之后的博客中详细探讨的。


userdata

userdata是一种用户自定义数据,用于表示一种由应用程序或C/C++语言库所创建的类型,可以将任意C/C++的任意数据类型的数据 (通常是struct和指针) 存储到Lua变量中调用。一般的用户不需要了解该种类型。


解答开篇

在开篇的时候我抛出了一个疑问:Lua中的变量是如何自动改变类型的?

首先,Lua中的变量是不需要声明就可以直接赋值使用的,而对一个已赋值的变量还可以赋其他类型的值,这时该变量的类型会自动改变为它当前存放的值的类型。

a = 1
print(type(a))        --> number

a = "it is a string"
print(type(a))        --> string

a = { b = 2.33 }
print(type(a))        --> table
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值