Fast attribute/list item extraction

P

Peter Otten

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.attr
extract(name="attr") # necessary when attribute name only known at runtime

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

# extract a dictionary value
extract["key"]
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):
self.name = name
def __call__(self, obj):
return getattr(obj, self.name)

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),
print

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 :)

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top