[Tutor] a question about indentation

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Fri Nov 24 20:20:31 CET 2006


> I'm fairly new to python, and trying to get used to the indentation. I
> just encountered my first problem with it. I wrote the following code:
>
> for ord in f_ord:
>        if not ordliste.has_key(ord) :
>            ordliste[ord] = {}
>        for word in e_ord:
>            if ordliste[ord].has_key(word) :
>                ordliste[ord][word] += 1
>            else :
>                ordliste[ord][word] = 1
>
> and then later realized I had to put in one more if-test at the
> beginning of the loop. In most languages I've used, this would be simple
> -- I would simply enclose lines 2-8 in curly braces and put the if-test
> in front.


Hi Arild,


Try using functions more.  Well-written functions can help to support the 
kind of rapid changes that you're making to your program, and to reduce 
the nesting that you're seeing.

Concretely, there's a block in the code that updates the dictionary data 
structure.

>        if not ordliste.has_key(ord) :
>            ordliste[ord] = {}
>        for word in e_ord:
>            if ordliste[ord].has_key(word) :
>                ordliste[ord][word] += 1
>            else :
>                ordliste[ord][word] = 1


We can turn that block into a full-fledged function:

################################################
def update_ordliste(ordliste, ord, words):
     if not ordliste.has_key(ord):
         ordliste[ord] = {}
     for word in words:
         if ordliste[ord].has_key(word) :
             ordliste[ord][word] += 1
         else:
             ordliste[ord][word] = 1
################################################

(There is actually a nicer way to write update_ordliste, but I'll leave 
that for another time.)



Once we have this, we can revisit the original code, and turn:

> for ord in f_ord:
>        if not ordliste.has_key(ord) :
>            ordliste[ord] = {}
>        for word in e_ord:
>            if ordliste[ord].has_key(word) :
>                ordliste[ord][word] += 1
>            else :
>                ordliste[ord][word] = 1

into:

#########################################
for ord in f_ord:
     update_ordliste(ordliste, ord, e_ord)
#########################################

This code is in a form that should be easier to change more rapidly, since 
the block is itself not too nested or long.

The general idea is that, when we have a for loop on a fairly long and 
substantial block, there's often a name we can give to the concept that 
it's doing.  "update_ordliste" is not such a good, descriptive name, 
though: if you can think of a better name, please feel free to change it. 
*grin*


> When I try do it in python, however, it seems I have to do the 
> indentation all over.

With the refactored code above, we can support this kind of change with 
very little work:

#############################################
for ord in f_ord:
     if not ord in tegn:
         update_ordliste(ordliste, ord, e_ord)
#############################################



> This isn't really a problem in this case, as the expression is quite 
> small, and I can quickly check the indentation line by line. But I can't 
> begin to imagine what a hassle that would be if my expression was 70 
> lines and not 7.

Text editors for Python often support indenting whole blocks.  If you're 
using Emacs, for example, "C-c >" should indent a block forward.  I'm sure 
that other Python-aware text editors provide similar tools.

What IDE are you using?

You bring up a good point that it's a hassle to adjust long blocks of 
code.  One way to attack this problem is to avoid it altogether: it's 
often very possible to refactor the code to make code blocks smaller or 
simpler.


More information about the Tutor mailing list