Lua中的Python“from some_module import *”

时间:2016-08-22 17:34:16

标签: module lua

在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中这样做吗?怎么样?

2 个答案:

答案 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)