2016-12-07 39 views
0

我寫了一個解決數獨問題的腳本。 爲了模擬的網格的每個時隙,我已經在第一時間限定插槽和網格類這樣的(elipsed爲簡單起見完整代碼:對象子類列表到父列表中的索引

class Slot(): 
    def __init__(self,grid): 
     self.grid = grid 
     self.values = list(range(9)) 

    def pos(self): 
     return self.grid.index(self) 

class Grid(list): 
    def __init__(self): 
     for i in range(9*9): 
      self.append(Slot(self)) 

這樣,我可以爲我的槽類中定義的方法使用self.pos()和self.values()。例如:

g = Grid() 
g[5].pos() -> returns 5, OK ! 

現在,我的完整劇本的作品很好,我想重構它,並且,作爲一個插槽基本上是屬於一個列表網格,我決定這將是我的插槽子類列表很好,像這樣:

class Slot(list): 
    def __init__(self,grid): 
     self.grid = grid 
     self.append(list(range(9))) 

    def pos(self): 
     return self.grid.index(self) 

class Grid(list): 
    def __init__(self): 
     for i in range(9*9): 
      self.append(Slot(self)) 

g = Grid() 
g.index(g[5]) -> returns 0, KO ! 

我試着先初始化列表,即:super()。 初始化(名單(範圍(9)),也有一些變化,但似乎沒有任何工作 我缺少什麼

PS:?在g.index(g[5])只是來形容,我知道這是沒有意義的。我使用這個邏輯裏面我的對象(self.pos()等)

+0

爲什麼不使用組合繼承,有一個列表作爲一個內部屬性,並簡單地公開列表協議的所有相關方法工作正常? (像'__getitem__','__len__'等屬性) –

+0

任何類都不應該擴展'list'。這是一個實現細節而不是模型約束。 你應該隱藏實現和使用組合;實際上,我不會在任何一個類中使用'list',特別是在'Slot'中'index(x)== x'! –

+0

那麼,這是爲了避免我想要繼承,我的方法主要用在Slot對象中(例如:第一個版本,我在做self.values.remove(x),我一直在想做self.remove(x)等等)而不是重新定義__getitem__等將是一個矯枉過正的問題(對Lukasz的回答) –

回答

1

方法通過使Slotlist一個子類,你也讓Slot實例之間的比較,使用list已定義的邏輯(因爲你沒有重寫)

因爲所有的Slot都包含s AME值:

self.append(list(range(9))) 

g.index()將第一條目的grid得到0作爲結果簡單地匹配。如在Python參考定義(除非邏輯實現的是另有規定)

當您從object繼承(如Slot在你的第一個例子),所有實例相比不等於自己。

總之,如果需要對相似項目的插槽進行比較處理時,需要重新定義比較方法。除此之外,您可能需要重新考慮從list開始的子分類,而是從collections中選擇UserList

+0

謝謝你的解釋,這正是我所尋找的。你對我的代碼的建議是什麼,以儘可能「pythonic」;-)保持我的第一個實現或覆蓋比較邏輯? –

+1

@ Lapin-Blanc如果'Slot's *需要*像列表一樣行事,那麼對'list'進行子分類對我來說是有意義的(儘管其他人認爲的組合可能不太混亂)。如果你堅持使用子類,我建議你從'collections.UserList'繼承,儘管它在這些場景中表現得更好。我只是重新定義比較行爲,因爲我需要。 –

+0

謝謝!我喜歡子類列表,因爲我的算法基於從slots對象中刪除可能的值,直到只剩下一個值,這是解決方案的最終結果。順便說一句,如果我可以進一步詢問,你認爲「它表現更好」是什麼意思...... –