4
class Silly:
    @property
    def silly(self):
        "This is a silly property"
        print("You are getting silly")
        return self._silly

    @silly.setter
    def silly(self, value):
        print("You are making silly {}".format(value))
        self._silly = value

    @silly.deleter
    def silly(self):
        print("Whoah, you killed silly!")
        del self._silly

s = Silly()
s.silly = "funny"
value = s.silly
del s.silly

但它并没有像预期的那样打印“你越来越傻”,“你越来越傻了”,...... 不知道为什么。伙计们,你能帮我弄清楚吗?

提前致谢!

4

2 回答 2

16

property装饰器仅适用于新式类另请参阅)。Silly显式地进行扩展以使其object成为新型类。(在 Python 3 中,所有类都是新式类)

class Silly(object):
    @property
    def silly(self):
        # ...
    # ...
于 2012-04-01T05:05:42.967 回答
0

您很可能知道添加属性的正确方法是使用:

@property
def silly(self):
    return self._silly


@silly.setter:
def silly(self, value):
    self._silly = value

但这需要新的样式类,即链中的某个地方应该有一个class ParentClass(object):. 使用的类似选项silly = property(get_silly, set_silly)具有相同的要求。

但是,还有另一种选择,那就是使用相应的私有变量 like self._silly,并覆盖__getattr__and__setattr__方法:

def __getattr__(self, name): 
    """Called _after_ looking in the normal places for name."""  

    if name == 'silly':
        self._silly
    else:
        raise AttributeError(name)


def __setattr__(self, name, value):
    """Called _before_ looking in the normal places for name."""
    if name == 'silly':
        self.__dict__['_silly'] = value
    else:
        self.__dict__[name] = value

注意 how __getattr__will在检查其他属性之后被调用,但是在检查其他属性之前__setattr__调用。因此,如果不是接受的属性,前者可以并且应该引发错误,而后者应该设置该属性。不要使用inside,因为这会导致无限递归。self._silly = value__setattr__

另请注意,由于我们在这里处理旧样式类,因此您实际上应该使用 dict 方法,而不是较新的方法baseclass.__setattr__(self, attr, value),请参阅docs__delattr__()如果您愿意,也确实存在类似的情况。

使用此代码,您现在可以执行以下操作:

i_am = Silly()
i_am.silly = 'No, I'm clever'
print i_am.silly
于 2015-11-21T12:13:52.827 回答