2015-02-09 74 views
0

假设我有一对相互引用的实例。有没有比以下更好的方式来构建这种关系。Python中相互引用的实例

class Human(): 
    def __init__(self, name): 
     self.name = name 
     self.pet = Dog('Sparky', self) 

    def pet(self, animal): 
     self.pet.receive_petting() 


class Dog(Pet): 
    def __init__(self, name, owner): 
     self.name = name 
     self.owner = owner 

    def receive_petting(self): 
     pass 

    def bark_at(self, person): 
     "do something" 

我不喜欢的事情是,关系需要在两个地方指定。任何想法如何使这台烘干机?

+0

真的没有什么特定于Python的;这只是基于构造函数的依赖注入的限制。您可以使用“承诺”并在第一次解除引用时填写属性。 – 2015-02-09 22:56:19

回答

1

我会打破这个分为三类:现在

class Human(): 
    def __init__(self, name): 
     self.name = name 

class Dog(Pet): 
    def __init__(self, name): 
     self.name = name 

    def bark_at(self, person): 
     "do something" 

class OwnerPetRelation(): 
    def __init__(self, dog, human): 
     self.owner=human 
     self.pet=dog 

,一个所有者还可以有许多狗,我们只需要定义尽可能多的OwnerPetRelation秒。

同样,狗现在也可以属于多个所有者。

+0

但是,现在只能通过遍历所有'OwnerPetRelation's来查找人类的狗或狗的人类 - 因此必须将它保存在某处... – glglgl 2015-02-09 20:05:48

+1

准确地说,这是我最初倾向于使用的解决方案,但是此方法使访问Human实例从一个宠物实例中(反之亦然)有点复杂。如果人类实例是自我的,我不再能够自己写self.pet – Raphi 2015-02-09 22:52:01

+1

看起来像这样可以很容易地通过将关系对象添加到所有者和宠物来解决。只需动态添加属性即可。 – 2015-02-09 22:53:24

1

我将创建Human一个方法,它允许您添加的宠物(因为一个人可能有很多宠物):

class Human(): 
    def __init__(self, name): 
     self.name = name 
     self.pets = [] 

    def add_pet(self, pet): 
     pet.owner = self 
     self.pets.append(pet) 

    def pet(self, animal): 
     for pet in self.pets: 
      pet.receive_petting() 


class Dog(Pet): 
    def __init__(self, name): 
     self.name = name 
     self.owner = None 

    def receive_petting(self): 
     pass 

    def bark_at(self, person): 
     "do something" 

这可以用于如下

human = Human('Jim') 
human.add_pet(Dog('Woof')) 

这种方法可以当然也可用于只是一个单一的宠物和一个还可以扩展它来让宠物被许多人所拥有。

1

这里没有任何真正的Python特有的;这只是基于构造函数的依赖注入的限制。很难注入到另一个还不能创建的对象的引用。相反,你可以创建具有该有其他对象的引用一些参考的对象。举例来说,你可以传递一个函数的构造函数就能返回值:

class Human(): 
    def __init__(self,name,dog): 
     self.name = name 
     self._dog = dog 

    @property 
    def dog(self): 
     return self._dog() 


class Dog(): 
    def __init__(self,name,human): 
     self.name = name 
     self._human = human 

    @property 
    def human(self): 
     return self._human() 

然后你可以使用它像这样:

human = None 
dog = Dog('fido',lambda: human) 
human = Human('john',lambda: dog) 

print(dog.human.name) 
print(human.dog.name) 
john 
fido 

这是不很难更新这个,所以属性函数当然会缓存这个值。例如:

class Dog(): 
    def __init__(self,name,human): 
     self.name = name 
     self._human = human 

    @property 
    def human(self): 
     try: 
      return self._human_ 
     except AttributeError: 
      self._human_ = self._human() 
      return self._human_