如何避免使用__setattr__和属性设置器的递归循环?

2 投票
1 回答
2433 浏览
提问于 2025-04-17 02:28

当调用 setattr 函数时,如果试图为 some_prop 这个属性设置值,就会导致无限递归循环,因为 some_prop 是一个有设置器的属性。

class TypeSystem(object):

    def __setattr__(self, key, value):
        if the_special_case is True:
            # do something
        else:
            super(TypeSystem,self).__setattr__(key,value)


class Entity(TypeSystem):

    @property
    def some_prop(self):
        some_prop = self.data.get('some_prop')
        if some_prop is None and hasattr(self,"some_prop"):
            some_prop = self.some_prop
        return some_prop

    @some_prop.setter
    def some_prop(self,value):
        self.some_prop = value

>>> entity = Entity()
>>> entity.some_prop = 3

对于那些没有定义为属性的普通属性,这种情况不会出现问题,因为 Super 会调用对象的 setattr 来防止递归循环。

但是,由于 some_prop 不是预先定义的,所以看起来是调用了 setattr,而不是 some_prop 的设置器,这就导致了循环。

我也尝试过这个……

@some_prop.setter
def some_prop(self, value):
    super(TypeSystem, self).__setattr__("some_prop", value)

但它仍然进入了递归循环。我不知道该怎么避免这个问题。

1 个回答

10

这和 __setattr__ 或你的 TypeSystem 没什么关系。你遇到的问题是

@some_prop.setter
def some_prop(self,value):
    self.some_prop = value

这明显是一个无限循环——你在属性的设置方法里又试图设置这个属性。

在获取方法里你也有同样的问题:

some_prop = self.some_prop

这也会导致无限循环——你在属性的获取方法里又试图获取这个属性。

你需要用另一个变量来保存实际的数据:

class Entity(TypeSystem):

    @property
    def some_prop(self):
        some_prop = self.data.get('some_prop')
        if some_prop is None and hasattr(self,"_some_prop"):
            some_prop = self._some_prop
        return some_prop

    @some_prop.setter
    def some_prop(self,value):
        self._some_prop = value

撰写回答