我有一个基类:
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
AnimalStore
和PetStore
位于不同的模块中。 AnimalStore
是标准Animal
API的一部分,不会更改。基本上我想通过使用与动物相同的机制获取宠物列表来扩展Animal
API,我希望能够利用Animal API已经提供的所有其他内置函数适用于Animal
和AnimalStore
类。
答案 0 :(得分:4)
您可以为__init__()
编写Pet
来接受Animal
的实例(或者实际上,任何具有必要属性的ojbect - 鸭子打字!)以及各个属性。然后你可以做fluffy_as_pet = Pet(fluffy_as_animal)
。或者,如果您不想重载Pet.from_object()
,请提供类方法(例如__init__()
)来执行相同操作。即使您不控制Animal
和Pet
类,也可以根据需要制作自己的子类。
但是,最好更进一步,不要编写接受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
类型的对象。