Wednesday, March 21, 2012

Source code formatting


Ok, about a year ago, I reluctantly adopted PEP8 formatting style for my Python code. Lord knows, we need to make sure that our lines aren't too long for the transition when punch cards come back into vogue. PEP8 also dictates that we have certain numbers of blank lines in certain places to make code more readable. This is where I think that PEP8 doesn't go far enough.

Perhaps the visual pattern matching system in my brain has lapsed into senility, but empty space isn't good enough for me. Maybe I'm just a product of early corruption by COBOL, but I like horizontal lines to mark out blocks in my code. Compare these examples:

    from numbers import Number
  
  
    class Alpha(object):
        """This is a silly class that does very very little"""
        def __init__(self, config):
            self.config = config
  
        def do_something(self, data):
            if isinstance(data, basestring):
                return ''.join(x for x in 'you think this is silly?'
                                 if x not in 'aoeui')
            elif isinstance(data, Number):
                return 2 * data
            else:
                return data
  
        def do_something_else(self, data):
            if data is None:
                return True
            else:
                raise TypeError('only None is acceptable')

I have a tough time seeing the method definitions in the code above.  A single blank line and the indentation is insufficient to make them stand out.  The following code is what I'm likely to write:

    from numbers import Number
   
   
    #==============================================================================
    class Alpha(object):
        """This is a silly class that does very very little"""
        #--------------------------------------------------------------------------
        def __init__(self, config):
            self.config = config
   
        #--------------------------------------------------------------------------
        def do_something(self, data):
            if isinstance(data, basestring):
                return ''.join(x for x in 'you think this is silly?'
                                 if x not in 'aoeui')
            elif isinstance(data, Number):
                return 2 * data
            else:
                return data
        #--------------------------------------------------------------------------
        def do_something_else(self, data):
            if data is None:
                return True
            else:
                raise TypeError('only None is acceptable')


For me, the method definitions stand out.  Scanning down through a long file, I can quickly see and understand the structure.

Am I just a product of a different era?  Why is this style eschewed in most of the code that I see these days?