Python中可互相引用的实例

时间:2015-02-09 18:07:09

标签: python design-patterns

假设我有一对相互引用的实例。构建这种关系的方式是否优于以下方式。

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"

我不喜欢的是需要在两个地方指定关系。关于如何制作这种烘干机的任何想法?

3 个答案:

答案 0 :(得分: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个。{/ p>

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

答案 1 :(得分: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'))

这种方法当然也可以用于一只宠物,也可以扩展它以允许宠物被许多人拥有。

答案 2 :(得分: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

当然,更新它并不难以使属性函数缓存该值。 E.g:

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_