[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