Lua教程(十): 全局变量和非全局的环境

(编辑:jimmy 日期: 2024/12/24 浏览:2)

Lua将其所有的全局变量保存在一个常规的table中,这个table被称为“环境”。它被保存在全局变量_G中。

1. 全局变量声明:

Lua中的全局变量不需要声明就可以使用。尽管很方便,但是一旦出现笔误就会造成难以发现的错误。我们可以通过给_G表加元表的方式来保护全局变量的读取和设置,这样就能降低这种笔误问题的发生几率了。见如下示例代码:
复制代码 代码如下:
--该table用于存储所有已经声明过的全局变量名
local declaredNames = {}
local mt = {
    __newindex = function(table,name,value)
        --先检查新的名字是否已经声明过,如果存在,这直接通过rawset函数设置即可。
        if not declaredNames[name] then
            --再检查本次操作是否是在主程序或者C代码中完成的,如果是,就继续设置,否则报错。
            local w = debug.getinfo(2,"S").what
            if w ~= "main" and w ~= "C" then
                error("attempt to write to undeclared variable " .. name)
            end
            --在实际设置之前,更新一下declaredNames表,下次再设置时就无需检查了。
            declaredNames[name] = true
        end
        print("Setting " .. name .. " to " .. value)
        rawset(table,name,value)
    end,
   
    __index = function(_,name)
        if not declaredNames[name] then
            error("attempt to read undeclared variable " .. name)
        else
            return rawget(_,name)
        end
    end
}   
setmetatable(_G,mt)

a = 11
local kk = aa

--输出结果为:
--[[
Setting a to 11
lua: d:/test.lua:21: attempt to read undeclared variable aa
stack traceback:
        [C]: in function 'error'
        d:/test.lua:21: in function <d:/test.lua:19>
        d:/test.lua:30: in main chunk
        [C]: "codetitle">复制代码 代码如下:
a = 1
setfenv(1,{})
print(a)

--输出结果为:
--[[
lua: d:/test.lua:3: attempt to call global 'print' (a nil value)
stack traceback:
        d:/test.lua:3: in main chunk
        [C]: "codetitle">复制代码 代码如下:
a = 1
local newgt = {}  --新环境表
setmetatable(newgt,{__index = _G})
setfenv(1,newgt)
print(a)  --输出1

a = 10
print(a)  --输出10
print(_G.a) --输出1
_G.a = 20
print(a)  --输出10

最后给出的示例是函数环境变量的继承性。见如下代码:
复制代码 代码如下:
function factory()
    return function() return a end
end
a = 3
f1 = factory()
f2 = factory()
print(f1())  --输出3
print(f2())  --输出3

setfenv(f1,{a = 10})
print(f1())  --输出10
print(f2())  --输出3

一句话新闻

一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?