lua之文件加载require、loadfile、dofile、load、loadstring的用法及区别

目录

1.load

2.loadfile

3.dofile

4.require


1.load

同loadstring,5.2版本之后loadstring被移除,用load代替

load(chunk, chunkname, mode, env) 用于加载字符串代码块,参数如下:

chunk字符串代码块
chunkname模块名,默认是"chunk",当使用assert函数报错后会被打印出来
mode文件类型:"b":二进制;"t":文本文件;"bt":同时兼容二进制和文本文件,不填默认是"bt"
env环境变量,不填默认会用_ENV填充,附带lua标准类库

这里要注意:load用于加载字符串代码块并编译,但是并没有运行。在使用前要记得运行一下,参见如下:

a = 100
--加载字符串代码块
f = assert(load("a = a + 100"))
print("before a = "..a)
--运行代码块
f()
print("after  a = "..a)

输出如下:

before a = 100
after  a = 200

可以看到加载代码块后,在没有运行前,a的值没有发生变化为100,运行后执行了a = a + 100,a = 200

1.代码块chuck如何理解?

lua中的代码块chunk,实际编译的时候,相当于被一个可变参匿名函数包装,并且会绑定一个唯一的upvalue值_ENV,运行后将代码块chunk中的全局变量添加到了全局环境变量_ENV中。代码块 "a = a + 100" 相当于如下函数:

--代码块
function chuck()
    a = a + 100
end
--这句是比喻load代码块的加载编译过程(不一定恰当,意会就好)
f = chuck()
--运行
f()

2.这里有些同学可能会疑惑,load中的这段代码块为什么能访问到外部的变量a?

env:它是一个环境变量,可以自定义(一般用于模拟一个沙盒环境),默认这个值会用lua的全局环境变量_ENV填充。

_ENV是lua5.2版本才有的用来代替_G的一个全局变量(_ENV内部是指向_G的,可以简单的认为他们是同一个东西),但它是一个upvalue值。(_G及_ENV感兴趣的可以自行了解)这里简单描述一下_ENV,每一个lua代码块默认都会有一个_ENV全局环境变量,它是一个表,包含了所有的lua标准类库及所有编译过的全局变量。

参见如下:

a = 100
--加载并运行字符串代码块
assert(load("a = a + 11; b = 'b126'; print('this is chunk')"))()
print("a = "..a)
print("_ENV.a = ".._ENV.a)
print("b = "..b)
print("_ENV.b = ".._ENV.b)

输出如下:

this is chunk
a = 111
_ENV.a = 111
b = b126
_ENV.b = b126

可以看到:

1) 代码块中,可以调用print函数,这就是因为默认env传入的是_ENV,相当于调用_ENV.print

2) a 和 _ENV.a 输出相同,其实在编译的时候,全局变量默认都会在前面加一个_ENV.限定

3) 编译并运行代码块chunk后,变量b已被加入到_ENV中

3.自定义环境变量env的使用

一般用于模拟一个沙盒环境,参见如下:

a = 100
--自定义环境变量
local env = {
    a = 8,
    print = print
}
--加载并运行字符串代码块
assert(load("a = a + 10; print('this is chunk, a = '..a)", "chunkTest", "bt", env))()
print("a = "..a)

输出如下:

this is chunk, a = 18
a = 100

1) 可以看到代码块chunkTest中,a取的是自定义环境变量env的a值,打印a = 18;

2) 因为这里没有用默认全局环境变量_ENV填充,所以外部变量 a 并没有被修改: a = 100

3) env中的 print = print,等价于:print = _ENV.print

2.loadfile

loadfile(filename, mode, env) 用于加载一个指定路径filename的代码块,参数如下:

filename文件的加载路径,要包含文件后缀
mode文件类型:"b":二进制;"t":文本文件;"bt":同时兼容二进制和文本文件,不填默认是"bt"
env环境变量,不填默认会用_ENV填充,附带lua标准类库

基本和load等同,区别是用来加载一个文件的代码块,参见如下:

LuaFunc.lua(被访问)文件:

--LuaFunc.lua
function add(x, y)
    return x + y
end

m = "LuaFunc.m"
local n = "n"

print("------------------ < LuaFunc.lua > ------------------")
print("m = "..m)
print("n = "..n)
print("------------------ < LuaFunc.lua > ------------------")

调用代码如下:

--加载并编译代码
f = assert(loadfile("Child/LuaFunc.lua"))
--运行
f()
print("add : "..add(100, 88))
print(m)

输出如下:

------------------ < LuaFunc.lua > ------------------
m = LuaFunc.m
n = n
------------------ < LuaFunc.lua > ------------------
add : 188
LuaFunc.m

3.dofile

dofile(filename) 用于加载一个指定路径filename的代码块,并运行。参数如下:

filename文件的加载路径,要包含文件后缀

内部先调用了loadfile,然后会自动运行一下,参见如下:

dofile("Child/LuaFunc.lua")
print("add : "..add(100, 88))
print(m)

输出与上例等同

4.require

require(modname) 用于加载一个指定的代码块,并运行。参数如下:

modname文件名,不包含后缀

这个函数对于同一个代码块只会加载一次(加载过会保存起来),和dofile类似,加载编译后也会自动运行,参见如下:

--加载编译并运行
require("Child/LuaFunc") -- 等同于:require("Child.LuaFunc")
print("add : "..add(100, 88))
print(m)

输出同上例

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值