当前位置:网站首页>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。
边栏推荐
- [gwctf 2019] boring lottery
- [actf freshmen 2020] crypto AES
- BUUCTF-bbbbbbrsa
- [GWCTF 2019]BabyRSA1
- Starfish OS X metabell strategic cooperation, metauniverse business ecosystem further
- 基于mediapipe的姿态识别和简单行为识别
- 给网站套上Cloudflare(以腾讯云为例)
- Use of date
- Posture recognition and simple behavior recognition based on mediapipe
- Smartrefresh nested multiple recycleview sliding conflicts and incomplete layout display
猜你喜欢

Starfish OS X metabell strategic cooperation, metauniverse business ecosystem further

(十二)51单片机----用DS18B20浅测一下工(江)西的室外温度

窗口函数over

给网站套上Cloudflare(以腾讯云为例)

(12) 51 Single Chip Microcomputer -- use DS18B20 to measure the outdoor temperature in Gongjiang West

五子棋人机对战实现

如果我们是那晚负责修复 B 站崩了的开发人员

Realization of gobang man-machine combat

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

TCP sticking and unpacking problem + Solution
随机推荐
BUUCTF-RSA4
BUUCTF-bbbbbbrsa
How Flink uses savepoint
基于mediapipe的姿态识别和简单行为识别
[GWCTF 2019]枯燥的抽奖
BUUCTF-Baby RSA
BUUCTF-childRSA费马小定理
Flutter pull_ to_ refresh-1.6.0/lib/src/internals/slivers. dart:164:13: Error: Method not found: ‘descr
4小时定单破20000+,自称“百万内最豪华”,国产品牌飘了?
MapReduce (III)
What is the prospect of low code development? Are you really optimistic about low code development?
[GWCTF 2019]BabyRSA1
MQTT----mqtt.fx客户端软件
If we were the developer responsible for repairing the collapse of station B that night
BUUCTF-RSA roll
Starfish OS X metabell strategic cooperation, metauniverse business ecosystem further
UE4 official AEC blueprint case course learning notes
面试官问线程安全的List,看完再也不怕了!
Arm32进行远程调试
TCP sticking and unpacking problem + Solution