July 2003 archive

Formatting a Simple Function in Python

I use Python often for writing web based applications, such as this weblog you’re reading right now. I love using Python, but I occasionally have problems with making the code asthetically pleasing. This article presents a short case study into formatting a simple function from my website’s picture gallery.

Original code (artifically wrapped for web viewing):


def getThumbnailLink(self):
    return '<a href="%s"><img class="thumbnail" src="%s" width="%s" height="%s"
/></a><br /><span class="thumbnail-title">%s</span>' % (self.getHandPageURL(),
self.getWebPath(self.getThumbnailPath()), self.thumbnailDimensions[0],
self.thumbnailDimensions[1], self.title)

This code presents a simple problem. It has large line of code. I like to keep lines of code to shorter than 79 columns when possible. Additionally, this code is hard to modify. I approached this because I wanted to add an alt attribute into the img tag, but found that where I put the attribute would actually affect the order of elements in the tuple. That’s really unfortunate.

The first attempt to clean up this code was simply by putting a linebreak in between the string literal and the tuple (also artificially wrapped for web viewing):


def getThumbnailLink(self):
    return '<a href="%s"><img class="thumbnail" src="%s" width="%s" height="%s"
/></a><br /><span class="thumbnail-title">%s</span>' % \
        (self.getHandPageURL(), self.getWebPath(self.getThumbnailPath()),
self.thumbnailDimensions[0], self.thumbnailDimensions[1], self.title)

This helped a bit, but both lines were still greater than 79 characters, and it failed entirely to address the problem of the tuple ordering. I whacked at it with the enter and tab keys for a while, but didn’t get anywhere. Fearing I was low on visionary power, I consulted with Lynx. She threw out a chunk of code with shorter lines:


def getThumbnailLink(self):
    ret1 = '<a href="%s"><img class="thumbnail" src="%s" width="%s"'
    ret2 = ' height="%s" /></a><br /><span class="thumbnail-title">%s</span>'
    t = self.getWebPath(self.getThumbnailPath())
    ret1 = ret1 % (self.getHandPageURL(), t, self.thumbnailDimensions[0])
    ret2 = ret2 % (self.thumbnailDimensions[1], self.title)
    return "%s%s" % (ret1, ret2)

This code was a bit of an improvement. It’s a bit more flexible because there aren’t any tuples of arguments that are quite as long as the original, and the code lines are shorter. The function has grown a bunch of extra operations (but who cares?), and a number of extra lines (oh, my poor hard drive…), but it’s definately an improvement.

I wondered whether there wasn’t a better way to write such a small function. I thought about common templating systems and how they work, such as [A-Z]SP, but I didn’t want to do anything that complex. I like the idea of seperating code and HTML, and this current function and server-page technologies do the opposite of that. I pounded at it for a bit, and came up with this function:


def getThumbnailLink(self):
    htmlText = """
        <a href="%(handURL)s">
            <img class="thumbnail" src="%(thumbnailImageURL)s" alt="[%(title)s]"
            width="%(thumbnailImageWidth)s" height="%(thumbnailImageHeight)s" />
        </a>
        <br />
        <span class="thumbnail-title">%(title)s</span>"""
    return htmlText % \
        {'handURL': self.getHandPageURL(),
        'thumbnailImageURL': self.getWebPath(self.getThumbnailPath()),
        'thumbnailImageWidth': self.thumbnailDimensions[0],
        'thumbnailImageHeight': self.thumbnailDimensions[1],
        'title': self.title}

This function shortens the lines of code, addresses the issue of the tuple ordering, and it also seperates the HTML from the Python code. It would be easy to get the htmlText variable from a module full of HTML strings which define the entire web page. It wouldn’t be as flexible as a full-out template system, but I like it more.