在Python中,我可以编写from my_module import *
,my_module
的所有成员都可以在本地范围内使用。 e.g。
我的模块定义:
my_module = {}
my_module.a = 1
my_module.b = 2
在另一个档案中使用:
from my_module import *
return a + b
#=> 3
我可以在Lua中这样做吗?怎么样?
答案 0 :(得分:1)
要在本地范围内获得这些价值,您唯一的选择就是实际上让他们感到遗憾:
--in main.lua
local mymodule = require("mymodule")
local a, b = mymodule.a, mymodule.b
--in mymodule.lua
return {a = 1, b = 2}
或者,或者:
--in main.lua
local a, b = table.unpack(require("mymodule"))
--in mymodule.lua
return {1, 2}
如果您不想实际命名它们,那么唯一的方法就是将它们放在全局范围内。以下是两个例子:
--Python's from mymodule import *
--in main.lua
require("mymodule")
print(a + b)
--in mymodule.lua
a, b = 1, 2
--Python's import mymodule
--in main.lua
require("mymodule")
print(mymodule.a + mymodule.b)
--in mymodule.lua
mymodule = {a = 1, b = 2}
这些都是有效的方法,但最常用和安全的是第一种。
另一种可能性是尝试更改环境,修改_ENV
值:
--Python's from mymodule import *
--in main.lua
local _ENV = require("mymodule")
--in mymodule.lua
return {a = 1, b = 2}
但是,通过更改环境,您将无法访问全局范围中的所有变量(除非您将它们预先声明为本地(local print = print; _ENV = require("mymodule"); print(a);
),或者从{复制所有变量) {1}}从_G
返回的表格的表格,这通常不是一件快乐的事情。
答案 1 :(得分:0)
这不是完全可以实现的,因为修改local
值(debug.setlocal
无法定义新的本地人)是不完美的。最好的办法是调整你的环境,因为污染全球范围并不是一个好主意,但这不是一件容易的事。
如果仔细完成,这实际上可以优雅地完成有点。我有点说,因为总会有一点需要注意,你必须手动调整环境以适应你所处的任何功能/块。在Lua 5.2+中,local _ENV = ...
是必需的。在Lua 5.1中,setfenv(1, ...)
可以做到这一点,并且在眼睛上可以说更容易。
这是我们能做的。我们首先定义一个返回克隆环境的函数。 clone
是浅表复制功能。
return function (env)
env = clone(env or _G)
return env
end
接下来,我们添加自定义import
函数,直接修改我们的新环境,而不是返回任何内容(例如require
)。您可以在这里获得好的和复杂的,实现不同的方法来决定将哪些内容导入到环境中,以及如何导入。 (例如''')
-- @module: import.lua
return function (env)
env = clone(env or _G)
function env.import (modname, ...)
local args = { ... }
local m = require(modname)
for _, name in next, args
env[name] = m[name]
end
end
return env
end
我们可以用作:
local _ENV = require('import')()
-- setfenv(1, require('import')())
import('module_name', 'a', 'b')
return a + b
在小规模上,这是一个相当大的开销,只是为了避免:
local module_name = require('module_name')
local a, b = module_name.a, module_name.b
对于包含许多导入的大型文档,它可能更有用。进口通常以任何方式聚集在文档的顶部,因此额外的噪音并不是那么糟糕。如果您可以将env
设置为某个地方的全局值,它看起来会更清晰。
local _ENV = env()
import('webserver', 'open', 'status', 'close')
import('database', 'connect', 'query', 'disconnect')
import('json', 'parse', 'stringify')
...
也可以用来创建沙箱,假设在重写import
函数时不小心使用require
!
local my_env = env { print = print }
my_env.import('my_mod', 'foo', 'bar')
local chunk = loadfile('my_file.lua', 'bt', my_env)