A modest indentation proposal

Quinn Dunkan quinn at chunder.ugcs.caltech.edu
Mon Dec 3 17:37:13 EST 2001


On Mon, 3 Dec 2001 11:23:09 +0100, Andreas Kostyrka <andreas at mtg.co.at> wrote:
>> The latest changes in 2.2 do a lot to address this, I think.  At the cost
>> of two kinds of classes and method lookup rules and a semi smalltalk style
>Well, old style classes will be depracted some time in the future. Being so 
>fundamental as it is, it will take a long time.

I'd be kind of surprised if we ever get rid of classic classes.  If you think
there was a lot of noise about integer division a while back...

While premature optimization may be the root of all evil, I think maintaining
backward compatibility while trying to "fix" old mistakes is another.  You
just keep accumulating gunk.

>> Since new magic attributes seem to pop up every day, what about existing
>> __getattr__-using code that had all the holes patched up, but is now going
>> to explode because suddenly python wants to look up an __eq__ method where
>> it never did before?
>well, I personally prefer this design:
>def __getattr__(self,k):
>  # special ones we need to deal with.
>  if k=="__repr__":
>    pass
>  elif k.startswith("__"):
>    raise AttributeError,k
>  else:
>    # deal here with the "normal" stuff
>    pass

Yeah, but that won't help much for delegation, like:

def __getattr__(self, k):
    return getattr(self.__data, k)

Oh wait!  What if '__data' is a list (and we're not in 2.2 yet)?  Now we need:

def __len__(self):
    return len(self.__data)
def __delitem__(self, k):
    del self.__data[k]
... etc. ...

Or what if __getattr__ is supposed to force a lazy object?  Now they all need
to be:

def __getattr__(self, k):
    self.__force() # handle memoization etc.
    return getattr(self.__data, k)
def __len__(self):
    self.__force()
    return len(self.__data)
def __del__(self):
    pass # *don't* force!
def __cmp__(self, other):
    self.__force()
    return cmp(self.__data, other)
... etc. ...

I solved the above with:

class Lazy_attr:
    def __init__(self, attrs):
        'attrs is [(f_to_set_attr1_attr2, (attr1, attr2))]'
        self.__attrs = list(attrs)
    def __getattr__(self, attr):
        for i in range(len(self.__attrs)):
            f, attrs = self.__attrs[i]
            if attr in attrs:
                f()
                del self.__attrs[i]
                return getattr(self, attr)
        else:
            raise AttributeError(attr)

... where f() is expected to set the attribute, thus avoiding the __getattr__
overhead in subsuquent lookups.



More information about the Python-list mailing list