[Python-3000] enhanced descriptors

tomer filiba tomerfiliba at gmail.com
Sat Jun 10 10:55:17 CEST 2006

disclaimer: i'm not sure this suggestion is feasible to
implement, because of the way descriptors work, but
it's something we should consider adding.

as you may remember, in iostack, we said the position
property should act like the following:

f.position = <non-negative int> # absolute seek
f.position = <negative int> # relative-to-end seek
f.position += <int> # relative-to-current seek

so i wrote a data descriptor. implementing the first two is
easy, but the third version is tricky.
doing x.y += z on a data descriptor translates to
x.__set__(y, x.__get__(y) + z)

in my case, it means first tell()ing, adding the offset, and
then seek()ing to the new position. this works, of course,
but it requires two system calls instead of one. what i
wished i had was x.__iadd__(y, z)

so my suggestion is as follows:
data descriptors must define __get__ and __set__. if they
also define one of the inplace-operators (__iadd___, etc),
it will be called instead of first __get__()ing and then

however, the inplace operators would have to use a different
signature than the normal operators -- instead of
__iadd__(self, other)
they would be defined as
__iadd__(self, obj, value).

therefore, i suggest adding __set_iadd__, or something in
that spirit, to solve the ambiguity.

for example, my position descriptor would look like:

class PositionDesc(object):
    def __get__(self, obj, cls):
        if obj is None:
            return self
        return obj.tell()

    def __set__(self, obj, value):
        if value >= 0:
            obj.seek(value, "start")
            obj.seek(value, "end")

    def __set_iadd__(self, obj, value):
         obj.seek(value, "curr")


p = f.position      # calls __get__
f.position = 5      # calls __set__
f.position = -5     # calls __set__
f.position += 10    # calls __set_iadd__

now there are two issues:
* is it even possible to implement (without overcomplicating the
descriptors mechanism)?
* is it generally useful?

i can't answer the first question, but it would surely be useful
in iostack; and besides, for symmetry's sake, if x += y calls
x.__iadd__(y), it should be optimized for descriptors as well.
i'd hate having to do two system calls for something that can
be done with one using seek().


More information about the Python-3000 mailing list