2011-04-23 93 views
6

我目前正在從庫中修補一個類的屬性,以使其更通用。爲什麼property.fget是隻讀屬性?

我用下面的代碼的正常工作這樣做:

_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函數使文檔字符串被保留:

_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開發人員只是認爲它沒有任何意義的修改後創建一個屬性,而不用一個新的替換它。

回答

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} 
    }; 

旁白:如果更換READONLY0和編譯,這一切都需要允許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 
+0

嘿,不錯 - 我不會破解蟒蛇來源雖然:p – ThiefMaster 2011-04-23 18:56:12

+2

當然:-)我只是指出,只讀的背後沒有什麼更奇特的東西。 – samplebias 2011-04-23 18:58:44

+1

可變屬性會爲無意的副作用創造一些可怕的機會。 'Thread.ident.fget = Thread.daemon.fget'任何人? – ncoghlan 2011-04-24 17:10:00

0

與蟒蛇2.3.0(Python的3.4.3)在IDLE殼測試

>>> 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 
>>> 

看起來不那麼只讀給我;)