类型与值

lua 是动态类型的语言

  1. 在语言中没有类型定义的语法
  2. 每个值都携带有它的类型信息

8种基础类型

  1. 用 type 可以返回这个值的类型的名称
  2. 将一个变量用于不同类型,通常会导致混乱的代码
  3. 但合理使用,如异常情况下返回 nil ,以区别正常情况下的其他类型的返回值
  4. 变量没有预定义的类型,任何变量都可以包含任何类型的值
print(type("Hello")) --string
print(type(666)) --number
a = print
print(type(a)) --function
a = 111
print(type(a)) --number
print(type(b)) --nil
print(type(string)) -- table 不太懂为什么
print(type(type(X))) -- string
  1. 最后一行将永远返回将永远返回 "string" , 而无关乎 X 这个值的内容。这是因为 type 函数总是返回一个字符串

nil (空)

  1. nil 类型只有一个值,表示空
  2. 主要功能是区别其他任何值
  3. 一个全局变量在它第一次赋值之前它的默认值就是 nil
  4. 将 nil 赋给一个全局变量等同于删除这个变量
  5. lua 将 nil 用于表示一种 "无效值"的情况,即没有任何有效值的情况

boolean (布尔)

  1. 布尔类型有两个可选值,

    1. 一个是 true,一个是 false
    2. true 表示真, false 表示假
  2. boolean 不是条件值的唯一表达方式
  3. 在 lua 中任何值都可以用来表示条件
  4. lua 将值 false , nil 视为假。将除此之外的其他值视为真
  5. lua 在条件测试中数字 0 和空字符串都视为真

number (数字)

  1. lua 中用于表示实数,即双精度浮点数
  2. lua 没有整数类型
  3. 可以重新编译 lua ,使用其他类型来表示数字
  4. 如 使用长整型 long 表示数字,或单精度浮点数 float 表示数字
  5. 书写一个数值常量,可以使用普通写法或科学计数法

科学计数法

  1. 在计算机中用 e 或 E 表示 ,表示10的几次方
  2. 可以简单理解为e 后面是多少就挪几个0
a = 3.2e2
print(a) --320

string (字符串)

  1. lua 中的字符串通常表示为一个字符序列
  2. lua 采用8位编码
  3. lua 字符串中的字符可以具有任何数值编码包括数值0
  4. 这种特性:可以让我们将任意进制(如二进制),存储到字符串中
  5. lua 中的字符串是不可变的值,不能像 C 语言那样可以直接修改一个字符串中的某个字符
  6. 而是应该根据修改要求建立一个新的字符串

修改子串

a = "one string"
b = string.gsub(a, "one", "another") -- 字符串替换函数
print(b) -- another string
print(a) -- one string
  1. lua 中的字符串和其他的 lua 对象如 table, function 一样都是自动内存管理机制所保存的对象
  2. 这意味着我们无需担心字符串的分配和释放
  3. 字符串可以是一个字母也可以是一本书的所有字符
  4. lua 可以高效处理长字符串,如100k ,1M容量的字符串

字面字符串

  1. 需要用一对匹配的单引号或者双引号来包裹
  2. 如果字符串本身包含两种引号中的一种,我们可以使用另一种引号来包裹
  3. 也可以使用 \ 来进行转义
a = 'Hello'
b = "World"
c = "I'm a student"
d = "I\'m a student'"

转义序列

  1. \a 响铃
  2. \b 退格
  3. \f 提供表格
  4. \n 换行
  5. \' 单引号
  6. \" 双引号
  7. \t 水平tab
  8. \v 垂直 tab
  9. \\ 反斜杠
  10. \r 回车
print("one line\nnext line\"in quotes\",'in quotes'")
--[[
one line
next line
"in quotes",'in quotes'
--]]

可以通过数值指定字符串中的字符

  1. 数值转义序列 \<XXX>
  2. <xxx>是一个至多三个十进制数字组成的序列
print('a' == '\97') -- true
  1. 用一对方括号 [[]] 可以包裹多行字符串

    1. lua 就不会解释其中的转义序列
    2. 如输入 html 代码
page = [[
<html>
<head>
<title>Lua Study</title>
</head>
<body>
<a href="http://www.lua.org">Lua 学习 </a>
</body>
</html>
]]

lua 提供了运行时数字和字符串的自动转换

print("10" + 1)  --字符串10会被自动转换为数字10,结果打印为11
print("Hello" + 1) -- 会报错

字符串连接符 ..

  1. 可在多个字符串之间使用 .. 用以连接字符串
  2. 当在一个数字后输入它时,必须使用一个空格分割,不然 lua 会误解第一个点为小数点
print("A".."=".."B") -- A=B
print(10..24) -- 会报错
print(10 .. 24) -- 1024

长度操作符 #

  1. 可在字符串前放置 # 用以获取这个字符串的长度
print(#"Hello") -- 5

tonumber

  1. 将字符串显式地转换为数字
line = io.read() -- 读取一行
n = tonumber(line)
if n = nil then
error(line .. " is not a valid number")
else
print(n * 2)
end

tostring

  1. 将一个数字转换成字符串
  2. 也可将数字与一个空字符串用字符串连接符 .. 连接
a  = 2333
print(tostring(2333) == "2333") -- true
print(a .. "" == "2333") -- true

table (表)

  1. lua 中的 table 类型实现了关联数组

    1. 关联数组就是具有特殊索引方式的数组
  2. 可以使用整数、字符串或其他类型的值(除了 nil)来做为索引
  3. table 没有固定大小,可以动态的添加元素到一个 table 中
  4. table 是 lua 中主要的也是仅有的数据结构机制
  5. 基于 table 可以简单、统一和高效的方式表示普通数组、符号表、集合、记录、队列和其他数据结构
  6. lua 通过 table 来表示模块、包和对象

举例: io.read

  1. io 模块中的 read 函数

  2. 使用字符串 read 作为 key 来索引 table io

  3. 在 lua 中 table 既不是值也不是变量,而是对象

  4. 可将 table 想象为一个动态分配的对象

  5. 程序仅持有对他们的一个引用(或指针)

  6. lua 不会暗中产生 table 的副本,或者创建新的 table

在 lua 中不需要声明一个 table

  1. table 的创建是通过构造表达式来完成的
  2. {} 一对这样的大括号就称之为 table 的构造表达式
a = {} -- 创建了一个 Table 把它的引用存储到 a 这个变量里,那么 a 就是一个 table 类型的变量了
k = "x"
a[k] = 10 -- 新条目, key = x, value = 10 在 a 这个 table 添加了一个元素,这个 table 的索引是字符串索引,这个新生成的条目的值就是 10,它的索引是 x
a[20] = "great" -- 新条目, key = 20, value = "great"
print(a["x"]) -- 10
k = 20
print(a[k]) -- great
a["x"] = a["x"] + 1
print(a["x"]) -- 11

table 永远是匿名的

  1. 一个只有 table 的变量和 table 自身之间没有固定的关系
a = {}
a["x"] = 10
b = a -- b 与 a 引用了同样一个 table
print(b["x"]) -- 10
a = nil
print(a["x"]) --报错
print(b["x"]) --10 因为现在只有 b 在引用 table ,而 a 已经清除了对 table 的引用
b = nil -- 现在 a 和 b 都没有对 table 引用了
  1. 在 lua 中当一个程序在没有对 table 进行引用的时候,这个 table 就会被垃圾回收器给删除掉,并且释放它的内存

所有 table 都可以通过不同类型的索引来访问它的值

  1. 当需要添加新的元素的时候,table 会自动的增长
  2. 如果 table 中的某个值未被初始化的时候,那它就是 nil
  3. 可以通过给 table 中的某个元素赋值 nil 来删除它
  4. 因为 lua 将全局变量存储在一个普通的 table 种
-- for 循环 ,索引从1开始,与C或其他语言从0开始不同, do 里面的代码块是循环体
t = {}
for i = 1, 1000 do
t[i] = 2 * i -- 值是索引的两倍
end
print(t[8]) -- 16
t["x"] = 10
print(t["x"]) --10
print(t["y"]) -- nil
t["x"] = nil -- 删除了 table 中索引为 x 的元素

lua table 访问的两种写法(语法糖)

  1. a["name"]
  2. a.name
  3. 这两种写法是等效的
  4. a.name 的写法可能暗示了代码读者将 table 当做了一条记录使用
    1. 每个记录都有一组固定的预定义的键 key
  5. a["name"]的写法可能暗示了代码读者该 table 可以以任何字符串作为 key
    1. 而现在出于某些原因是需要访问某个特定的 key
a.x  --  表示为 a["x"] 以字符串 x 为索引 table
a[x] -- 以变量 x 的 值 为索引 table a = {}
x = "y" -- x 已经被赋值为"y" 所以变量 x 的值为字符串 y ,索引 x 变量就是索引字符串 y
a[x] = 10
print(a.x) -- 索引为字符串 x --> nil
print(a["x"]) -- 索引为字符串 x --> nil
print(a[x]) -- 索引为变量 x --> 10
print("\n")
print(a.y) -- 索引为字符串 y --> 10
print(a["y"]) -- 索引为字符串 y --> 10
print(a[y]) -- 索引为变量 y --> nil

表示传统的数组或线性表

  1. 只需要 key 为整数即可
  2. 并不需要声明一个大小值,直接初始化元素就可以
  3. 数组通常以 1 作为索引的起始值

长度操作符 # 对于 table 的作用

  1. 用于返回一个数组或一个线性表的最后一个的索引值(或者称为大小)
t = {}
for i = 1, i = 666 do
t[i] = i * 2
end
print(#t) -- 666, 相当于这个 table 有 666 个元素(或者称这个 table 的大小为 666)
for i = 1, #t do
print(t[i])
end
print(t[#t]) -- 打印 table 最后一个值
t[#t] = nil -- 删除 table 的最后一个值
print(#t) -- 现在 table 的长度就是 665 个
t[#t + 1] = 8888 -- 给 table 再加一个元素
print(#t) -- 现在 table 的长度是 666 个
print(t[#t]) -- 现在 table 的最后一个元素就是 8888 了

数组的实际大小

  1. 对于所有未初始化的元素的索引结果都是 nil
  2. lua 将 nil 作为判断数组结尾的标志
  3. 当一个数组有空隙即中间含有 nil 时,长度操作符会认为这些 nil 元素就是结尾标记
  4. 注意:避免对含有空隙的使用长度操作符,可以使用 table.maxn,它返回一个 table 的最大正索引数
a = {}
a[10000] = 1
print(#a) -- 0
print(a[10000]) -- 1
print(table.maxn(a)) --> 10000

对于索引类型不明确时进行显式转换

  1. 使用 tonumber() 函数可以显式的转换为整数格式
i = 10
j = "10"
k = "+10"
t = {}
t[i] = "one value"
t[j] = "another value"
t[k] = "yet another value"
print(t[i]) -- one value
print(t[j]) -- another value
print(tonumber(t[k])) -- one value
print(tonumber[t[j]]) -- one value
print(t[tonumber(k)])
print(t[tonumber(j)])

函数

  1. lua 中函数是作为第一类值来看待的
  2. 函数可以存储在变量中
  3. 我们可以通过参数传递给其他函数,还可以作为其他函数的返回值
  4. 基于这种机制,当我们给一个函数添加新的功能的时候,程序可以重新定义这个函数
  5. 在运行一些不受信任的代码的时候,可先删除某些函数,从而创建一个安全的运行环境
  6. lua 既可以调用自身编写的函数,还可以调用 C 语言编写的函数
  7. lua 所有的标准库都是用 C 语言编写的
    1. 如:对字符串的操作
    2. 对 table 的操作
    3. 输入输出
    4. 操作系统的功能调用
    5. 数学函数
    6. 调试函数
  8. 应用程序也可以使用 C 语言来定义的其他函数

userdata (自定义类型)

  1. 可以将任意的 C 语言数据存储到 lua 变量中
  2. 没有太多的预定义操作
  3. 只能进行赋值和相等性测试
  4. 用于表示一种由应用程序或 C 语言库创建的新类型
  5. 如 标准的输入输出库(IO 库)就用 userdata 来表示文件

thread (线程)

  1. 后续学习

lua学习之类型与值篇的更多相关文章

  1. Lua学习之类型与值

    Lua是一种动态语言,在语言中没有类型定义的语法. 在lua中有8中基本的类型: 1.nil(空) 2.boolean 3.number(数字) 4.string(字符串) 5.userdata(自定 ...

  2. Lua中的类型与值

    [基础介绍] Lua是一种动态类型的语言.在语言中没有类型定义的语法,每个值都带有其自身的类型信息.在Lua中有8中基本类型,分别是: nil(空)类型 boolean(布尔)类型 number(数字 ...

  3. lua学习之深入函数第一篇

    深入函数第一篇 函数是第一类值,具有特定的词法域 第一类值 第一类值的意思是函数与 lua 中的其他类型如数字,字符串具有相同的权力 函数可以存储到全局变量或局部变量变量,还可以存储到 table 中 ...

  4. lua学习之深入函数第二篇

    深入函数 2 非全局的函数 函数是第一类值,函数可以存储到全局变量,局部变量,table 字段中 lua 函数库中的大部分函数存储到 table 字段中 Lib = {} Lib.foo = func ...

  5. Lua 学习笔记(二)语法、类型、值

    首先Lua执行的每一段代码都称之为“程序块”,一个程序块也就是一连串的语句或命令,例如一个源码文件或一行代码.Lua语句之间并不需要分隔符,如代码中的换行就不起任何作用,当然为了养成编码习惯当两条或者 ...

  6. Lua学习高级篇

    Lua学习高级篇 之前已经说了很多,我目前的观点还是那样,在嵌入式脚本中,Lua是最优秀.最高效的,如果您有不同的观点,欢迎指正并讨论,切勿吐槽.这个系列完全来自于<Programming in ...

  7. lua学习之复习汇总篇

    第六日笔记 1. 基础概念 程序块 定义 在 lua 中任何一个源代码文件或在交互模式中输入的一行代码 程序块可以是任意大小的 程序块可以是一连串语句或一条命令 也可由函数定义构成,一般将函数定义写在 ...

  8. lua学习之table类型

    关系表类型,这是一个很强大的类型.我们可以把这个类型看作是一个数组.只是 C语言的数组,只能用正整数来作索引: 在Lua中,你可以用任意类型的值来作数组的索引,但这个值不能是 nil.同样,在C语言中 ...

  9. php学习日志(5)-解决Windows Live Writer错误:WindowsLive.Writer.CoreServices.HttpRequestHelper的类型初始值设定发生异常

    以前用Windows Live Writer写日志都好好的,前几天用写完日志,点击发布,突然弹出意外错误:“WindowsLive.Writer.CoreServices.HttpRequestHel ...

随机推荐

  1. 写代码 Log 也要认真点么?

    Log自然是需要的, 尤其是正式的产品; 但如果只是自己或内部用用的小工具, 也需要认真点吗? 实话说, 自己对 log 总是不上心, 总觉得调试好了, 能跑了, 足以. 所以, 被大妈怼了好几次 l ...

  2. 啊哈!C语言课后参考答案下

    最近看到一本好评量很高的的C语言入门书,课本真的很好,入门的话.专业性没有那么强,但入门足够了!!好评!看着看着就想把这本书的题课后习题都写出来,最后就有了这个小结.可能有的不是最好,不那么专业,但主 ...

  3. HR系列GPS北斗时间同步服务器在电力系统典型应用

    HR系列GPS北斗时间同步服务器在电力系统典型应用 时间同步系统主要由主时钟.若干从时钟.时间信号传输介质组成.根据时间同步现场的不同要求,时间同步系统的结构配置有多种形式,主要分为三种:基本式.主从 ...

  4. HTTP,来一个详细的学习。

    HTTP 认识 HTTP 首先你听的最多的应该就是 HTTP 是一种 超文本传输协议(Hypertext Transfer Protocol),这你一定能说出来,但是这样还不够,假如你是大厂面试官,这 ...

  5. Tomcat的性能优化及JVM内存工作原理

    JVM性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收机制)代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容 1.增加最大连接数 2.调整工作 ...

  6. 解决RabbitMQ远程不能访问的问题

    刚刚安装的RabbitMQ-Server-3.3.5,并且也已经开启了Web管理功能,但是现在存在一个问题: 出于安全的考虑,guest这个默认的用户只能通过http://localhost:1567 ...

  7. ArcGIS Server for JavaScript 3.3 的安装部署

    一.安装包下载 首先从官网下载ArcGIS API for JavaScript 3.3 的API和SDK,地址:http://support.esrichina.com.cn/2011/0223/9 ...

  8. Linux查看端口监听占用

    # 查看所有 netstat -ntlp # 过滤PORT8080 netstat -ntlp | grep 8080 -t # 仅显示tcp相关选项 -u # 仅显示udp相关选项 -n # 拒绝显 ...

  9. 安装dbeaver,The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.

    在连接mysql时,出现了以下错误: 解决方法是 在数据库链接指定useUnicode=true&useSSL=false&characterEncoding=utf8&ser ...

  10. 缓存读写策略 - Cache Aside.md

    场景描述 比如一条数据同时存在数据库.缓存,现在你要更新此数据,你会怎么更新? 先更新数据库?还是先更新缓存? 其实这两种方式都有问题. (1)先更新数据库,后更新缓存 这样会造成数据不一致. A 先 ...