This simple collection class forwards requests to
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #!/usr/bin/env python
import UserList
class Collection(UserList.UserList):
"""Collections group objects together and forward attribute lookups.
At least this is the Collection I remember from LYMB (an interpreted OO
language developed by Bill Lorensen et al at GE CRD), which almost
certainly got it from Smalltalk.
"""
def get(self, attr):
"""return a list of attributes from ourselves.
note that an object in the collection is not required to have 'attr',
so the result may be shorter than the collection itself."""
return Collection([getattr(x, attr) for x in self if hasattr(x, attr)])
def call(self, attr, *args, **kwds):
"""return the result of calling 'attr' for each of our elements"""
attrs = self.get(attr)
return Collection([x(*args, **kwds)
for x in attrs
if callable(x)])
if __name__ == "__main__":
import time
class Food:
def __init__(self):
self.t = time.time()
time.sleep(0.5)
class Ham(Food):
def say(self):
print "I am Ham, and I don't want any arguments, thank you."
return ()
def speak_up(self, arg):
print 'I am Ham, and my arguments are %s' % arg
return arg
class Eggs(Food):
def speak_up(self, arg='bacon'):
print 'I am Eggs, and my arguments are %s' % arg
return arg
class Spam(Food):
def shout(self, arg1, arg2='sausage'):
print 'I AM SPAM AND MY ARGUMENTS ARE %s AND %s' % (arg1, arg2)
return (arg1, arg2)
c = Collection()
# kind of boring example...
c.extend(range(3))
print c.get("__hash__")
print c.call("__hash__")
print
# slightly more interesting example...
c = Collection([Ham(), Eggs(), Spam()])
print "*** when was this food made? ***"
times = c.get("t")
print map(round, times, [2]*len(times))
print
print "*** what kind of food is it? ***"
print c.get("__class__").get("__name__")
print
print "*** shouting ***"
print c.call("shout", "nickel", "dime")
print
print "*** speaking up ***"
print c.call("speak_up", "juice please")
print
print "*** saying ***"
print c.call("say")
print
|
Programmers occasionally want to call the same method or retrieve the same data attribute for a group of objects. If you want to call a function for each of a group of objects, map() does the trick. The common idiom to call a method for a group of objects is something like
for o in list_of_objects:
o.some_method(*someargs, **somekwds)
with suitable tests for existence of some_method.
The Collection class simply makes that idiom somewhat easier to use.