《07》制御構造(3)if/elif/else 文〈Python 2.x 版〉

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

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

今日の進捗

  • Python.use(better) -- セミナー研修テキスト
  • スケール課題を「続・ひよ子のきもち」で公開(続き)
Comment
本人:野中 頭を整理するつもりで資料にまとめ始めたら今度は資料が分散してしまい混乱し始めてきました。
担当:本間 ブログラムと同様に資料もリファクタリングできたらいいのにと、私も何度か思い悩みました。でも、なかなかこれだけは、そうもうまくいかないのよね。(^^)

スケール課題(3)if/elif/else 文

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

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

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

def step3():
    for e in range(21):
        print "%2d"%e, scale(e)

>>> step3()
 0 
 1 .
 2 ..
 3 ...
 4 ....
 5 ....+
 6 ....+.
 7 ....+..
 8 ....+...
 9 ....+....
10 ....+....1
11 ....+....1.
12 ....+....1..
13 ....+....1...
14 ....+....1....
15 ....+....1....+
16 ....+....1....+.
17 ....+....1....+..
18 ....+....1....+...
19 ....+....1....+....
20 ....+....1....+....2

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

def scale(n, offset=1):            # step 3A
    s = ""
    for e in range(offset, n+1):
        c = "."
        if e%10==0:
            c = `e/10`
        if e%5==0:
            c = "+"
        s += c
    return s

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

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

この結果には、少し問題があります。

何が問題か

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



すると、変数 e の値が10の倍数になるときに加えて、その値が5の倍数になるときも、変数 c の値が更新されます。前に示した実行結果において、5つおきに "+" だけが出力されたのは、そのためです。そこで登場するのが、elif です。


def scale(n, offset=1):
    s = ""
    for e in range(offset, n+1):
        c = "."
        if not e%10:
            c = `e/10`
        elif not e%5:
            c = "+"
        s += c
    return s

if に代えて elif を利用するとif に続く条件式を満足しないときには、elif に続く条件式を評価します。すると(if が連続するのと違って)特定の条件を満たすときだけ、必要な処理を施すことが保証されます。また、多重 if 文にように、不必要に入れ子が深くなるのを防ぐという効果が期待できます。
さらにここでは、演算子 == に代えて、演算子 not を導入します。すると、式の値が何か(実現方法)とは無関係に、連結したい文字列を選択する部分のコードを記述(抽象化)できます。後でリファクタリングを実践するときに、その効能を実感できるようになるので、楽しみにしていてください。
このようにして、step 3 の動作を確認できるようになり、ひとまず「スケール課題」は完成したものと見なして、次の「ヒストグラム課題」へと進みます。

Tips

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

Tips

条件判定の順序依存性は、SP の特徴でもあり、また弱点ともされています。OOP では、この問題をどのように回避するのか、それを将来の学習目標に据えつつも、ここでは話を先に進めます。《ひよ子》

Last updated♪09/03/04