• Skip to primary navigation
  • Skip to main content

Algorithm.co.il

  • About
  • Best Posts
  • Origami
  • Older Projects

Various Small Python Helpers

Posted on 2008-03-09 by lorg 5 Comments

I’ve been working lately with arkon on various projects related to diStorm. One of these projects involved writing a solid Python API around an existing C API. This C API uses a lot of flags as arguments and return values of functions.
Since I want my code to be easy to use in an interactive shell, I’d like to return something that’s not just a number. The obvious solution is to use a Python Enum. There are many implementations going around, most of them equivalent. I’ve got the one I use. What I recently added though, is the SymbolInt:

def SymbolInt(value, name):
    class _SymbolInt(int):
        def __str__(self):
            return name
        def __repr__(self):
            return 'SymbolInt(%d, "%s")' % (value, name)
        def __eq__(self, other):
            if isinstance(other, str):
                other = other.lower()
            return int(self)==other or name.lower() == other
        def __ne__(self, other):
            return not self == other
    return _SymbolInt(value)

def SymbolInt(value, name): class _SymbolInt(int): def __str__(self): return name def __repr__(self): return 'SymbolInt(%d, "%s")' % (value, name) def __eq__(self, other): if isinstance(other, str): other = other.lower() return int(self)==other or name.lower() == other def __ne__(self, other): return not self == other return _SymbolInt(value)

Short, and very much to the point, this makes exploratory API’s much more readable and usable. It is useful as a return value from enum functions as well.

Along with SymbolInt I wrote hexint:

class hexint(long):
    def __str__(self):
        return hex(self)[2:-1]
    __repr__ = __str__
    def __repr__(self):
        return hex(self)[:-1]

class hexint(long): def __str__(self): return hex(self)[2:-1] __repr__ = __str__ def __repr__(self): return hex(self)[:-1]

This one makes program addresses readable.

Lastly, here’s a little function that I found missing from itertools:

def head(iterable, num_items):
    for obj,i in zip(iterable,xrange(num_items)):
        yield obj

def head(iterable, num_items): for obj,i in zip(iterable,xrange(num_items)): yield obj

UPDATE: Don’t use this head() function, use itertools.islice instead. Thanks go to Erez for pointing that out.

Filed under: Programming, Python, Utility Functions

Reader Interactions

Comments

  1. Yoni says

    2008-03-09 at 4:16 pm

    Neat @ first two.

    The last one isn’t missing (unless I misunderstood your intent): “enumerate” is a built-in since Python 2.4, I believe.

    Reply
  2. lorg says

    2008-03-09 at 4:53 pm

    Yoni: You misunderstood my intent. Head takes the first num_items from iterable.
    I’m piggy-backing on zip’s behavior. zip always takes the shorter of the input sequences.
    It also works for infinite sequences (such as itertools.count()).

    Maybe I should have used itertools.izip instead though, to avoid generating the num_items of iterable at once.

    And thanks!

    Reply
  3. Erez says

    2008-03-13 at 12:05 pm

    Hi, two suggestions:
    1) Replace hex(self)[2:-1] with ‘%x’%self. It’s prettier.
    Also, the ‘L’ postfix gets abandoned in Python 3.0 .

    2) Your ‘head’ function is just a special case of ‘itertools.islice’ .

    Reply
  4. lorg says

    2008-03-14 at 6:50 am

    1. You are correct. Using %x is more elegant, and will work in Python 3.
    2. You are correct on this one as well. In fact, my implementation of head might cause a potential bug. This is because zip (and izip) leave long iterators in an uncertain state, by taking more elements than they should.

    Reply

Leave a Reply Cancel reply

© 2022 Algorithm.co.il - Algorithms, for the heck of it