在Python中从基类对象创建对象

时间:2011-04-01 16:38:06

标签: python

我有一个基类:

class Animal(object):
    def __init__(self, name=None, food=None):
        self.name = name
        self.food = food

    def eat(self):
        print "The %s eats some %s" % (self.name, self.food)

一个扩展它的类:

class Pet(Animal):
    def pet(self):
        print "You pet the %s." % self.name
    def feed(self):
        print "You put some %s into the bowl." % self.food
        self.eat()

假设我有一个Animal对象,因此创建了:

>>> fluffy_as_animal = Animal('dog', 'kibbles')

在python中有一种直接的方法可以从Pet创建一个fluffy_as_animal对象,但实际上没有写出:

>>>> fluffy_as_pet = Pet(fluffy_as_animal.name, fluffy_as_animal.food)

更新

我正在执行此实现的原因是我有一个带有函数的类,该函数返回一组Animal类型的对象,我想将它们实际用作Pet个对象:

class AnimalStore(object):
    def fetch(count, query=None, server=None, *args, **kwargs):
        connection = connect_to_server(server)
        resp = connection.fetch_animals(query)
        objects = parse_response(resp)
        animals = []
        for a in objects[:count]:
            animals.append(Animal(a['name'], a.['food']))
        return animals

class PetStore(AnimalStore):
    def fetch(count, query=None, server=None, *args, **kwargs):
        query = 'type=pet AND %s' % query
        animals = super(PetFactory, self).fetch(count, query, server, *args, **kwargs)
        pets = []
        for animal in animals:
            pets.append(magic_function(animal))
        return pets

AnimalStorePetStore位于不同的模块中。 AnimalStore是标准Animal API的一部分,不会更改。基本上我想通过使用与动物相同的机制获取宠物列表来扩展Animal API,我希望能够利用Animal API已经提供的所有其他内置函数适用于AnimalAnimalStore类。

4 个答案:

答案 0 :(得分:4)

您可以为__init__()编写Pet来接受Animal的实例(或者实际上,任何具有必要属性的ojbect - 鸭子打字!)以及各个属性。然后你可以做fluffy_as_pet = Pet(fluffy_as_animal)。或者,如果您不想重载Pet.from_object(),请提供类方法(例如__init__())来执行相同操作。即使您不控制AnimalPet类,也可以根据需要制作自己的子类。

但是,最好更进一步,不要编写接受Animal但不接受Pet的代码。然后你不必转换它。再次,鸭子打字 - 如果一个对象具有正确的属性,你可以使用它而不管它的类型。

答案 1 :(得分:1)

你可以做到

fluffy_as_pet = object.__new__(Pet)
fluffy_as_pet.__dict__ = fluffy_as_animal.__dict__.copy()

from copy import copy
fluffy_as_pet = copy(fluffy_as_animal)
fluffy_as_pet.__class__ = Pet

但这两种方式都可能比干净的解决方案更糟糕。

答案 2 :(得分:1)

我最终使用了委托(信用证应该转到S.Lott):

class Animal(object):
    def __init__(self, name=None, food=None):
        self.name = name
        self.food = food

    def eat(self):
        print "The %s eats some %s" % (self.name, self.food)

class Pet(object):
    def __init__(self, animal=None):
        self.animal = animal

    def __getattr__(self, key):
        return getattr(self.animal, key)

    def __setattr__(self, key, value):
        return setattr(self.animal, key, value)

    def eat(self):
        return self.animal.eat()

    def pet(self):
        print "You pet the %s." % self.name

    def feed(self):
        print "You put some %s into the bowl." % self.food
        self.eat()

我只希望我正确实施它;无论哪种方式,它都有效!

答案 3 :(得分:-1)

就我个人而言,我会使用类方法:

class Animal(object):
    def __init__(self, name):
        self.name = name

    @classmethod
    def fetch(cls, name):
        # DB code left out intentionally.
        return cls(name)


class Dog(Animal):
    def bark(self):
        print("woof")

这样调用Dog().get('fido')将返回Dog类型的对象,而Animal().get('Mickey')将返回Animal类型的对象。