《06》制御構造(2)if 文〈Python 2.x 版〉

実録:はじめてのプログラミング記事一覧
《06》制御構造(2)if 文

《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
2009年1月21日(水)

今日の進捗

  • Python.use(better) -- セミナー研修テキスト
  • スケール課題を「続・ひよ子のきもち」で公開(続き)
Comment
本人:野中 OmniGraffleだと資料を使い回したいときに便利というのを実感する1日でした。
担当:本間 今日のテクは、私が伊藤さんから教わったもののひとつです。ほかにも教わったことはたくさんあるけど、焦らずに少しずつしっかりと身につけていこうね。(^^)

スケール課題(2)if 文

引き続き、関数 scale が完成するまでの過程を紹介します。

《step 2》引数に指定した値と同じ数の文字 "." を出力するとともに、5つおきに "+" を出力します。

まず、step 2 の動作を確認します。

def step2():
    for e in range(11):
        print "%2d"%e, scale(e)

>>> step2()
 0 
 1 .
 2 ..
 3 ...
 4 ....
 5 ....+
 6 ....+.
 7 ....+..
 8 ....+...
 9 ....+....
10 ....+....+

すると、引数に指定した値と同じ数の "." を出力するとともに、5つおきに "+" を出力するのが分かります。
さらに、ここに至るまでの過程を段階的に示します。まず、

def scale(n):             # step 2A
    s = ""
    for e in range(n):
        if e%5==0:
            s += "+"
        s += "."
    return s

if に続く条件式 e%5==0 を満たすときだけ、"." の代わりに "+" を連結します。この条件式を満たすのは、変数 e の値が5の倍数になるときだけです。すると、5つおきに "+" を出力するはずです。ところが、

>>> print 6,scale(6)
6 +.....+.

この結果には、いくつかの問題があります。

何が問題か

ここで、if 文の流れを図解すると、次のようになります。



ある条件を満たすときには、if ブロック内にあるコードを一度だけ実行します。そのため、条件式 e%5==0 を満たすとき、つまり変数 e の値が5の倍数になるときだけ、"." の代わりに "+" を連結します。
ところが、if ブロックを抜けた後で、それに続くコードを実行するため、さらに "." を連結します。ステップ2の実行結果として、末尾に "." が出力されたのは、そのためです。また、先頭に "+" が出力されるのも考えものです。そこで、これらの問題に対処すると、



def scale(n, offset=1):            # step 2B
    s = ""
    for e in range(offset, n+1):
        if e%5==0:
            s += "+"
        else:
            s += "."
    return s

第2引数 offset には、規定値として =1 を設定しています。そのため、この引数を省略して scale(n) を呼び出すと、scale(n,1) を呼び出したものと見なされます。ステップ2の実行結果として、scale(0) のとき何も出力されないのは、そのためです。
ある条件を満たさないときには、else ブロック内にあるコードを一度だけ実行します。そのため、条件式 e%5==0 を満たさないとき、つまり変数 e の値が5の倍数でないときには、"." を連結します。その結果として、"." または "+" のどちらか一方だけが連結されて、step2 で示した結果が得られます。

何が問題か

次に進む前に、ここで少しコードに手を加えて、その動作を確認します。

def scale(n, offset=1):            # step 2C
    s = ""
    for e in range(offset, n+1):
        c = "."
        if e%5==0:
            c = "+"
        s += c
    return s

一時変数 c を用意して、これで出力したい文字列を管理します。すると、変数 c の値が何か(実現方法)とは無関係に、文字列を連結する部分のコードを記述できる(抽象化)ようになります。

Tips

この些細なコードの違いが、後にリファクタリングを実施するときに、その効果を発揮します。すると、要求仕様の変更があっても、柔軟に対処できるようになります。プログラムの「実行効率」の違いには「あまり」影響しませんが、プログラミングの「作業効率」の違いには「かなり」影響します。これらの指針は、what/how を分割統治するとともに「情報隠蔽の原則」にも適っています。その実現方法に依存しない、抽象的な表現が可能になるので、簡潔で見通しの良いコードを促進します。《ひよ子》

Last updated♪09/03/02