tags:

views:

113

answers:

3

I'm an experienced programmer, but still a little green at python. I just got caught by an error in indentation, which cost me a significant amount of debugging time. I was wondering what experienced python programmers do to avoid creating such problems in the first place.

Here's the code (Part of a much larger program) :

class Wizvar():

    def select(self):
        self.selected = True

    def unselect(self):
        self.selected = False

        value = None

The problem is that 'value = None' should be outdented one level. As it is, the variable gets clobbered every time the unselect method is called, rather than once only. I stared at this many times without seeing what was wrong.

+1  A: 

In general: a lot of unit testing. Code reviews also help a lot.

This specific error seems like an easy one to identify since if value was supposed to be outdented once it would have been a class variable, proper unit testing would have spotted that it isn't in this case.

Tools like PyDev do a good job at finding some other common mistakes so you might want to consider those.

Idan K
+8  A: 

Put all the class attributes (e.g. value) up at the top, right under the class Wizvar declaration (below the doc string, but above all method definitions). If you always place class attributes in the same place, you may not run into this particular error as often.

Notice that if you follow the above convention and had written:

class Wizvar():
        value = None

    def select(self):
        self.selected = True

    def unselect(self):
        self.selected = False

then Python would have raised an IndentationError:

% test.py
  File "/home/unutbu/pybin/test.py", line 7
    def select(self):
                    ^
IndentationError: unindent does not match any outer indentation level
unutbu
This is good advice. In fact, it's what I normally do in other languages. I have no idea why I didn't do it in this case.But what I'm asking about is techniques that would be specific to python.
Neil Baylis
@Neil: Unfortunately, I can't think of any Python-specific techniques that could be helpful here, only general techniques. Unit-testing has been mentioned. I use print statements liberally when debugging, and tend to write code in small bits with (unit)test runs in between. Now that you've been bitten by this, I suspect your awareness of this potential problem will be greatly heightened, and maybe that in itself will prevent future errors.
unutbu
+1  A: 

I don't have such problems ;) At least I have them less often than a superfluous, missing or misplaces brace or the classic:

if (foo) 
    bar();
    baz();

in language that use braces.

That being said, certain coding styles help. For example, I always list class variables at the top of the class body, so if I accidentally the indentation, I'll get an IndentationError instead of creating an unused local variable. By the way, I've always seen it like this. Consistent indentation (I'm with PEP 8 and use 4 spaces) also helps, some people use only one space for some blocks - that's really easy to overlook.

Static code analysis (like PyLint) may point such errors out, but I don't have much experience with these. As I wrote, it just works most of the time.

delnan
Totally agree that python's significant whitespace prevents more problems than it causes, as well as promoting good meta-programming practices like stylistic consistency between coders.
Seamus Campbell