2017-07-23 33 views
1

我想實現在Lua一類,這是應該被實例化的第一個參數。但是,在輸入參數BatchLoader.init的輸入參數發生偏移時出現錯誤。我是否缺少將self關鍵字作爲參數輸入到Python中的任何成員函數中,或者類定義是否還有其他錯誤?的Lua:類方法跳過

整個classcode看起來像這樣(我剝出不重要的事情):

function BatchLoader:new() 
    setmetatable({}, BatchLoader) 
    self.epoch_done = false 
    return self 
end 

function BatchLoader:init(X, y, sids, batch_size, argshuffle)  
    print("In batchloader") 
    print(X:size()) -- Prints size(62000, 1) [which is 'y'] 
    print(y:size()) -- Prints size(62000, 1) [which is 'sids'] 
    print(sids)  -- Prints '10'   [which is 'batch_size'] 
end 

但是,當我創建這個類,然後調用函數BatchLoader.init似乎y被解釋爲X,Y被解釋爲sids等。因此,batch_size的輸入被解釋爲sids,其中每個參數都從實際參數'移開'。

下面的代碼是我正確的進入是BatchLoader.init之前調用。這裏的一切都按預期打印。

local BatchLoader = require "../datahandler/BatchLoader.lua" 
local trainLoader = BatchLoader:new() 
print(X_data[{{1, 62000}, {}, {}}]:size()) -- Prints size(62000, 8, 16) 
print(y_data[{{1, 62000}, {}}]:size())  -- Prints size(62000, 1) 
print(sid_data[{{1, 62000}, {}}]:size()) -- Prints size(62000, 1) 

local X_train, y_train, sid_train = trainLoader.init(
    X_data[{{1, a}, {}, {}}], 
    y_data[{{1, a}, {}}], 
    sid_data[{{1, a}, {}}], 
    10, true) 

我的問題是:那裏的類聲明有什麼問題嗎?這是我在Lua的第一個OOP代碼,所以任何想法或幫助表示讚賞! :)

+1

你已經用冒號(不帶點)定義了'BatchLoader:init',所以你必須使用帶有冒號的'trainLoader:init'。 –

+0

非常感謝,我的錯誤,太愚蠢了! – DaveTheAl

+0

您還可以編寫如下代碼:function Foo.init(...)local _,a,b if ... == Foo then _,a,b = ... else a,b = ... end print (a,b)結束' – moteus

回答

4

在Lua中,這句法:

o:f(x, y) 

是語法糖這樣的:

o.f(self, x, y) 

這對於定義和調用正確的。這裏你用冒號語法定義了init,並用點語法來調用它,所以它不起作用,因爲第一個參數將變成self,而其他參數將被關閉。一種解決方法是調用init這樣的:

local X_train, y_train, sid_train = trainLoader:init(
    X_data[{{1, a}, {}, {}}], 
    y_data[{{1, a}, {}}], 
    sid_data[{{1, a}, {}}], 
    10, true) 

這解決了這個問題,但請注意,在你的榜樣構造也完全打破。因爲您使用冒號語法來定義它,它將始終返回BatchLoader表本身而不是新實例。既然是一個類的方法,你應該寫它,用點語法調用它:

function BatchLoader.new() 
    local self = setmetatable({}, BatchLoader) 
    self.epoch_done = false 
    return self 
end 

或者乾脆:

local trainLoader = BatchLoader.new() 

function BatchLoader.new() 
    return setmetatable({epoch_done = false}, BatchLoader) 
end 

然後,你還用點語法調用它

要了解那些東西,如果你還沒有這麼做過,我強烈建議你買編程的Lua中的最新版本的副本和閱讀的面向對象編程的部分。

3

方法語法(使用foo:bar而不是foo.bar)自動引入self參數。

在函數定義,function Foo:bar(...)相當於function Foo.bar(self, ...)。上的函數調用,foo:bar(...)大致相當於foo.bar(foo, ...)(後者求值foo兩次)。

因此,讓我們來剖析代碼:

function BatchLoader:new() 
    setmetatable({}, BatchLoader) -- creates a table & throws it away 
    self.epoch_done = false  -- self is the hidden first argument 
    return self 
end 

local trainLoader = BatchLoader:new() -- i.e. BatchLoader.new(BatchLoader) 

這意味着你有效運行

function BatchLoader:new() 
    setmetatable({}, BatchLoader) 
    BatchLoader.epoch_done = false 
    return BatchLoader 
end 

這肯定不是你想要的。幾種方法可以做到你可能想什麼

-- fixed creation scheme 
function BatchLoader.new() 
    local self = { epoch_done = false } 
    return setmetatable(self, BatchLoader) 
end 

-- acceptable uses: 
local trainLoader = BatchLoader.new() 
local trainLoader = BatchLoader:new() -- ignores passed self 

-- permit passing base object 
function BatchLoader:new() -- equivalently: BatchLoader.new(self) 
    self = self or { } -- use passed table or create new 
    self.epoch_done = false 
    return setmetatable(self, BatchLoader) 
end 

-- acceptable uses: 
local trainLoader = BatchLoader.new() -- creates from scratch 
local trainLoader = BatchLoader.new { n = 23 } -- re-uses this table 
-- WRONG uses: 
local trainLoader = BatchLoader:new() -- reuses BatchLoader class as object 

或許多其他的選擇。

你同樣混了其他調用方法符號:

function BatchLoader:init(X, y, sids, batch_size, argshuffle) 

是罰款和相當於

function BatchLoader.init(self, X, y, sids, batch_size, argshuffle) 

你,然後錯誤地調用作爲

local X_train, y_train, sid_train = 
    trainLoader.init(X, y, ...) 

(看看爲什麼一切都轉移了?)

使用trainLoader:init(X, y, ...)通過trainLoader作爲self

+0

這真是太好了! :) – DaveTheAl