[Types-sig] getattr glitch

Edward Welbourne Edward Welbourne <eddy@chaos.org.uk>
Wed, 9 Dec 1998 02:36:22 +0000 (GMT)

I noticed a glitch in my getattr, I now want it to start

def readattr(obj, key):
    try: return obj.__dict__[key]
    except KeyError: pass

def basereadattr(obj, key):
    try: return readattr(obj, key)
    except AttributeError: pass
    for base in obj.__bases__:
	try: return readattr(base, key)	# not getattr, I think.
	except AttributeError: pass

    raise AttributeError

def getattr(obj, key):
    try: return basereadattr(obj, key)
    except AttributeError: pass

    for whatever in obj.__classes__: ...

but this just makes basereadattr another simple and easy tool that we
can fit in with the whatever.__getinstattr__ methods and, for that
matter, the trailing __getattr__ protocol.

We'd then reduce to

def getattr(obj, key):

    for col in obj.__protos__:
	try: return col(obj, key)
	except AttributeError: pass

    raise AttributeError

and each col would `own' a piece of obj's namespace (__bases__ and
__dict__ owned by readattr and co-operating protocols, __getitem__ by
the fallback protocol in which __protos__ usually ends, etc.).
The familiar class/instance protocol (which owns __class__) becomes

def getinstattr(obj, key):
    val = getattr(obj.__class__, key) # fail with AttributeError if absent
    try: meth = val.bind(obj)
    except (AttributeError, BindingError): return val
    else: return meth

and appears in every instance's __proto__ just behind basereadattr.

Now __bases__ becomes redundant by putting
	lambda s, k, b=base, r=readattr: r(b, k)
into __protos__ for each base we would have put in __bases__.  One could
even use getattr for some bases, as I did in my original for all.

It's too am and I wrote a whole lot more but I've snipped it off to make
sense of it later and I'll send the sane bit now <yawn>