Welcome, guest | Sign In | My Account | Store | Cart

This simple collection class forwards requests to

Python, 83 lines
 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.