今天来聊两个话题——全局变量和非全局环境。
正如大家目前心里所感受到的,全局变量的内容很简单,而非全局环境的内容就稍微要锻炼一下脑细胞了。
1.全局变量的原形
在Lua中,要声明全局变量很简单,那就是定义变量的时候,前面不要加上local。
这个神秘的全局变量,其实本质上也是一个table,它把我们创建的全局变量都保存到一个table里了。
而这个table的名字是:_G
我们来看看代码:
-- 定义一个全局变量 gName = "哎哟,很挫哦"; -- 用三种方式输出变量的值 print(gName); print(_G["gName"]); print(_G.gName);
输出结果如下:
[LUA-print] 哎哟,很挫哦 [LUA-print] 哎哟,很挫哦 [LUA-print] 哎哟,很挫哦
2.非全局的环境
对于全局变量,不管到了哪个地方,哪种语言,大家总是会告诫说:“不要滥用,后果自负”
也许是因为这样,所以Lua有了一种比较特殊的机制:非全局环境。
我称它为“不会造成全局影响的全局变量”。
3.改变函数的全局变量环境——setfenv函数
先看看以下代码:
-- 定义一个全局变量 gName = "哎哟,很挫哦"; -- 将当前全局环境重新设置为新的table setfenv(1, {}); -- 输出值 print(gName);
[LUA-print] LUA ERROR: [string "src/main.lua"]:107: attempt to call global ‘print' (a nil value)
这是因为我们已经把当前函数范围内的全局变量环境改变了,全局变量默认是保存在_G中的,而现在的全局变量是在一个新的table里。
目前这个table是空的,所以不存在任何全局变量。
setfenv函数就是用来改变某个函数范围里的全局环境的,通俗地说,就是把某个函数范围内的_G给弄没了。
setfenv函数两个参数分别代表:
1). 第一个参数,可以是即将要改变环境的函数,也可以是一个数字。数字1代表当前函数,数字2代表调用当前函数的函数,后面以此类推。
2).第二个参数,新的全局环境table。
4.保留原来的_G
现在连print函数都无法使用了,对于测试很不方便,我们可以做个小动作,把原来的_G保留起来。
如下代码:
-- 定义一个全局变量 gName = "哎哟,很挫哦"; -- 将当前全局环境重新设置为新的table setfenv(1, {g = _G}); -- 输出值 g.print(gName); -- 再次定义一个全局变量 gName = "哎哟,有点错哦"; -- 再次输出值 g.print(gName); -- 输出原来的值 g.print(g.gName);
只要在定义新的环境时,把_G作为一个字段放到新的table里,就可以调用原来的全局变量了。
那么,输出结果如下:
[LUA-print] nil [LUA-print] 哎哟,有点错哦 [LUA-print] 哎哟,很挫哦
a.第一次,此时刚刚重新设置了全局环境,这时候当前函数的全局变量只有一个,那就是g,所以gName的值是nil。
b.第二次,我们再一次对gName进行赋值,此时,已经在新的环境中了,所以接下来输出的gName值是存在的。
c.第三次,这次输出的是g.gName的值,通过g调用的gName值是原先的全局环境里的值,所以gName的值仍然是最初的“哎哟,很挫哦”。
其实,这有什么用呢?倒不如直接用局部变量好了。
确实,从这例子里看不出什么特别的地方。
书里对于知识的介绍都是由浅入深的,所以这里暂时也没有更深入的介绍,看到后面内容的时候,我再继续和大家分享。
5.使用__index元方法保留原来的_G
这里还有一个小技巧分享一下,刚刚举例保留_G,但是调用print等函数时还需要形如g.print的方式,有点碍事。
我们可以利用__index来解决这个问题,如下代码:
-- 定义一个全局变量 gName = "哎哟,很挫哦"; -- 一个table,即将成为新的环境 local newG = {}; setmetatable(newG, {__index = _G}); -- 将当前全局环境重新设置为新的table setfenv(1, newG); gName = "别再哎哟了,很烦!"; -- 输出值 print(gName); print(_G.gName);
我们给新的table设置一个元表,这个元表的__index元方法就是_G。
于是,当新的环境里找不到print字段时,就会去_G里寻找。
输出结果如下:
[LUA-print] 别再哎哟了,很烦! [LUA-print] 哎哟,很挫哦
6.结束
好了,关于全局变量和非全局环境,就暂时说这么多。
虽然暂时还感觉不到有什么作用,没关系,后面还会有关于这部分的内容。
就像__index一样,是基础,后面可能会经常提到。
本文向大家介绍Lua中的全局变量、非全局变量总结,包括了Lua中的全局变量、非全局变量总结的使用技巧和注意事项,需要的朋友参考一下 前言 Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”。这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现;另一个优点是,可以像其他table一样操作这个table。为了便于实施这种操作,L
问题内容: 我了解Python中局部变量和全局变量的概念,但是我只是有一个问题,为什么下面的代码中会出现错误?Python逐行执行代码,因此在读取第5行之前,它不知道a是局部变量。Python尝试执行第5行后,会回退一行并将其标记为错误吗? 问题答案: 设置和测试 为了分析您的问题,让我们创建两个独立的测试函数来复制您的问题: 版画。因此,调用此函数不是问题,而是在下一个函数上: 我们收到一个错误
我需要在我所有的idea运行配置中使用一个环境变量。我目前使用run- 我试图设置env变量在我的linux系统使用在各种会话配置文件:,,,但是intellij在运行过程中似乎忽略了这些变量,即使当我从intellij内置终端启动时,它显示了正确的输出。 我也尝试使用intellij. env文件插件,然后设置在文件在项目根。也没起作用。
如果你要多于一个函数共用一个简单的变量,简单的处理方法就是把这个变量在所有函数中定义为global全局变量。在命令行做同样的事情,如果你要工作空间访问上述变量。这个全局变量的定义必须出现在变量被应用于一个函数之前。虽然不是要求,但全局变量也最好以大写字母开头,这样可以同其他变量区别出来。举个例子,做一个以falling.m命名的M-文件。 function h = falling(t) globa
ThinkCMF封装了前台模板开发时常用的一些变量,这些变量是全局的,你在前台模板任何时候都能直接调用: {$site_name} /站点名称 {$site_host} /站点域名 {$site_root} /安装目录 {$site_icp} /
swoole内置了几个全局变量供程序内使用。一般不要自行创建全局变量。 SwooleG 超全局本地内存变量,此变量在swoole_init时就初始化好了。存储了一些全局的信息。但不是共享内存的。当创建子进程后再修改其中的字段,其他进程是感知不到的 SwooleG.main_reactor,全局事件循环 SwooleG.lock,全局锁 SwooleG.memory_pool,全局共享内存池 Swo