[Tutor] dictionary dispatch for object instance attributes question

Jeff Shannon jeffshannon at gmail.com
Wed Feb 16 03:20:09 CET 2005

On Tue, 15 Feb 2005 17:19:37 -0500, Brian van den Broek
<bvande at po-box.mcgill.ca> wrote:

> My Node class defines a _parse method which separates out the node
> header, and sends those lines to a _parse_metadata method. This is
> where the elif chain occurs -- each line of the metadata starts with a
> tag like "dt=" and I need to recognize each tag and set the
> appropriate Node object attribute, such as .document_type. (I do not
> want to rely on the unhelpful names for the tags in the file format,
> preferring more self-documenting attribute names.)

In addition to using setattr(), I'd take a slightly different approach
to this.  (This may just be a matter of personal style, and is not as
clearly advantageous as using setattr() instead of exec, but...)

.class Node(object):
.    metadata = {'dt': 'document_type', 'something': 'some_other_field', ...}
.    def __init__(self):  # ....
.    def update(self, **kwargs):
.        for key, value in kwargs.items():
.        try:
.            attr_name = self.metadata[key]
.        except KeyError:
.            raise ValueError("Invalid field type '%s'" % key)
.        setattr(self, attr_name, value)

For starters, I've made metadata a class attribute rather than an
unconnected dictionary.  This seems conceptually nicer to me.

In addition, update() can now modify several attributes at once, at
the cost of a bit of extra parsing up front.

Supposing that your node header looks like this:

.header = "dt=text/plain;something=some_value;last=some_other_thing_here"

Now, we can break that into fields, and then split the fields into a
name and a value --

.tags = {}
.for field in header.split(';'):
.    name, value = field.split('=')
.    tags[name] = value
.n = Node()

You can even simplify this a bit more, by rewriting the __init__():

.    def __init__(self, **kwargs):
.        if kwargs:
.            self.update(**kwargs)

Now you can create and update in a single step:

.n = Node(**tags)

You could also put all of the splitting into fields in a method, and
when __init__ gets a single string as its argument simply pass it to
that method and update with the results...

--Jeff Shannon

More information about the Tutor mailing list