2009-01-09 83 views
2

爲了說明問題,請檢查下面的代碼:爲什麼託管屬性只適用於類屬性,而不適用於python中的實例屬性?

class MyDescriptor(object): 
    def __get__(self, obj, type=None): 
    print "get", self, obj, type 
    return self._v 
    def __set__(self, obj, value): 
    self._v = value 
    print "set", self, obj, value 
    return None 

class SomeClass1(object): 
    m = MyDescriptor() 

class SomeClass2(object): 
    def __init__(self): 
    self.m = MyDescriptor() 

x1 = SomeClass1() 
x2 = SomeClass2() 

x1.m = 1000 
# -> set <__main__.MyDescriptor object at 0xb787c7ec> <__main__.SomeClass1 object at 0xb787cc8c> 10000 
x2.m = 1000 # I guess that this overwrites the function. But why? 
# -> 
print x1.m 
# -> get <__main__.MyDescriptor object at 0xb787c7ec> <__main__.SomeClass1 object at 0xb787cc8c> <class '__main__.SomeClass1'> 10000 
print x2.m 
# -> 10000 
  1. 爲什麼不x2.m = 1000不叫__set__ - 功能?看來這會覆蓋功能。但爲什麼?
  2. _v in x1?這不是在x1._v

回答

3

要回答你的第二個問題,哪裏是_v

描述符本身的描述符版本保持_v。在描述符(類級別的實例SomeClass1,以及所有在SomeClass2類的對象,對象級實例的每個實例將有_v不同的值。

看看這個版本。這個版本更新與相關聯的對象描述,這意味着該對象(SomeClass1x2)將包含屬性_v

class MyDescriptor(object): 
    def __get__(self, obj, type=None): 
    print "get", self, obj, type 
    return obj._v 
    def __set__(self, obj, value): 
    obj._v = value 
    print "set", self, obj, value 
+0

謝謝,這是一個好主意實施。 _v的一個問題:我也無法通過「MyDescriptor._v」訪問它 - 這很明顯,因爲它不是MyDescriptor的類屬性。但是實例的顯式名稱是什麼?它應該以某種方式訪問​​,對吧? – 2009-01-09 15:12:32

3

你應該閱讀thisthis

它overwri測試函數是因爲您沒有重載SomeClass的__set____get__函數,而是MyDescriptor類的函數。也許你想讓SomeClass繼承MyDescriptor? SomeClass1打印「get」和「set」輸出,因爲它是靜態方法AFAIK。詳情請閱讀上面的鏈接。

0

我發現X1_v:它是在SomeClass1 .__的dict __ [ 'M'] ._ v

對於其它應答內由美國洛特建議的版本:_v是在x1._v

相關問題