E-Scribe News : a programmer’s blog

About Me

PBX My name is Paul Bissex, and e-scribe.com is my consulting business. I build web applications using as much open source software as possible. From September to June I teach web design and other important non-photographic professional skills to photographers. In the '90s I wrote technology commentary and reviews for magazines, newspapers, and web publications, including Wired, Salon.com, FamilyPC, the late lamented Web Review, and the Chicago Tribune. Feel free to email me.

Book Project

I'm co-authoring a book, "Python Web Development with Django", with Jeff Forcier and Wesley Chun. It will be published by Prentice Hall in July 2008, but is available for pre-ordering on Amazon now.

Colophon

This site is built on a fresh trunk checkout of Django, running on Python 2.5.1, served by Apache and mod_python. The database is SQLite. The operating system is FreeBSD, on a VPS hosted at Johncompanies.com. Comment-spam protection by Akismet. Vintage topo imagery from the Maptech archive.

Pile o'Tags

Stuff I Use

Akismet, del.icio.us, Django, dpaste.com, Emacs, FreeBSD, Freenode, jQuery, LaunchBar, MacPorts, Markdown, Mercurial, OS X, Postfix, Python, SQLite, Subversion, TextMate, Trac, Ubuntu Linux, wmii

A Django site.
(Finally!)

Copyright 2008
by Paul Bissex
and E-Scribe New Media

Neat Python hack: infix operators

I came across this neat Python hack on reddit today, a technique for defining arbitrary infix operators. Not overriding + or >> et al., but creating keyword-style pseudo-operators that... well, the code is probably as clear as any description I could come up with:

class infix(object):
    """
    Clever hack (slightly modified) for defining infix operators. 
    Via http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/384122
    Intended for use as a decorator.

    >>> @infix
    ... def removing(str, chars):
    ...     for char in chars:
    ...         str = str.replace(char, '')
    ...     return str
    ...
    >>> print 'Hello, world!' |removing| 'eo'
    Hll, wrld!
    """
    def __init__(self, function):
        self.function = function
    def __ror__(self, other):
        return infix(lambda x: self.function(other, x))
    def __or__(self, other):
        return self.function(other)
    def __call__(self, value1, value2):
        return self.function(value1, value2)

Some people hate this kind of stuff. That's why we call it a hack, to indicate that we don't think it's a great building block for your missile control software. Some of Those People still get their underoos in a bunch regardless. But you have to admit it's damned clever.

This also reminds me of some of the lovely higher-order-function features in Haskell, where you can make a regular (prefix) function into infix by wrapping it in backticks -- 10 `mod` 3 -- and an infix function (operator) into prefix by wrapping it in parentheses -- (+) 2 2.

Sunday, February 25th, 2007
+ + +
5 comments

Comment from Justin, later that day

I totally hate it. :)

Comment from James, 4 days later

I totally love it. :)

Comment from Paul, 1 week later

Now that's what I call fair and balanced.

Comment from bruce, 14 months later

class infix2(object):
    def __init__(self, function):
        self.function = function
    def __ror__(self, other):
        self.value=other
        return self
    def __or__(self, other):
        return self.function(self.value,other)

With this version, you do not instanciate a lambda object for each __ror__ call. On my PC, it's 45% performance gain !

Comment from Paul, 14 months later

I love that you profiled it.

Post a comment

Comments use Markdown syntax. Your comment will not appear until approved, which may take a few hours or more. Spammers will be torpedoed.


(Will not be shared)

(Optional)