【问题标题】:Declaring global variable inside a function in LUA在LUA中的函数内声明全局变量
【发布时间】:2016-12-16 19:37:27
【问题描述】:

我有一个函数,在其中我声明了一个全局变量obs,在一个函数内部并分配了一些值。如果我想在其他一些lua文件中访问它,它会给出一个错误:“尝试调用obs一个 nil 值,我需要做什么才能访问它?

这是它的虚拟代码

//A.lua
function X()
obs = splitText(lk,MAXLEN)
end

//B.lua
function Y()
for i=1, #obs do      //error at this line
end
end

【问题讨论】:

  • 如果你在 B.lua 之上有一个 require 语句,它调用 A.lua 就必须工作。并确保在调用函数 Y() 之前调用函数 X()。
  • 哦,有可能,splitText 提供 nil
  • 哦,不,不。 splitText 根本没有提供 NIL。实际上,还有其他存储价值的方法吗?我只是不能为 A.lua 做 require 声明(我在这里无法解释),但是对于我拥有的那种代码是不可能的。我只需要找到一种方法将这个值存储在 B.lua 中可以访问的某个地方
  • 很难理解你的设计。你有不同的选择,取决于你的设计。你可以直接从B中调用X,也可以在Y内部调用X。也许在X中返回obs会更好,所以你可以在Y中调用X并使用返回值。您也可以将函数 X 作为参数传递给函数 Y。
  • 你也可以写一个文件来存储obs,然后在B中读取,但我认为这是最糟糕的方式:)

标签: lua


【解决方案1】:

有几种方法可以做到这一点。使用您当前的设置,您可以这样做:

a.lua

function x()
    -- _G is the global table. this creates variable 'obs' attached to
    -- the global table with the value 'some text value'
    _G.obs = "some text value"
end

b.lua

require "a"
function y()
     print(_G.obs); -- prints 'some text value' when invoked
end

x(); y();

不过,在全局表中填充东西通常是一个糟糕的主意,因为其他任何地方的任何脚本都可能会覆盖该值、将变量归零等。imo 更好的方法是让您的 a.lua 返回其功能在一个表格中,您可以在需要它的文件中捕获该表格。这将允许您定义一个 getter 函数以返回直接附加到当前状态的“a.lua”功能的“obs”变量。

您可能想要做这样的事情以获得更好的可移植性(也更清楚哪些模块以这种方式定义了哪些功能):

a.lua

local obs_
function x()
    obs_ = "some text value"
end

function get_obs()
    return obs_
end

return { x = x, obs = get_obs }

b.lua

local a = require "a"
function y()
    print(a.obs())
end


a.x()
y()

因为你提到你不能使用 require,我假设你正在使用其他一些函数来加载库/文件的其他框架中工作。在这种情况下,您可能只需要将所有内容都填充到全局表中。也许是这样的:

a.lua

-- this will attach functions a_x and a_get_obs() to the global table
local obs_
function _G.a_x()
    obs_ = "some text value"
end

function _G.a_get_obs()
    return obs_
end

b.lua

-- ignore this require, i'm assuming your framework has some other way loading
-- a.lua that i can't replicate
require "a"

function y()
    print(_G.a_get_obs())
end


_G.a_x()
y()

【讨论】:

  • 问题是由于某种原因我不能在顶部需要“a”
  • 啊,没关系,我在上面看到了你的评论。我将更新一个将所有内容都粘贴在全局表中的答案,因为如果您正在以其他方式加载 lua 文件,这可能是您唯一的选择。
【解决方案2】:

请记住,其他程序(Garry's Mod、魔兽世界、Vera、Domoticz)中的一些 Lua 程序使用 _ENV 而不是 _G 来限制它们的范围。所以全局变量必须是:

_ENV.variable = 1

代替:

_G.variable = 1

之所以会这样,是因为开发者想限制标准的Lua库,避免用户访问方法如:os.exit()。

要查看是否使用 _ENV 而不是 _G,请将其打印出来,如果它返回一个表而不是 nil,则很可能使用它。你也可以用下面的sn-p进行测试:

print(getfenv(1) == _G)
print(getfenv(1) == _ENV)

要打印的那个是你正在使用的那个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-11
    • 2012-09-01
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2015-05-11
    相关资源
    最近更新 更多