Python.use(better)《余録》comprehension: list

記事一覧 Python.use(better)《余録》

comprehension: list

《著》小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
第0版♪2001/03/02 ● 第1版♪2003/05/25 ● 第2版♪2004/06/01 ● 第3版♪2009/02/28

さまざまな事例

簡単な事例を使って、comprehension の理解を深めます。

《Note》Smalltalk-80 セミナーのために用意した課題です。ここでは「コレクションを扱う基本的なプロトコル(collect:/select:/reject:/detect:/inject:into:)を利用する」という制約を課してあるので、問題解決の「最適解」を示すものではありません。

課題:九九の表

掛算の九九の表を作成する課題 *1 によって、comprehension に関する理解を深めます。

■ filter 版

組み込み関数 filter を利用した事例の後に、comprehension 版と比較します。

def multiplicationTable():     # step 0
    for n in range(2, 10):
        for e in filter(lambda e: not e%n, range(n, n*10)):
            print("%2d"%e, end=" ")
        print()
>>> multiplicationTable()
 2  4  6  8 10 12 14 16 18
 3  6  9 12 15 18 21 24 27
 4  8 12 16 20 24 28 32 36
 5 10 15 20 25 30 35 40 45
 6 12 18 24 30 36 42 48 54
 7 14 21 28 35 42 49 56 63
 8 16 24 32 40 48 56 64 72
 9 18 27 36 45 54 63 72 81
■ comprehension 版

comprehension を利用して、filter 版と同等の機能を実現します。

def multiplicationTable():     # step 1
    for n in range(2, 10):
        for e in [e for e in range(n, n*10) if not e%n]:
            print("%2d"%e, end=" ")
        print()

まず、filter と同等の機能を、comprehension で実現します。

def multiplicationTable():     # step 2
    for n in range(2, 10):
        s = ["%2d"%e for e in
            [e for e in range(n, n*10) if not e%n]]
        print(" ".join(s))

次に、各項目を形成するための手段を、comprehension で実現します。

def multiplicationTable():     # step 3
    s = [" ".join(
            ["%2d"%e for e in
            [e for e in range(n, n*10) if not e%n]])
        for n in range(2, 10)]
    print("\n".join(s))

そして、各行を形成するための手段を、comprehension で実現します。

def multiplicationTable():     # step 4
    return "\n".join(
        [" ".join(
            ["%2d"%e for e in
            [e for e in range(n, n*10) if not e%n]])
        for n in range(2, 10)])

最後に、関数の本体から、関数 print を排除します。

>>> print(multiplicationTable())
 2  4  6  8 10 12 14 16 18
 3  6  9 12 15 18 21 24 27
 4  8 12 16 20 24 28 32 36
 5 10 15 20 25 30 35 40 45
 6 12 18 24 30 36 42 48 54
 7 14 21 28 35 42 49 56 63
 8 16 24 32 40 48 56 64 72
 9 18 27 36 45 54 63 72 81

結果を出力するには、関数 print の引数に、関数呼び出し multiplicationTable() を指定します。

■ 局所関数版

局所関数を定義して、機能分割を行います。

def multiplicationTable3():      # step 5
    def term(n): return [e for e in range(n, n*10) if not e%n]
    def line(n): return ["%2d"%e for e in term(n)]
    def table(): return [" ".join(line(n)) for n in range(2, 10)]
    return "\n".join(table())
  • 局所関数 term では、各項目を形成するための手段を提供します。
  • 局所関数 line では、各項目を生成するとともに、各行(段)を形成するための手段を提供します。
  • 局所関数 table では、各行を生成するとともに、表を形成するための手段を提供します。

《付録》九九の表を作るだけなら

この課題では、filter/comprehension の理解を深めるために、制約を設けました。九九の表を作るだけの目的なら、次のようにするとよいでしょう。

def multiplicationTable():         # for/in
    for n in range(2, 10):
        for e in range(n, n*10, n):
            print("%2d"%e, end=" ")
        print()
def multiplicationTable():         # comprehension
    return "\n".join(
        [" ".join(["%2d"%e
            for e in range(n, n*10, n)])
        for n in range(2, 10)])
def multiplicationTable():         # 局所関数
    def line(n): return ["%2d"%e for e in range(n, n*10, n)]
    def table(): return [" ".join(line(n)) for n in range(2, 10)]
    return "\n".join(table())

》こちらに移動中です《
TOP


関連記事

Last updated♪2009/11/10

*1:Smalltalk 3分クッキング《問6》九九の表, 1988.