Python 自动推断对象是父对象/类的属性

Python 自动推断对象是父对象/类的属性,python,class,parent-child,Python,Class,Parent Child,使用这样的类时: 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() class Parent: def __init__(self):

使用这样的类时:

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()
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!
>>> 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 = Child()
class Child:
    def __init__(self):
        print(self.parent)  # error, I don't have any way to know my parent!
p = 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!
>>> 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>
但在我的代码中,我有很多类,在实例化子对象时,总是必须将
self
作为参数传递,这有点烦人:

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有没有一种方法可以自动推断一个对象实际上是父对象的属性,而不必明确地传递
self
如果有,如何获取父对象


示例:在GUI编程中,当创建按钮实例时,它是面板的一个成员,它本身也是窗口的一个成员,等等。似乎我们必须始终将
self
传递给子构造函数


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

要差,从技术上讲,您可以使用
inspect
模块遍历堆栈来实现这一点,如下所示:

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()
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!
>>> 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>
导入检查 >>> >>>类父级: ... 定义初始化(自): ... self.child=child() ... >>>班级儿童: ... 定义初始化(自): ... 对于inspect.stack()中的帧: ... 如果isinstance(帧[0].f_locals.get('self'),父级): ... self.parent=frame[0]。f_locals.get('self')) ... 打破 ... >>>p=父项() >>> >>>家长
这是可怕的,原因很多。理想情况下,您应该完全避免这样的循环引用,更不用说通过在调用堆栈中搜索来构建它们。

您可以创建一个用于实例化子对象的设置方法,而不是使用inspect来动态确定调用方

类父级:
定义初始化(自):
self.child=self.create\u child(child)
定义创建子项(self、cls、*args、**kwargs):
返回cls(*args,parent=self,**kwargs)

如果这是您可能在许多类中使用的东西,您也可以将其移动到基类中。

您将有多少父实例?只有一个?这不是OOP父/子关系。这是呼叫者/被呼叫者关系。
inspect
模块将为您提供帮助。另外,您正在创建循环引用,以防止对象被释放(至少它们必须等待垃圾收集器)。如果我记得好,是的。但稍后也可以将子实例添加到
列表中。另外:子实例是父实例的属性,父实例本身是祖辈实例的属性,等等。这是否回答了您的问题?很抱歉,这是一个输入错误,刚刚修复它我认为这是最好的解决方案!如果我需要传递另一个参数来创建子实例,例如
Child(x=1,y=2,z=3)
,它是否也可以工作。可能是*arg**kwarg?它看起来是什么样子?是的,确切地说,你可以允许任意数量的带有星型符号的参数。我会更新答案。