2015-05-30 48 views
0

這看起來像類繼承,但我認爲它不是,並且必須有一個簡單的方法來執行以下操作。看看這個簡單的代碼:python多重嵌套類

class Land: 
    def __init__(self): 
     print "a new Land" 
     self.farms = [] 

    def addfarm(self): 
     self.farms.append(Farm()) 


class Farm: 
    def __init__(self): 
     print "a new farm" 
     self.animals = [] 

    def addanimal(self,name): 
     self.animals.append(Animal(name)) 

class Animal: 
    def __init__(self, name): 
     print "hi, I am %s" % name 
     self.name = name 


USA = Land() 
USA.addfarm() 
USA.farms[0].addanimal('George') 
USA.farms[0].addanimal('Martin') 
USA.addfarm() 
USA.farms[1].addanimal('Polly') 
USA.farms[1].addanimal('Ralph') 

有沒有讓所有的動物沒有做?:

for eachfarm in USA.farms: 
    for each in eachfarm.animals: 
     print each.name 

我問一個簡單的方法,因爲如果例如用戶希望增加一個新的喬治去農場0我想很快就能說出這個名字。我也可以快速運行一個功能,讓我在陸地或所有農場都可以擁有所有的動物。我應該爲所有這些編寫函數還是Python有自己的功能?

我也很想知道我的嵌套類結構是否不正確,並最終可能導致問題。

例如,假設我有一個功能,給定一個動物告訴我它的完美食物組合。我希望能夠在我的所有動物身上運行該功能並將它們寫回到它們的對象中。如果它們嵌套,恐怕功能可能會變得困惑!

謝謝!

+1

你想寫什麼而不是嵌套循環?此外,你是否想要讓所有農場中的「被採納」名稱的全球名單是全球性的,還是僅僅是每個農場?如果用戶試圖向農場1添加「喬治」會怎麼樣? – BrenBarn

回答

2

使用像這樣的嵌套類是完全正確的,而不是關於繼承。但是,您可能想要選擇稍微不同的數據結構。

你說在每個農場你只希望能夠擁有每個名字的一個動物。但是,您使用列表來存儲它們。列表允許您在任意位置擁有多個同名動物,因此當您添加另一個動物時,您需要執行檢查。

但是,您可以使用dict。字典是一個無用的數據結構,它將一個鍵鏈接到一個值。在你的情況下,你可以使用動物的名稱作爲關鍵字,並使用Animal對象作爲值。檢查一個鍵是否存在可以在恆定時間內完成(與具有循環的線性時間相比),因爲內部dict是一個散列表。

示例代碼可能是這樣的:

class Land: 
    def __init__(self): 
     print "a new Land" 
     self.farms = [] 

    def addfarm(self): 
     self.farms.append(Farm()) 


class Farm: 
    def __init__(self): 
     print "a new farm" 
     self.animals = {} 

    def addanimal(self,name): 
     if not name in self.animals: 
      self.animals[name] = Animal(name) 
      return True 
     return False 

class Animal: 
    def __init__(self, name): 
     print "hi, I am %s" % name 
     self.name = name 


USA = Land() 
USA.addfarm() 
USA.farms[0].addanimal('George') 
USA.farms[0].addanimal('Martin') 
USA.addfarm() 
USA.farms[1].addanimal('Polly') 
USA.farms[1].addanimal('Ralph') 

這會阻止您添加相同名稱的兩個動物一個農場,返回取決於動物是否可以添加到農場或不是布爾。

要獲得所有農場上的所有動物,您仍然需要嵌套循環。但是啓用迭代對象本身可以更好。如果你做到以下幾點:

class Land(object): 
    def __init__(self): 
     print "a new Land" 
     self.farms = [] 

    def addfarm(self): 
     self.farms.append(Farm()) 

    def __iter__(self): 
     for farm in self.farms: 
      yield farm 


class Farm(object): 
    def __init__(self): 
     print "a new farm" 
     self.animals = {} 

    def addanimal(self,name): 
     if not name in self.animals: 
      self.animals[name] = Animal(name) 
      return True 
     return False 

    def __iter__(self): 
     for name, animal in self.animals.iteritems(): 
      yield animal 

class Animal(object): 
    def __init__(self, name): 
     print "hi, I am %s" % name 
     self.name = name 

,那麼你可以:

for farm in USA: 
    for animal in farm: 
     pass #do something here 

根據您的意見,您也希望能夠做到land.getAllAnimals()farm.getAllAnimals()。後者很容易完成,因爲farm可以作爲所有動物的迭代器。如果你想要一個列表,你可以簡單地致電list(farm)
對於land.getAllAnimals()有兩個很好的選擇。兩者都將被添加到前面的聲明中。

選項1個
class Land(object): 
    def getAllAnimals(self): 
     for farm in self: 
      for animal in farm: 
       yield animal 
選項2
from itertools import chain 

class Land(object): 
    def getAllAnimals(self): 
     return chain(*self) 

雙方將返回迭代器在所有的動物。要將這些轉換爲列表,只需在它們上面調用list即可。前者更容易理解,但後者更簡潔,在我看來,更好。

+0

小小挑逗:在字典中訪問一個密鑰不是線性時間,它是恆定的時間。檢查存在列表是線性時間。 – sberry

+0

你是絕對正確的,這或多或少是一個錯字(我實際上給出了它爲什麼不變並且仍然寫成線性的非常簡短的原因)。感謝您指出:) – Cu3PO42

+0

感謝@ Cu3PO42 ...你說這不是關於繼承,但我想這個概念,因爲我想可能有一種方法將項目列表傳遞給父對象。例如,讓農場有一個函數來返回所有存在的動物。我將如何傳遞這個函數以便它可以由Land對象運行? (所以我的想法是隻寫一次,如果我有'Farm.getmetheanimals()'我不想做'Farm.getmetheanimals()''但希望可以簡單地做'Land.getmetheanimals()'' ...關於那個的任何想法?再次感謝! – Yona

1

嵌套你的循環沒有任何問題,它只是做它的方式。您可能希望查看更具說明性的方法,或者您可能希望以不同的方式存儲數據,但這只是實現細節,主要是品味的問題。