当前位置:网站首页>require、loadfile、dofile、load、loadstring
require、loadfile、dofile、load、loadstring
2022-07-27 21:24:00 【森明帮大于黑虎帮】
1.loadfile只编译,不运行loadfile(filename, mode, env) 用于加载一个指定路径filename的代码块,参数如下:
基本和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
loadfile:只编译,不运行,它只会加载文件,编译代码,不会运行文件里的代码,loadfile只会加载(load)lua文件但是不会执行(run)。比如,我们有一个hellofile.lua文件:
print(“hello”);
function hehe()
print(“hello”);
end
这个文件里有一句代码,和一个函数。试试用loadfile加载这个文件,如下代码:
loadfile("hellofile.lua");
print("end");
输出结果如下:
end
如果说loadfile会执行文件里的代码的话,那么,应该会输出hello字符串的。结果表明,它是不会执行代码的。
2.dofile执行dofile(filename) 用于加载一个指定路径filename的代码块,并运行。参数如下:
内部先调用了loadfile,然后会自动运行一下,参见如下:
dofile("Child/LuaFunc.lua")
print("add : "..add(100, 88))
print(m)
输出与上例等同。
- 执行
dofile就是执行代码,dofile与require类似,但是它没有caching已经执行过一次的文件,所以它可以重复执行多次。很明显,dofile就是会执行代码的家伙了,如下代码:
dofile("D:/vscode lua代码/hello world/foo.lua");
print("end");
输出结果如下:
hello
end
3.require我只执行一次
require(modname) 用于加载一个指定的代码块,并运行。参数如下:
这个函数对于同一个代码块只会加载一次(加载过会保存起来),和dofile类似,加载编译后也会自动运行,参见如下:
--加载编译并运行
require("Child/LuaFunc") -- 等同于:require("Child.LuaFunc")
print("add : "..add(100, 88))
print(m)
输出与上例等同。
require和dofile有点像,不过又很不一样,require在第一次加载文件的时候,会执行里面的代码。但是,第二次之后,再次加载文件,则不会重复执行了。换句话说,它会保存已经加载过的文件,不会重复加载。require的返回值会被存储cache起来,所以一个文件最多只会执行一次,即使被require很多次。
for i = 1, 2, 1 do
require("foo.lua");
end
print("end");
为了说明这种情况,我刻意调用了两次require,输出结果如下:
hello
end
和我们说的一样,调用了两次,但是代码只执行了一次。如果这里换成dofile,则会输出两次hello字符串。
4.load用于加载字符串代码块
同loadstring,5.2版本之后loadstring被移除,用load代替,load(chunk, chunkname, mode, env) 用于加载字符串代码块,参数如下:
这里要注意: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。
5.代码块chuck如何理解lua中的代码块chunk,实际编译的时候,相当于被一个可变参匿名函数包装,并且会绑定一个唯一的upvalue值_ENV,运行后将代码块chunk中的全局变量添加到了全局环境变量_ENV中。代码块 “a = a + 100” 相当于如下函数:
--代码块
function chuck()
a = a + 100
end
--这句是比喻load代码块的加载编译过程(不一定恰当,意会就好)
f = chuck()
--运行
f()
这里有些时候可能会疑惑,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
可以看到:
代码块中,可以调用
print函数,这就是因为默认env传入的是_ENV,相当于调用_ENV.print。a和_ENV.a输出相同,其实在编译的时候,全局变量默认都会在前面加一个_ENV.限定。编译并运行代码块
chunk后,变量b已被加入到_ENV中。
自定义环境变量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
可以看到代码块
chunkTest中,a取的是自定义环境变量env的a值,打印a = 18;因为这里没有用默认全局环境变量
_ENV填充,所以外部变量a并没有被修改:a = 100env中的 print = print,等价于:print = _ENV.print。
边栏推荐
- [NCTF2019]babyRSA1
- [development tutorial 11] crazy shell arm function mobile phone timer experimental tutorial
- [actf freshmen 2020] crypto AES
- 2022/7/24-7/25
- [GWCTF 2019]BabyRSA1
- Redis hash underlying data structure
- How to use C WinForm to copy files and display progress
- If we were the developer responsible for repairing the collapse of station B that night
- 【Objective-C语言的SEL对象】
- (十二)51单片机----用DS18B20浅测一下工(江)西的室外温度
猜你喜欢

【飞控开发基础教程6】疯壳·开源编队无人机-SPI(六轴传感器数据获取)

Master data management theory and Practice

BUUCTF-RSA4

Is it really hard to understand? What level of cache is the recyclerview caching mechanism?

BUUCTF-RSA roll

Introduction to several common usage scenarios of message queue

C语言实现五子棋游戏

Explain the idempotence of distributed system in detail

Latex常用总结(2):输入矩阵(输入矩阵、对角阵、方程组等)

The 4-hour order exceeds 20000+, claiming to be "the most luxurious in a million". Is the domestic brand floating?
随机推荐
传奇外网架设教程带图文解说——Gom引擎
[geek challenge 2019] rce me
J9数字科普:Sui网络的双共识是如何工作的?
Posture recognition and simple behavior recognition based on mediapipe
CPU的控制方式
BUUCTF-[BJDCTF2020]RSA1
[NCTF2019]babyRSA1
Redis hash underlying data structure
Notes on Shangpin project in shangsilicon Valley (I)
How to use FTP to realize automatic update of WinForm
Liux common commands (view and open firewall port number + view and kill process)
Assertion mechanism in test class
[development tutorial 11] crazy shell arm function mobile phone timer experimental tutorial
【开发教程9】疯壳·开源蓝牙心率防水运动手环-心率监测
窗口函数over
JS提升:JS中的数组扁平化问题
尚硅谷尚品项目汇笔记(一)
[unity] mapping 2D coordinates to ID
What are the software operation and maintenance monitoring?
很棒的一个思维题CF1671D Insert a Progression