2017-10-16 67 views
0

所以我想讓我的數據結構設置爲一個自動生成器我正在寫一個角色扮演遊戲,我遇到了一些特定的繼承怪癖問題。這是數據結構的摘錄。具體的類繼承行爲的問題

class data(): 
    def __init__(self): 
     self.races = Races() 
class Races(data): 
    def __init__(self): 
     self.humans = Humans() 
class Humans(Races): 
    def __init__(self): 
     self.Characteristics = { 
      'Brawn':2, 
      'Agility':2, 
      'Intellect':2, 
      'Cunning':2, 
      'Willpower':2, 
      'Presence':2 
      } 

結構中還有很多,但這只是一個從下到上的概述。我也知道它是奇怪的縮進,但這是嚴格的堆棧溢出。

現在我希望從這個對象有兩個行爲。 調用任何特徵的能力爲 data.races.humans.Characteristic['brawn'] 作爲調用格式。

而且也還能夠通過與子像發電機迭代: (subclass for subclass in data.races.__subclasses__())

後顯然我已經實例化對象。

現在我試圖改變結構好幾次,我可以得到它,無論是我可以用點符號調用它,但它通過它完全分離成一個更傳統的結構,但隨後返回AttributeError: 'Races' object has no attribute '__subclasses__'

反之亦然我不能用點符號來調用,這使得保持一切組織和可讀性變得非常困難。

任何人都可以提出我做錯了什麼或更Pythonic的方式來解決這個問題?

+1

要小心 - 這聽起來像你想要的組成,而不是繼承。人類可能是一場比賽,但種族不是數據。 –

+0

當他們以完全相同的方式製造時,人類如何與種族聯繫起來,但不是與數據競爭? 它們都與同一頂層對象相關的原因是存在不同的數據片段,我希望將它們全部放在它自己的模塊中並實例化一個對象。 –

+0

@KirkReynolds'data',而不是'Race'繼承的單個類,可以簡單地作爲一個類的列表:'races = [Human,Elf,Dwarf,...]',以我的答案作爲起點點。這完全取決於你如何建模數據。我嘗試在我的回答中給出一個簡短的口味,但是您的問題太寬泛,無法在這裏有效回答。 – chepner

回答

0

讓我們從中間開始。據推測,任何種族的角色都具有相同的屬性,只是這些屬性的值不同。

class Race: 
    def __init__(self): 
     self.life = 100 # 100% healthy 

class Humanoid(Race): 
    def __init__(self): 
     super().__init__() 
     self.legs = 2 

class Insectoid(Race): 
    def __init__(self): 
     super().__init__() 
     self.legs = 8 

class Human(Humanoid): 
    def __init__(self): 
     super().__init__() 
     self.brawn = 2 
     self.agility = 2 
     self.intellect = 2 
     self.cunning = 2, 
     self.willpower = 2 
     self.presence = 2 

class Elf(Humanoid): 
    def __init__(self): 
     super.__init__() 
     self.brawn = 1 
     self.agility = 3 
     self.intellect = 3 
     self.cunning = 2 
     self.willpower = 3 
     self.presence = 1 

現在,任何特定的字符將被實例化的正確類:

some_elf_1 = Elf() 
some_human_1 = Human() 
some_human_2 = Human() 

for character in [some_elf_1, some_human_1, some_human_2]: 
    print("Brawn: ", character.brawn) 

在前面的,不要緊的每個字符的實際類型是什麼;只要您知道它是Race(或Race本身的一個實例)的某個子類,它將具有您可以訪問的brawn屬性。

data類沒有更多的細節看起來沒有必要。

+0

我這樣做是爲了讓我從一個不同的模塊立即調用它,但是看看你的解決方案,它看起來好像對我有用。然而,可能有數百種不同的種族(畢竟這是星球大戰!),我想盡量避免初始化它們。這就是爲什麼我希望我可以把它們全部放在一個對象下面 - 如果需要的話調用一個特定的對象,但是可以輕鬆地遍歷它們,而無需編寫大量的樣板代碼來初始化對象。 –

+0

是否有任何比賽有關?你可以有比我所展示的更復雜的層次結構。 'Race .__ init__'可以進行任何種族共有的初始化,您可以創建中間類:想想地球上的生命是如何按照王國,門,階,階級,家族,屬,物種組織的。每個門將是一個擴展王國的類,每個命令擴展一個門等。此外,每個父節點的__init__方法是從子節點的__init__方法中調用的。 (我會給答案添加一個例子。) – chepner

0

所以,雖然給出的答案讓我走上了正確的軌道,但我意識到我需要什麼,並且只是爲了任何可憐的靈魂而投入我的生活。

首先 - 我意識到我的發生器出了什麼問題,我正在調用初始化對象而不是類對象。對象沒有子類屬性,我被大部分閱讀指南誤解了!

其次,我考慮使用元類來獲取我想從我的對象獲得的迭代行爲,可以簡單地通過一個註冊表屬性來實現,該註冊表屬性是所有初始化子類的字典。

lass Races(data): 
def __init__(self): 
    self.humans = Humans() 
    self.droids = Droids() 
    self.twileks = Twileks() 
    self.registry = { 
      'humans':self.humans, 
      'droids':self.droids, 
      'twileks':self.twileks 
      } 

這使我可以在不同的種族初始化後迭代通過某些值。

感謝所有偉大的答案!