Python 中可相互引用的实例

Mutually Reference-able Instances in 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"

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

我会把它分成三个 类:

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就可以了。

同样,现在一只狗也可以属于多个主人

我会在 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'))

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

这里没有什么 Python-具体的;这只是基于构造函数的依赖注入的一个限制。很难注入对另一个尚未创建的对象的引用。相反,您可以创建一个引用某个对象的对象, 引用另一个对象。例如,您可以将一个函数传递给构造函数,该函数将能够 return 值:

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_