[Tutor] container class

Paul Sidorsky paulsid@shaw.ca
Sat, 02 Feb 2002 22:35:09 -0700

Tim Wilson wrote:

> I've just put together a couple classes here investigating how to do a
> container class. Does the following seem reasonable? There isn't yet
> enough for any sort of useful program, but I think it shows my train of
> thought. Any feedback appreciated.

Strictly speaking, I don't believe these aren't container classes.  A
container class to me is a generic class that can contain any type of
object.  Python already provides a bunch of 'em (list, dictionary,
etc.).  Anyhow, that's just a terminology thing.  I know what you meant.

> # PyAddress, a simple program to organize names and addresses
> # by Tim Wilson <wilson@visi.com>

This should maybe be a module docstring.  Otherwise, good use of
docstrings throughout!

> class AddressBook:
>     def __init__(self):
>         """Initialize an empty address book."""
>         self.contents = {}

For maximum flexibility I suggest adding the capability to pass an
optional list of initializing entries:

    def __init__(self, initlist=[]):
        """Initialize an empty address book."""
        self.contents = {}
        for entry in initlist:

In fact, you could even put the last two lines in an addListOfEntries()
method which could then be used independently.  It may be handy for file
I/O, copying/pasting of entries, etc.  Given that a minimal amount of
effort is needed and the fact you're taking a "container class
approach", it certainly seems worth it.

>         self.contents[entry.ln + entry.fn] = entry

You may want to consider indexing your dictionary like this:

self.contents[(entry.ln, entry.fn)]

This is a little clearer IMO.  Furthermore, with your method there is a
very small possibility of collision for people with different names. 
Consider 1) fn="paul", ln="adamson" and 2) fn="paula", ln="damson". 
Both would yield "pauladamson" as a key name.  Granted this is a
contrived example, but problems like this do show up in the real world
quite a bit and are _EXTREMELY_ hard to track down, so I think it's best
to learn to watch for them and then get into the habit of preventing
them at the earliest possible stage.

>         for name in k:
>             entry = self.contents[name]
>             print entry

I'm not sure where others stand on creating single-use variables
('entry' in the case above), but my personal feeling is they normally
aren't necessary and tend to clutter up code.  That's more of a personal
preference thing though.

>     def __str__(self):
>         """One-line version of entry info."""
>         name = self.ln + ', ' + self.fn
>         return "%-20s %-12s" % (name, self.phone)

Exception to above - the 'name' variable makes the display string much
easier to use/maintain.

All in all, it looks very good!  Actually this is a very nice example of
class usage in a situation where it's very tempting not to bother with a
class in the first place.

Paul Sidorsky                                          Calgary, Canada
paulsid@shaw.ca                        http://members.shaw.ca/paulsid/