使用python属性的奇怪结果

时间:2013-08-29 15:13:55

标签: python properties

我花了一些时间来学习Python的属性魔法。但是当我写一个带有小错误的简单案例时,我得到了一个奇怪的结果。这是我的代码:

class PropertyShow(object):
    def __init__(self):
        self.__num = 90 

    def setNum(self,value):
        self.__num = value

    def getNum(self):
        return self.__num

    def delNum(self):
        del self.__num

    #num = property(getNum,setNum,delNum)
    # I made a mistake here!
    __num = property(getNum,setNum,delNum)


class PropertyTwo(object):
    def __init__(self):
        self.__num = None

    @property
    def num(self):
        """OK, use a decorator, you can do something here!"""
        return self.__num

    @num.setter
    def num(self,value):
        self.__num = value

    @num.deleter
    def num(self):
        del self.__num

one = PropertyShow()
print one.num 
two = PropertyTwo()
print two.num

在关键行中,“num = property(getNum,setNum,delNum)”。我将此行改为粗心,现在就像这个“__num = property(getNum,setNum,delNum)”。

此代码的结果:

File "property.py", line 6, in setNum
    self.__num = value
RuntimeError: maximum recursion depth exceeded
  1. num替换为__num时,为什么会出现这种意外结果?
  2. 如何理解property()的魔力以及为什么要使用私有变量?*

1 个答案:

答案 0 :(得分:4)

self.__num = value导致调用属性设置器。

属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性设置器尝试设置self.__num,这会导致调用属性设置器。属性setter尝试设置self.__num,这会导致调用属性设置器。

检测到无限递归。

当您的媒体资源 <{1}}时,这显然不会发生。

要明确:Python将行__num视为self.__num = value操作码:

STORE_ATTR

>>> import dis >>> def setNum(self, value): ... self.__num = value ... >>> dis.dis(setNum) 2 0 LOAD_FAST 1 (value) 3 LOAD_FAST 0 (self) 6 STORE_ATTR 0 (__num) 9 LOAD_CONST 0 (None) 12 RETURN_VALUE 的实现将首先在类上查找数据描述符,并找到您的STORE_ATTR __num对象。然后该呼叫有效地转换为:

property

PropertyShow.__num.__set__(self, value) 对象查找配置的setter函数,property并将其称为PropertyShow.setNum。这反过来再次调用PropertyShow.setNum(self, value),递归从那里开始。