Torch类的__index设置

是否可以为torch类设置__index方法?我尝试按照Torch教程中的示例实现一个简单的数据集类:(ipynb在这里

trainset = {
    inputs = {0, 1, 1, 0},
    targets = {1, 1, 1, 0}
}

index = function(t, i)
    return {t.inputs[i], t.targets[i]}
end

setmetatable(trainset, {
    __index = index
)

这样就可以用trainset[1]返回{0, 1}

然而,将其实现为torch类却不起作用。

local torch = require("torch")

do
    Dataset = torch.class("Dataset")

    function Dataset:__init(i, t)
        self.inputs = i
        self.targets = t
    end

    function Dataset.__index(t, v)
        print("inside index")
        return {
            rawget(t, inputs)[v],
            rawget(t, targets)[v]
        }
    end
end

Dataset({0, 1, 1, 0}, {1, 1, 1, 0}) -- 失败

似乎在对象创建时会调用__index()并因为index和targets尚未创建而失败。如果不使用rawget,那么它会导致堆栈溢出。

我对Lua的理解有限,但我很惊讶地看到__index()在对象创建期间被调用:我认为有些我尚未完全理解的事情正在发生。

点赞
用户4412981
用户4412981

Torch 中的所有类都实现了__index,它将在元表中查找__index__,以进行重载。

docs

如果想在元类中提供indexnewindex,这些运算符必须遵循特定的方案:

index 必须返回一个值和 true,或者仅返回 false。在第一种情况下,这意味着index能够处理给定的参数(例如,类型是正确的)。第二种情况意味着它无法做任何事情,因此根元表中的__index可以尝试查找元类是否包含所需的值。

这意味着对于示例,__index__(而不是__index!)方法必须检查type(v) == "number",如果不是,则返回false,以便__index可以在对象元表中查找该值。

local torch = require("torch")

do
    Dataset = torch.class("Dataset")

    function Dataset:__init(i, t)
        self.inputs = i
        self.targets = t
    end

function Dataset.__index__(t, v)
    if type(v) == "number" then
        local tbl =  {
            t.inputs[v],
            t.targets[v]
        }
        return tbl, true
    else
        return false
    end
end

local dset = Dataset({0, 1, 1, 0}, {1, 1, 1, 0})
dset[1] --> {0, 1}
2016-11-10 15:26:56