如何在没有循环导入的情况下在 Python 类 中创建 "reverse links"?

How do I create "reverse links" amongst Python classes without circular imports?

假设我在文件 person.py 中有一个名为 Person 的 Python class,如下所示:

class Person(object):
    static_id = 0
    instance_id = None

    @staticmethod
    def new_id():
        Person.static_id += 1
        return Person.static_id

    def __init__(self):
        self.instance_id = Person.new_id()

    def __repr__(self):
        return "<Person #%s>" % (self.instance_id)

实例化 Person 有效:

>>> a = Person()
>>> a
<Person #1>
>>> b = Person()
>>> b
<Person #2>

我在文件 thing.py 中还有一个名为 Thing 的 class,如下所示:

from person import Person

class Thing(object):
    static_id = 0
    instance_id = None
    instance_creator = None

    @staticmethod
    def new_id():
        Thing.static_id += 1
        return Thing.static_id

    def __init__(self, person):
        self.instance_id = Thing.new_id()
        self.instance_creator = person

    def __repr__(self):
        return "<Thing #%s created by %s>" % (self.instance_id, self.instance_creator)

现在,当我实例化 Thing 的实例时,我看到以下内容:

>>> Thing(person=b)
<Thing #1 created by <Person #2>>

>>> Thing(person=b)
<Thing #2 created by <Person #2>>

>>> Thing(person=a)
<Thing #3 created by <Person #1>>

我如何创建一个(非静态)方法 Person.created_things() 来 return 我将由该 Person 实例创建的所有事物?我要:

>>> b.created_things()
[<Thing #1 created by <Person #2>>, <Thing #2 created by <Person #2>>]

但如果不将 thing.Thing 导入 person.py,我不知道该怎么做。这样做会创建循环导入引用。那我该怎么做呢?在这种情况下,这些不是 Django classes.

只需向 Person 添加几个方法(并在 __init__ 中初始化 self.things):

def __init__(self):
    self.things = []
    self.instance_id = Person.new_id()

def addThing(self, thing):
    self.things.append(thing)

def created_things(self):
    return self.things

并且在初始化 Thing 时,只需将其添加到 Person

def __init__(self, person):
    self.instance_id = Thing.new_id()
    self.instance_creator = person
    self.instance_creator.addThing(self)

您可以在不修改 person.py 中的 Person 定义的情况下执行此操作,方法是动态修改传递给 Thing 的 person 实例:

from person import Person

class Thing(object):
    static_id = 0
    instance_id = None
    instance_creator = None

    @staticmethod
    def new_id():
        Thing.static_id += 1
        return Thing.static_id

    def __init__(self, person):
        self.instance_id = Thing.new_id()
        self.instance_creator = person
        try:
            person.created_things.append(self)
        except AttributeError:
            person.created_things = [self]

    def __repr__(self):
        return "<Thing #%s created by %s>" % (self.instance_id, self.instance_creator)


a = Person()
print a

b = Person()
print b

t1 = Thing(person=b)
print t1

t2 = Thing(person=b)
print t2

t3 = Thing(person=a)
print t3

print a.created_things
print b.created_things

输出

<Person #1>
<Person #2>
<Thing #1 created by <Person #2>>
<Thing #2 created by <Person #2>>
<Thing #3 created by <Person #1>>
[<Thing #3 created by <Person #1>>]
[<Thing #1 created by <Person #2>>, <Thing #2 created by <Person #2>>]