[Python-Dev] Re: "groupby" iterator

Duncan Booth duncan at rcp.co.uk
Wed Dec 3 09:25:25 EST 2003

Nick Coghlan <ncoghlan at iinet.net.au> wrote in
news:3FCDCDA1.2040402 at iinet.net.au: 

> Raymond Hettinger wrote:
>> Carried to the limit, the idea turns into something that is
>> either sublime or severely bonkers.  The good points are that
>> Guido gets his dotted access and I get to trade in the two ugly
>> names and for a single beautiful "extract".  And there's no
>> performance cost, the inner loop is the same.  The downside is I
>> still don't know how to explain it (AFAICT, super() is the closest
>> thing to it): 
> What you end up with is still a unary operator, so it could still live
> in the operator module, to.
> And I think what you posted would work for strings as dictionary keys,
> too - answering another of the objections to the original
> operator.extract 
You could even consider reinstating the ability to chain extract 
operations. (Although this may be even harder to explain).
The version below allows attribute and item access to be chained and mixed 

class ExtractorClass(object):
    def __init__(self, fn=None, arg=None, parent=None):
        if fn is None:
            extract = []
            extract = [(fn,arg)]
        if parent is not None:
            extract = parent._accessors + extract
        self._accessors = extract
    def __getattribute__(self, attr):
        if attr == '_accessors':
            return object.__getattribute__(self, attr)
        return ExtractorClass(getattr, attr, self)
    def __getitem__(self, key):
        return ExtractorClass(operator.getitem, key, self)
    def __call__(self, obj):
        for fn, arg in self._accessors:
            obj=fn(obj, arg)
        return obj
extract = ExtractorClass()

class A:
a = A()
a.score = 10
b = A()
a.b = b
b.score = 42
getscore = extract.score      # Houston, we have dotted access
print getscore(a)

getsubscore = extract.b.score # Chaining
print getsubscore(a)

b = [10, 20, 30, 40]

getsecond = extract[1]        # and, we have the bracketed lookups 
print getsecond(b)

a.b = b
getbsecond = extract.b[1]   # Chain a mix of attributes and indexes.
print getbsecond(a)

Duncan Booth                                             duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?

More information about the Python-Dev mailing list