一个类可以包含其自身的实例作为数据容器吗?

10 投票
3 回答
16004 浏览
提问于 2025-04-16 02:03

一个Python类可以包含它自己作为数据容器吗?看起来可能是这样的:

class A:
    def __init__(self, val):
        self.a = A(val)
        self.val = val

aa = A(2) 
#this will cause RuntimeError: maximum recursion depth exceeded

我的目的是使用这个类作为一个数据容器,当它被初始化时,里面包含一个自己的副本,这样可以减少深拷贝的操作。它可以用作一个“撤销”链,当需要的时候可以获取初始化时的值。

这样的操作可能吗?

3 个回答

1

好吧,你在self.a里面定义的类也有self.a,而且这样一直循环下去,没有尽头。我不太明白你这样做的目的是什么,但你可以试试下面这样的写法:

class A:
    def __init__(self, val, copy = True):
        if copy:
            self.a = A(val, False)
        self.val = val
8

是的,一个类可以包含它自己的一个实例,不过在创建的时候不能直接这样做,原因已经有其他人解释过了。

比如说,这个类就可以做到这一点:

class A:
    def __init__(self,value):
        self.value=value
    def setProperty(self,subvalue):
        self.innerInstance=A(subvalue)

然后你可以这样创建它,并设置它内部的那个自己的副本:

>>>OuterInstance=A(123)
>>>OuterInstance.setProperty(456)

你可以用下面的方式来验证它是否成功:

>>>OuterInstance.innerInstance.value
456
8

这个方法行不通,原因已经说过了:

  1. Python 看到 A(2) 后,会调用 A.__init__
  2. A.__init__ 会再调用 A(val)
  3. A(val) 又会调用 A.__init__
  4. 回到第2步

我猜你这么做是为了记录 val 的历史值;也就是说,如果你后来决定想把 val 改成 3,你不想丢掉原来的值 2。那这样怎么样:

代码

class A( object ):
    @property
    def val( self ):
        return self.history[ -1 ]

    @val.setter
    def val( self, value ):
        self.history.append( value )

    def __init__( self, val ):
        self.history = [ ]
        self.val = val

解释

  • A( object ):类现在应该继承自 object。基本上就是这个原因。
  • @property:这个告诉 Python,每次我们请求 A.val 时,它应该调用 A.val() 并返回结果。这是一个 装饰器;可以查一下 property 这个内置函数,了解更多信息。
  • @val.setter:这个和上面类似,但它告诉 Python,每次我们尝试给 A.val 赋值时,应该调用下面的函数。它不是直接设置 A.val,而是把值添加到历史记录列表中。

撰写回答