2017-06-28 97 views
2

我試圖通過在Jamis Buck中翻譯程序員迷宮中的代碼來教自己Python。這是一本很棒的書,但它是用Ruby編寫的,而且我在理解一些Ruby代碼時遇到困難。使用yield語句將Python循環迭代轉換爲Python

要理解這個問題,我已經包括了代碼庫的縮小版本

cell.rb

class Cell 
    attr_reader : row, :column 

def initialize(row, column) 
    @row, @column = row, column 
end 

grid.rb

require 'cell' 
class Grid 
    attr_reader :rows, :columns 

def initialize(rows, columns) 
    @rows = rows 
    @columns = columns 
    @grid = prepare_grid 
end 

def prepare_grid 
    Array.new(rows) do |row| 
    Array.new(columns) do |column| 
     Cell.new(row, column) 
    end 
    end 
end 

到目前爲止好。以上所有內容都很容易理解並轉化爲Python。然後有以下兩個函數作爲Grid類的一部分。

def each_row 
    @grid.each do |row| 
    yield row 
    end 
end 

def each_cell 
    each_row do |row| 
    row.each do |cell| 
     yield cell if cell 
    end 
    end 
end 

這裏實際做的最後兩個函數是什麼?我發現了類似的here,這導致我認爲Python版本需要接受可選的lambda變量,測試它是否爲空,如果不是,則運行與該變量關聯的代碼。問題是我知道這些函數的意圖是一個迭代器,我不認爲添加lambda會有幫助。

StackOverflow上已經有一個類似的問題here,這讓我覺得答案是微不足道的,但是我不太瞭解Ruby能夠直觀答案或向Google詢問正確的問題。

回答

4

然後有以下兩個函數作爲Grid類的一部分。

這些都不是功能。他們是方法。

def each_row 
    @grid.each do |row| 
    yield row 
    end 
end 

def each_cell 
    each_row do |row| 
    row.each do |cell| 
     yield cell if cell 
    end 
    end 
end 

什麼這裏是最後兩個函數實際在做什麼?

each_row方法需要一個塊作爲參數,並依次將所述yield@grid數組的所有元素。 @grid被構造爲一個數組數組,表示單元格的行。換句話說,each_row將依次爲網格的每一行yield,即它是行的迭代器方法。

each_cell方法需要一個塊作爲參數,並將先後yield所有網格@grid陣列中的行陣列的元件。換句話說,each_cell將連續yield網格的每個單元(如果它存在的話),即它是單元的迭代器方法。

直譯到Python會是這樣的(未經測試):

def each_row(self, f): 
    self.grid.each(lambda row: f(row)) 

def each_cell(self, f): 
    self.each_row(lambda row: lambda cell: if cell: f(cell)) 

但是,這只是沒有任何意義,從一種語言到另一種這樣轉換的代碼。在Python中使用lambdas進行迭代是非慣用的。Python使用迭代器進行迭代。因此,而不必each_roweach_cell迭代方法,你寧願row_iteratorcell_iterator干將它返回迭代器對象的行和單元格,這樣你就可以這樣做:

for cell in grid.cell_iterator 

,而不是

grid.each_cell(lambda cell: …) 

像這樣的東西(也未經測試):

def row_iterator(self): 
    for row in self.grid: yield row 

def cell_iterator(self): 
    for row in self.row_iterator: 
    for cell in row: 
     if cell: yield cell 

當「反式遲到「的代碼,你不能只是逐行,逐個語句,逐個表達式,逐個子程序,逐個類等來翻譯它。你需要重新 - 從一開始就使用語言及其核心和標準庫中社區的模式,實踐和慣用語以及類型,類,子例程,模塊等來設計它。

否則,你可以使用一個編譯器。編譯器實際上定義爲「將程序從一種語言翻譯成另一種語言的程序」。如果這就是你想要做的,使用一個編譯器。但是,如果您希望翻譯後的代碼具有可讀性,可理解性,可維護性和慣用性,則只能由人來完成。

+0

我試圖理解代碼和它背後的意圖,以便我可以使它作爲一個寫得很好,結構良好的Python代碼塊。所以,謝謝你的回答。 –