Fast attribute/list item extraction

Peter Otten __peter__ at
Sun Nov 30 11:45:14 CET 2003

There is currently a discussion on python-dev about an extract() function
which offers fast access to list items and object attributes. It could
serve, e. g., as the key argument of the future list.sort() method:

extract("attr") # extract an attribute
extract(1) # extract a list item

Below is a slight variation of this idea, together with a pure-python
implementation. As a "real" C version is currently beyond me, I chose not
to post it on python-dev.

Following variants are possible:

# extract an attribute
extract(name="attr") # necessary when attribute name only known at runtime

# extract a list item or slice
extract(index=1) # for symmetry only

# extract a dictionary value
extract(key="key") # for symmetry only

<toy implementation>
# the gory details
class GetItem(object):
    def __init__(self, index):
        self.index = index
    def __call__(self, item):
        return item[self.index]

class GetAttr(object):
    def __init__(self, name): = name
    def __call__(self, obj):
        return getattr(obj,

class Extract(object):
    def __getitem__(self, key):
        return GetItem(key)
    def __getattribute__(self, name):
        return GetAttr(name)
    def __call__(self, name=None, key=None, index=None):
        assert sum([name is None, key is None, index is None]) == 2, (
        "Please provide only one of these arguments: name, key, index")
        if name is not None: return GetAttr(name)
        if key is not None: return GetItem(key)
        return GetItem(index)

extract = Extract()

# usage demonstration

class Demo:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return "(x=%s, y=%s)" % (self.x, self.y)
    __repr__ = __str__

indexSample = [(1, 10), (2, 20), (3, 30)]
keySample = [{"x": x, "y": y} for x, y in indexSample]
attrSample = [Demo(*xy) for xy in indexSample]

print "Index", indexSample
print "Key", keySample
print "Attribute", attrSample

def printSeq(seq, extractor):
    for item in seq:
        print extractor(item),

printSeq(indexSample, extract[0])
printSeq(indexSample, extract(index=1))
printSeq(indexSample, extract[:])

printSeq(attrSample, extract.x)
printSeq(attrSample, extract(name="y"))

printSeq(keySample, extract["x"])
printSeq(keySample, extract(key="y"))

</toy implementation>

Comments welcome :-)


More information about the Python-list mailing list