2013-12-18 119 views
0

任何人都可以解釋下面的陌生感嗎?__setitem__和__get__之間的奇怪互動

這按預期工作:

[email protected]:~/Working/wtf$ python -V 
Python 2.7.3 

[email protected]:~/Working/wtf$ cat test_without_get.py 
class B(object): 
    def __setitem__(self, key, value): 
     print "__setitem__" 

class A(object): 
    b = B() 

a = A() 
a.b 
a.b[0] = 1 

[email protected]:~/Working/wtf$ python test_without_get.py 
__setitem__ 

但在這裏__setitem__休息,似乎稱之爲__get__在它的地方:

[email protected]:~/Working/wtf$ cat test_with_get.py 
class B(object): 
    def __setitem__(self, key, value): 
     print "__setitem__" 
    def __get__(self, instance, owner): 
     print "__get__" 

class A(object): 
    b = B() 

a = A() 
a.b 
a.b[0] = 1 

[email protected]:~/Working/wtf$ python test_with_get.py 
__get__ 
__get__ 
Traceback (most recent call last): 
    File "test_with_get.py", line 12, in <module> 
    a.b[0] = 1 
TypeError: 'NoneType' object does not support item assignment 

沒有任何一個有任何見解INT爲什麼發生這種情況 以及如何解決它?


進一步的實驗:

通過伊格納西奧 - 巴斯克斯 - 艾布拉姆斯@的建議, 如果__get__返回一個對象,事情如預期:

[email protected]:~/Working/wtf$ python -V 
Python 2.7.3 
[email protected]:~/Working/wtf$ cat test_with_get_working.py 
class B(object): 
    def __setitem__(self, key, value): 
     print "__setitem__" 

    def __get__(self, instance, owner): 
     print "__get__" 
     return self 

class A(object): 
    b = B() 

a = A() 
a.b 
a.b[0] = 1 

[email protected]:~/Working/wtf$ python ./test_with_get_working.py 
__get__ 
__get__ 
__setitem__ 

,但只有當你是謹慎__get__返回:

[email protected]:~/Working/wtf$ cat test_with_get_notworking.py 
class B(object): 
    def __setitem__(self, key, value): 
     print "__setitem__" 

    def __get__(self, instance, owner): 
     print "__get__" 
     return [1] 

class A(object): 
    b = B() 

a = A() 
a.b 
a.b[0] = 1 

[email protected]:~/Working/wtf$ python ./test_with_get_notworking.py 
__get__ 
__get__ 

回答

1

發生這種情況是因爲您已將B創建爲描述符,因爲它定義了描述符協議方法之一。唯一的解決方法是先不將它創建爲描述符,或者從描述符中返回一個單獨的對象,該描述符的方法的行爲如所期望的那樣。

+0

是的。因爲我的用例需要使用B()作爲描述符,所以返回一個對象。 (有關進一步的實驗,請參閱原始文章中的其他片段)。 – mrdunk