自动推断 object 是 parent object/class 的属性

Automatically infer that an object is an attribute of a parent object/class

像这样使用类时:

class Parent:
    def __init__(self):
        self.child = Child()
class Child:
    def __init__(self):
        print(self.parent)  # error, I don't have any way to know my parent!
p = Parent()

当然是returns错误,因为Child实例没有属性parent,这是正常的。

一个解决方案就是像这样简单地定义 类:

class Parent:
    def __init__(self):
        self.child = Child(self)
class Child:
    def __init__(self, parent):
        self.parent = parent
        print(self.parent)  # now it's ok!

但是在我的代码中,我有很多 类,在实例化 child [=45 时,必须始终将 self 作为参数传递,这有点烦人=]s:

self.child = Child(self)  # pass self so that this Child instance will know its parent

我更愿意保持简单:

self.child = Child()      # can this Child instance know its parent without passing self?

有没有办法让 Python 自动推断 object 实际上是 parent object 的属性,而无需显式传递 self? 如果是这样,如何获得 parent?


示例:在GUI编程中创建Button实例时,它是Panel的成员,它本身是Window的成员,等等。看来我们必须通过self一直child任建设者。

注意:我想避免使用 inspect,因为它的解决方案似乎比仅传递 self.

更差

从技术上讲,您可以通过使用 inspect 模块遍历堆栈来做到这一点,如下所示:

>>> import inspect
>>>
>>> class Parent:
...     def __init__(self):
...         self.child = Child()
...
>>> class Child:
...     def __init__(self):
...         for frame in inspect.stack():
...             if isinstance(frame[0].f_locals.get('self'), Parent):
...                 self.parent = frame[0].f_locals.get('self')
...                 break
...
>>> p = Parent()
>>>
>>> p.child.parent
<__main__.Parent object at 0x000001ED3901A310>

不过,由于 许多 原因,这很糟糕。理想情况下,您应该完全避免这样的循环引用,更不用说通过在调用堆栈中翻找来构建它们了。

您可以创建一个设置方法来实例化子项,而不是使用检查来动态确定调用者。

class Parent:
    def __init__(self):
        self.child = self.create_child(Child)

    def create_child(self, cls, *args, **kwargs):
        return cls(*args, parent=self, **kwargs)

如果这是您可能会在很多 class 中使用的东西,您也可以将它移到基础 class 中。