title: Strange interaction between __setitem__ and __get__
body: <p>Can anyone explain the following strangeness?</p>
  
  <p>This works as expected:</p>
  
  <pre><code>duncan@duncan:~/Working/wtf$ python -V
  Python 2.7.3
  
  duncan@duncan:~/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
  
  duncan@duncan:~/Working/wtf$ python test_without_get.py 
  __setitem__
  </code></pre>
  
  <p>But here <code>__setitem__</code> breaks and appears to call <code>__get__</code> in it's place:</p>
  
  <pre><code>duncan@duncan:~/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
  
  duncan@duncan:~/Working/wtf$ python test_with_get.py
  __get__
  __get__
  Traceback (most recent call last):
    File "test_with_get.py", line 12, in &lt;module&gt;
      a.b[0] = 1
  TypeError: 'NoneType' object does not support item assignment
  </code></pre>
  
  <p>does any one have any insight int why this happens
  and how to work around it?</p>
  
  <hr>
  
  <p>Further experimentation:</p>
  
  <p>as suggested by ignacio-vazquez-abrams@ ,
  if <code>__get__</code> returns an object, things work as expected:</p>
  
  <pre><code>duncan@dunksbox:~/Working/wtf$ python -V
  Python 2.7.3
  duncan@dunksbox:~/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
  
  duncan@dunksbox:~/Working/wtf$ python ./test_with_get_working.py 
  __get__
  __get__
  __setitem__
  </code></pre>
  
  <p>but only if you are careful about what <code>__get__</code> returns:</p>
  
  <pre><code>duncan@dunksbox:~/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
  
  duncan@dunksbox:~/Working/wtf$ python ./test_with_get_notworking.py 
  __get__
  __get__
  </code></pre>