应用“属性”到实例变量“self.x”时超出最大递归深度

5 投票
2 回答
4718 浏览
提问于 2025-04-17 15:05

我在看property()这个东西,理解为属性的访问是通过property()里指定的方法来进行的。但是,当我执行以下代码时,出现了“RuntimeError: 最大递归深度超出”的错误。

class Property(object):

    def __init__(self):
        self.x = "Raj"

    def gettx(self):
        print "getting x"
        return self.x

    def settx(self, val):
        print "Setting x"
        self.x = val

    def dellx(self):
        print "deleting"
        return self.x

    x = property(gettx, settx, dellx, "I'm object property")


p = Property()
print "p.x", p.x
p.x = "R"
print "p.x:", p.x

这样使用property是不行的吗?因为当我把'self.x'改成self._x和self.__x时,代码就正常运行了。

2 个回答

0

根据Python文档的说明:

如果c是C类的一个实例,那么c.x会调用获取器,c.x = value会调用设置器,而del c.x会调用删除器。

所以,你的代码行self.x = "Raj"实际上是在调用settx(self, val)这个方法。在这个方法里,self.x = val又会再次调用settx(self, val),这样就形成了一个无限循环。

因此,正确设置属性值的方法是self._x = value

正确的代码:

class Property(object):
    def __init__(self):
        self._x = 'Raj'

    def gettx(self):
        print "getting x"
        return self._x

    def settx(self, val):
        print "Setting x"
        self._x = val #stores the value in _x. writing self.x = val would cause an infinite loop

    def dellx(self):
        print "deleting"
        del self._x    

    x = property(gettx, settx, dellx, "I'm object property")

p = Property()
print "p.x", p.x
p.x = "R"
print "p.x:", p.x

输出:

p.x getting x
Raj
Setting x
p.x: getting x
R
13

这个错误是因为出现了无限递归循环:你定义了一个属性 x,它使用了 gettxsettxdeltx 这几个方法来访问,但这些方法又试图去访问属性 x(也就是说,它们在调用自己)。

你应该按照以下方式来写代码:

class Property(object):

    def __init__(self):
        self.__x = "Raj"  # Class private

    def gettx(self):
        print "getting x"
        return self.__x

    def settx(self, val):
        print "Setting x"
        self.__x = val

    def dellx(self):
        print "deleting"
        return self.__x

    x = property(gettx, settx, dellx, "I'm object property")

撰写回答