1

我花了一些时间学习 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. 为什么我在替换numto时会得到这个意外的结果__num
  2. 如何理解私有变量的魔力property()以及为什么要使用私有变量?*
4

1 回答 1

4

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

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

检测到无限递归。

当您的属性命名__num时,这显然不会发生。

明确地说:Python 将该行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        

for 的实现STORE_ATTR将首先在类上查找数据描述符,并找到您的__num property对象。然后调用有效地转换为:

PropertyShow.__num.__set__(self, value)

property对象查找配置的 setter 函数,PropertyShow.setNum并将其称为PropertyShow.setNum(self, value). 这又再次调用self.__num = value,递归从那里接管。

于 2013-08-29T15:16:56.080 回答