[Python-ideas] Extending properties to sequence-like behavior

Raymond Hettinger raymond.hettinger at gmail.com
Wed Apr 6 07:52:23 CEST 2011


On Apr 5, 2011, at 10:31 PM, Dan Baker wrote:
> I want to be
> able to translate:
> 
> return box.Items -> return box.GetAllItems()
> box.Items = itemlist -> box.SetAllItems(itemlist)
> return box.Items[idx] -> return box.GetItemAtPos(idx)
> box.Items[idx] = new_item -> box.SetItemAtPos(idx, new_item)
> 
> Just using property() doesn't quite work; it handles the "set all" and
> "get all" operations easily enough, and "get item" works for any
> interface that it would be sane to attempt this on by just getting the
> appropriate slice of the list returned by "get all" (although this may
> be inefficient compared to calling the real "get item" function), but
> "set item" doesn't work because it calls "get all" and then assigns to
> a slot in the list returned by that function.
> 
> The best solution I've come up with so far is to create an object (of
> a class I'll call ListProp) and have the "get" function of the
> property return this object. Then I can override the __getitem__ and
> __setitem__ methods to call the "get item" and "set item" functions.
> The "get all" function no longer works exactly as above, though;
> box.Items would instead return the ListProp object. This can be solved
> by using __call__ on the ListProp as the "get all" method; then the
> only change is to use box.Items() for the "get all" function.
> 
> I've attached some scratch code here (Python 2.7) demonstrating the
> basic idea. Is there a better way to do this?

I don't see any other way.  You're solution is probably the only
workable approach.

Since the [idx] call occurs after the box.Items attribute lookup, 
the box.Items lookup needs to return some object that can a 
subsequent [idx] call using __getitem__ or __setitem__:

>>> from dis import dis
>>> dis(compile('box.Items[idx] = new_item', '', 'exec'))
  1           0 LOAD_NAME                0 (new_item)
              3 LOAD_NAME                1 (box)
              6 LOAD_ATTR                2 (Items)
              9 LOAD_NAME                3 (idx)
             12 STORE_SUBSCR        
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        

Thanks for the interesting post.  Nice work in figuring this all out.


Raymond








More information about the Python-ideas mailing list