【问题标题】:Python's "from some_module import *" in LuaLua 中 Python 的“from some_module import *”
【发布时间】:2016-08-24 11:26:46
【问题描述】:

在 Python 中,我可以编写 from my_module import * 并且 my_module 的所有成员都将在本地范围内可用。例如

我的模块定义:

my_module = {}
my_module.a = 1
my_module.b = 2

在另一个文件中使用:

from my_module import *
return a + b
#=> 3

我可以在 Lua 中执行此操作吗?怎么样?

【问题讨论】:

  • local my_module = require("my_module"); local a, b = my_module.a, my_module.b; return a+b
  • 那更像是from my_module import a, b。如果我要导入(极端示例)500 件东西怎么办?我宁愿不手动导入所有这些。

标签: module lua


【解决方案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);),或者您从 _G 复制所有变量从mymodule返回的表),这通常不是一件令人高兴的事情。

【讨论】:

    【解决方案2】:

    这不是完全可以实现的,因为修改 local 值(debug.setlocal 不能定义 new 局部变量)是不完美的。最好的办法是调整您的环境,因为污染全局范围不是一个好主意,但这并非不重要。

    这实际上可以在某种程度上优雅地完成,如果仔细完成的话。我有点说,因为总会有一个警告,你必须为你所在的任何功能/块手动调整你的环境。在 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)
    

    【讨论】:

      猜你喜欢
      • 2014-07-21
      • 2018-12-09
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      相关资源
      最近更新 更多