我目前正在从库中修补类的属性,使其更加通用.
我正在使用以下代码执行此操作:
_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)
Run Code Online (Sandbox Code Playgroud)
但是,如果我可以简单地覆盖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)
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为它property.fget是一个只读属性(TypeError: readonly attribute当尝试分配给它时).我很好奇,如果有一个特殊的原因,或者python开发人员只是认为在创建它之后修改属性没有用新的替换它是没有意义的.
你可能是对的,只是将这些属性设为只读的惯例,选择这些属性使属性"全有或全无".似乎更多的是"Pythonic"允许在事后分配它们,但是在Python 2.2发行说明中没有找到基本原理(当引入属性时).
在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}
};
Run Code Online (Sandbox Code Playgroud)
旁白:如果更换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
Run Code Online (Sandbox Code Playgroud)
输出:
True
False
Run Code Online (Sandbox Code Playgroud)