为什么property.fget是只读属性?

时间:2011-04-23 16:53:44

标签: python properties

我目前正在从库中修补类的属性,以使其更加通用。

我正在使用以下代码执行此操作:

_orig_is_xhr = BaseRequest.is_xhr.fget
_orig_is_xhr_doc = BaseRequest.is_xhr.__doc__
BaseRequest.is_xhr = property(lambda self: _orig_is_xhr(self) or
    '_iframe-xhr' in request.form, doc=_orig_is_xhr_doc)

但是,如果我可以简单地覆盖getter函数以保存docstring,那就更好了:

_orig_is_xhr = BaseRequest.is_xhr.fget
BaseRequest.is_xhr.fget = lambda self: (_orig_is_xhr(self) or
    '_iframe-xhr' in request.form)

这不起作用,因为property.fget是一个只读属性(TypeError: readonly attribute,当尝试分配给它时)。 我很好奇是否有特殊原因,或者python开发人员认为在创建它之后修改属性没有用新的属性替换它是没有意义的。

2 个答案:

答案 0 :(得分:6)

你可能是对的,只是将这些属性设为只读的惯例,选择这些属性使属性“全有或全无”。似乎更多的是“Pythonic”允许在事后分配这些,但是在Python 2.2 release notes中找不到基本原理(当引入属性时)。

Objects/descrobject.c中,属性的成员属性被定义为只读:

    static PyMemberDef property_members[] = {
        {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
        {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
        {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
        {"__doc__",  T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
        {0}
    };

除此之外:如果您将READONLY替换为0并进行编译,则只需分配fget, fset, ..即可:

class Test(object):
    def __init__(self):
        self.flag = True
    prop = property(lambda self: self.flag)

obj = Test()
print obj.prop
Test.prop.fget = lambda self: not self.flag
print obj.prop

输出:

True
False

答案 1 :(得分:0)

在IDLE shell中使用Anaconda 2.3.0(Python 3.4.3)进行测试

>>> p = property()
>>> p.fget
>>> p.__init__( lambda obj: None )
>>> p.fget
<function <lambda> at 0x0121FF18>
>>> p.fget = lambda obj: None
Tracebabk (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    p.fget = lambda obj: None
AttributeError: readonly attribute
>>>

对我来说看起来并不那么简单;)