トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

Pythonとインデント

Pythonとインデント

 インデント記法の長所

1から1000までの整数の和を表示するプログラムは、Pythonで書くと、4行ですむ。

x=0
for i in range(1,1001):
    x += i
print x

これを、他の言語で書くと、

  • C言語
int main(int argc, char* argv[])
{
    int i,x=0;
    for(i=1;i<=1000;i++){
        x+=i;
    printf("%d\n", x);
}

6行。

  • Fortran
program main
integer i,x
x=0
do i=1,1000
    x = x+i
end do
write(*,*) x
end

8行。

  • Perl
$x=0;
foreach $i ( 1..1000 ){
  $x+=$i;
}
print "$x\n";

5行。

  • Pascal
program main
  var
    x,i:integer;
  begin
    x:=0;
    for i:=1 to 1000 do
      begin
        x := x+i;
      end;
    writeln(x);
  end.

11行

ここに挙げたのは、いずれも少しオーソドックスな言語。これらの言語と比べると、Pythonの文法は際だってシンプルであることがわかる。

なぜシンプルに書けるのか。それは、Python独特のプログラム記法=インデントのせい。

他の言語も、インデントを使って記述してあるが、Python以外の言語では、インデントには何の意味もなく、単に読みやすくするためだけの習慣的な約束事にすぎない。例えば、上のFortranプログラムの場合は、

program main
integer i,x
x=0
do i=1,1000
x = x+i
end do
write(*,*) x
end

とべたっと書いても構わないし、その他の言語(Pascal、C、C++、Perlなど)に至っては、改行すらも任意なので、

program main var x,i:integer; begin x:=0; for i:=1 to 1000 do begin x := x+i; end; writeln(x); end.

と書いても構わない。

一方、Pythonの場合は改行にもインデントにも意味がある。改行は文と文を区切り、インデントはブロック(文のあつまり)を明示する。上のプログラム

x=0
for i in range(1,1001):
    x += i
print x

を、

x=0
for i in range(1,1001):
    x += i
    print x

に書きかえると、何がおこるだろうか。

前者では、最後の行にはインデントがないので、最後の行はfor文のブロックの外にあるとみなされる。後者では、プリント文はブロック内にあるとみなされる。

for文のブロック内は1000回実行されるので、前者ではxの値は最後に一回だけ表示され、後者ではxの値の途中経過が1000回表示されることになる。

このように、インデントを使ったpython独特の記法は、プログラムを簡潔にするのに非常に有効である。一方、従来の言語では、ブロックの終わりが"end"や"}"で明示されるが、Pythonの場合それに相当するものがないので、ブロックの範囲がわかりにくい場合がある。特に、ブロックが非常に長かったり、多重ブロック(forの中にifがあり、その中にforがある場合など)の場合にはわかりにくい。これを回避する方法として、ブロックが閉じる位置にコメントを入れるという手がある。例えば上の例であれば、

x=0
for i in range(1,1001):
    x += i
#end for i
print x

あるいは、

x=0
for i in range(1,1001):
    x += i
    print x
#end for i

と書いておけば、for文で繰り返す範囲が一目瞭然である。また、積極的に関数を定義して、多重ブロックや長いブロックを書かないで、ブロックの大きさを常に一画面におさまる程度にするのも良い方法である。

 インデントに使う文字

インデントには、タブもしくは空白を使うことができる。空白を使う場合は、個数をきちっとそろえる。タブを使うなら、空白を混在させないように注意する。見かけ上は同じだけインデントされているように見えても、タブや空白が混在していて、しかもその個数が行ごとに異なっていると、同じ字数だけ字下げされているかどうかが判別できないのでエラーになる。

入力するにはタブの方が楽なのだが、タブとスペースが混在した時に気付きにくい。一般には空白4つでインデントすることが推奨されている。

誤りの例

x=0
for i in range(1,1001):
	x += i
        print x

誤り。空白文字のインデントとタブのインデントが混在。

x=0
for i in range(1,1001):
	x += i
 	print x

誤り。タブの前に空白がはいっている行とはいっていない行がある。

x=0
for i in range(1,1001):
 x += i
  print x

誤り。全角漢字の空白文字がはいっている。

 x=0
 for i in range(1,1001):
   x += i
   print x

誤り。インデントの必要のない行にまで空白がはいっている。

 インデント記法の欠点

ただし、欠点もある。プログラムをコピー&ペーストする場合には、非常に慎重になる必要がある。

ひとつは、コピー元と、それを挿入する先でインデントの深さが違う場合、コピーしてもってきた部分にインデントを追加あるいは削除して、インデントをそろえる作業をする必要がある。この時に、本来字下げすべき部分のインデントを誤って消したりすると、一見問題のないプログラムのように見えても、誤動作する。

もう一つは、コピー元が他人のプログラムである場合などで、インデントに使っている文字が違う場合。例えば、自分はタブでインデントを入れているが、コピーした部分はインデントに空白文字が使われている、といった場合、インデント文字を全部統一しないとエラーになる。

今のところ、講義で出てくるプログラムでは、インデントの深さは深くても3段程度なので、そんなに混乱はないと思うが、もっと本格的に大きなプログラムを書く場合には、Pythonの編集に適したテキストエディタを物色したほうがいいだろう。

インデントが深いということは、それだけforやifを多用した複雑なプログラムになっていることを意味する。forの中身やifの中身を関数に分ければ、より見通しのよいプログラムになるだろう。

  • http://www.clomidlmt.com/ clomid online no prescription - order cheap clomid online - clomid (2013年02月21日 10時40分34秒)
  • http://www.cialislmtd.com/ buy cialis pills - cialis - cialis (2013年02月24日 19時03分56秒)
  • http://www.propeciaitem.com/ propecia - propecia cheap - propecia (2013年02月26日 15時13分09秒)
  • http://www.levitradelightful.com/cheap-levitra.html cheap levitra - cheap levitra pharmacy - cheap levitra (2013年03月04日 14時46分13秒)
  • my $sum = 0; $sum += $_ for (1 .. 1000); print "$sum\n" - Perl (2018年01月27日 02時41分00秒)
  • C言語6行の例のfor文の{が閉じていないように見えます。 - 通りすがり (2020年07月11日 09時53分04秒)
お名前: コメント: