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

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)

输出同上例

相关推荐

“七夕情人节送出红包的合理金额是多少”?
32斤等于多少公斤

32斤等于多少公斤

07-24 💫 7215
如何将EXCEL表格的内容导入到CorelDRAW中
猫牙齿对照表全图(猫牙齿图片解剖)

本文标签