【问题标题】:Python's property decorator does not work as expectedPython 属性装饰器无法按预期工作
【发布时间】:2012-04-15 06:19:57
【问题描述】:
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

但它并没有像预期的那样打印“你变得愚蠢”、“你变得愚蠢有趣”……不知道为什么。伙计们,你们能帮我弄清楚吗?

提前致谢!

【问题讨论】:

    标签: python class properties decorator new-style-class


    【解决方案1】:

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

    @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) 的类似选项具有相同的要求。

    但是,还有另一种选择,那就是使用相应的私有变量,例如 self._silly,并覆盖 __getattr____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
    

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

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

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

    i_am = Silly()
    i_am.silly = 'No, I'm clever'
    print i_am.silly
    

    【讨论】:

      【解决方案2】:

      The property decorator 仅适用于 new-style classes (see also)。使 Sillyobject 显式扩展以使其成为新样式类。 (在 Python 3 中,所有类都是新式类)

      class Silly(object):
          @property
          def silly(self):
              # ...
          # ...
      

      【讨论】:

      • class Silly --> class Silly(object),它起作用了。我错过了。谢谢!
      猜你喜欢
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-30
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多