python多个嵌套类

时间:2015-05-30 16:52:55

标签: python class

这看起来像是类继承,但我认为不是,并且必须有一种简单的方法来执行以下操作。看看这个简单的代码:

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

我问这个问题,因为如果用户想要将新的George添加到农场0,我希望能够快速地说出该名称。我也可以快速运行一个功能,让我在陆地或所有农场的所有动物。我应该为所有这些编写函数还是Python有自己的函数?

我也有兴趣了解我的嵌套类结构是否正确并最终导致问题。

例如,假设我有一个功能,给动物告诉我完美的食物搭配。我希望能够在我的所有动物上运行该功能并将其写回到他们的对象中。如果它们是嵌套的,恐怕功能可能会混淆!

谢谢!

2 个答案:

答案 0 :(得分:2)

使用像这样的嵌套类是完全没问题的,根本不是继承。但是,您可能希望选择稍有不同的数据结构。

你说在每个农场你只想拥有一个每个名字的动物。但是,您使用列表来存储它们。列表允许您在内部拥有尽可能多的同名动物,因此当您添加另一个动物时,您需要自己执行该检查。

但是,您可以使用dict。 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即可。前者更容易理解,但后者更简洁,在我看来更好。

答案 1 :(得分:1)

嵌套循环没有任何问题,而这只是实现它的方法。您可能希望研究一种更具声明性的方法,或者您可能希望以不同方式存储数据,但这只是实现细节,主要是品味问题。