根無し草日記

好きな事についての雑記帳

Pythonの基本を学ぶ

Pythonの基本を学んでみる。

お題

プログラミングを学習するときの有名な題材にFizzBuzz問題というのがある。英語圏の飲み会とかで行われる山手線ゲームみたいなものらしく、数字をカウントして行き、3の倍数ならFizz、5の倍数ならBuzz、15の倍数ならFizzBuzzというのがルールらしい。とは言え、日本人には馴染みが無いゲームなので近くてイメージが付きやすいものを題材にする。そう、世界のナベアツである。

学ぶ事

世界のナベアツの実装を通して下記の事を学ぶ。

  • print文の使い方
  • for文の使い方
  • if文の使い方
  • 関数について
  • クラスについて

いよいよ実装

何はともあれHello World!

先ずはHello Worldから始める。print文を使えばそのまま表示する事が出来る。

print("Hello World!")

実行結果

Hello World!

0から99までカウントする

世界のナベアツを作る一歩目として、先ずは普通にカウントしてみる。for文を使い、rangeで100を指定すると100回繰り返す事が出来る。

for count in range(100):
    print(count)

実行結果

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

3の倍数の時だけアホになる

繰り返す時に、if文を使って3の倍数の時だけアホになるようにする。3の倍数かどうかを判定するには%を使う。これは割り算の余りを出してくれるのでそれが0であれば3の倍数と言うことである。また、アホになる時のprint文でも%dを使い、printの中に数字を入れ込む。

for count in range(100):
    if count %3 == 0 : ## 3で割った時余りが0であれば
        print("( ´∀`) %d !" % count) ## %d の中にcountを入れる。
    else: ## それ以外の時は普通にカウント
        print(count)

実行結果

( ´∀`) 0 !
1
2
( ´∀`) 3 !
4
5
( ´∀`) 6 !
7
8
( ´∀`) 9 !
10
11
( ´∀`) 12 !
13
14
( ´∀`) 15 !
16
17
( ´∀`) 18 !
19
20
( ´∀`) 21 !
22
23
( ´∀`) 24 !
25
26
( ´∀`) 27 !
28
29
( ´∀`) 30 !
31
32
( ´∀`) 33 !
34
35
( ´∀`) 36 !
37
38
( ´∀`) 39 !
40

=== 以下省略 ===

数字に3がつく時もアホになる

本家ナベアツは数字に3がつくときもアホになっている。その判定を追加する。条件を追加するためにはelif文を使う。今度はプログラム中のcountの変数を数字としてではなく、文字として判定しないといけない。また、先ほどのように"=="で判定すると、"3"しか条件に引っかからないので、inを使った少し緩い条件文にする。

for count in range(100):
    if count %3 == 0 : ## 3で割った時余りが0であれば
        print("( ´∀`) %d !" % count) ## %d の中にcountを入れる。
    elif "3" in str(count) : #countを文字として扱い、その中に3が含まれているかどうか判定する。
         print("( ´∀`) %d !" % count) ## %d の中にcountを入れる。
    else: ## それ以外の時は普通にカウント
        print(count)

実行結果

( ´∀`) 0 !
1
2
( ´∀`) 3 !
4
5
( ´∀`) 6 !
7
8
( ´∀`) 9 !
10
11
( ´∀`) 12 !
( ´∀`) 13 !
14
( ´∀`) 15 !
16
17
( ´∀`) 18 !
19
20
( ´∀`) 21 !
22
( ´∀`) 23 !
( ´∀`) 24 !
25
26
( ´∀`) 27 !
28
29
( ´∀`) 30 !
( ´∀`) 31 !
( ´∀`) 32 !
( ´∀`) 33 !
( ´∀`) 34 !
( ´∀`) 35 !
( ´∀`) 36 !
( ´∀`) 37 !
( ´∀`) 38 !
( ´∀`) 39 !
40

=== 以下省略 ===

3の倍数でさらに数字に3がつく場合は大アホになる

さらに本家ナベアツに近づけるため3の倍数で、さらに数字に3が付く場合は大アホになって貰う。if文の条件式を工夫して行けば実現出来る。

for count in range(100):
    if count %3 == 0 and "3" in str(count) : ## 3で割った余りが0で数字に3が含まれていれば
        print("・:*+.\(( °ω° ))/.:+  %d !!!"%count)
    elif count %3 == 0 : ## 3で割った時余りが0であれば
        print("( ´∀`) %d !" % count) ## %d の中にcountを入れる。
    elif "3" in str(count) : #countを文字として扱い、その中に3が含まれているかどうか判定する。
         print("( ´∀`) %d !" % count) ## %d の中にcountを入れる。
    else: ## それ以外の時は普通にカウント
        print(count)

実行結果

( ´∀`) 0 !
1
2
・:*+.\(( °ω° ))/.:+  3 !!!
4
5
( ´∀`) 6 !
7
8
( ´∀`) 9 !
10
11
( ´∀`) 12 !
( ´∀`) 13 !
14
( ´∀`) 15 !
16
17
( ´∀`) 18 !
19
20
( ´∀`) 21 !
22
( ´∀`) 23 !
( ´∀`) 24 !
25
26
( ´∀`) 27 !
28
29
・:*+.\(( °ω° ))/.:+  30 !!!
( ´∀`) 31 !
( ´∀`) 32 !
・:*+.\(( °ω° ))/.:+  33 !!!
( ´∀`) 34 !
( ´∀`) 35 !
・:*+.\(( °ω° ))/.:+  36 !!!
( ´∀`) 37 !
( ´∀`) 38 !
・:*+.\(( °ω° ))/.:+  39 !!!
40

=== 以下省略 ===

3以外の条件でもナベアツを作る

世界のナベアツは、元々はジャリズムと言う漫才コンビのボケ担当であった。さらに現在は落語家に転身され、"桂三度"と名乗っておられる。三度の由来は持ちギャグだけではなく、深い意味があるとのこと。。。これについてはもう少し話したい所ではあるが本題に戻す。世界のナベアツ桂三度であるならば、異世界には桂四度がいるかも知れないし、桂九度が居るかも知れない。そこで、桂N度を作って行こうと思う。

例えば、桂四度を作ろうと思うとどうするか?勿論プログラム中の3を4に変えれば簡単に作ることが出来る。しかしその方法だと、この程度の規模のプログラムならともかく、今後複雑なプログラムで対応しようと思うと非常に大変になる。そこで、今回のプログラムを関数にすることを考える。関数とは、似た様な処理をまとめる仕組みの事である。

関数を作るためにはdefを使う。

def 関数名(引数):

で作る事が出来る。 あとは、3にしていた所をNにして行けば良い。 但し、"3"を単純に"N"にしてしまうと、数字に"N"という文字が含まれているかの判定になってしまい、意図した動作にならない。str(N) として、変数Nで指定した数字を文字として扱うようにしないといけない。 作成した関数を使うのは簡単で関数名と引数を指定すれば実行出来る。これで桂四度でも、桂九度でも作る事が出来るようになった。

def COUNT(N): ## 桂N度を関数にする。
    for count in range(100):
        if count % N == 0 and str(N) in str(count) : 
            print("・:*+.\(( °ω° ))/.:+  %d !!!"%count)
        elif count % N == 0 : 
            print("( ´∀`) %d !" % count) 
        elif str(N) in str(count) : 
            print("( ´∀`) %d !" % count) 
        else: 
            print(count)

COUNT(N=4) ## 桂四度として実行

実行結果

( ´∀`) 0 !
1
2
3
・:*+.\(( °ω° ))/.:+  4 !!!
5
6
7
( ´∀`) 8 !
9
10
11
( ´∀`) 12 !
13
( ´∀`) 14 !
15
( ´∀`) 16 !

=== 以下省略 ===

複数の関数をまとめたクラスを作る

世界のナベアツは現在は落語家であるし、最近は3の時だけアホになるギャグをテレビで見かける事はほぼ無い。ここでは桂N度に落語家らしい色々な動作をさせてみようと思う。つまり、色々な関数を作るというである。さて、関数を作るだけなら何通りも作れば良いだけなのだが、後々利用する事を考え、関数をまとめて管理することを考えたい。この複数の関数をまとめて上手く管理する仕組みこそクラスと呼ばれ、オブジェクト指向プログラミングの大切な入り口となる考え方である。

以下にコードを示す。記述内容は、冒頭にclassを宣言し、関数が増えたようなイメージであるが、いくつか見慣れないものがあると思う。まず、変数としてNを使っていたが、大部分がself.Nに変わっている。他にもちらほらselfという言葉が含まれている。これはclassを使う時に必要になるものである。じゃあ、classって何だ?という事になるが、一番イメージしやすいのは"学校のクラス"では無いだろうか?色んな生徒や場合によっては先生や教室が集まってクラスの要素を形成しているが、学校ではクラスを区別するために、3組の担任の先生、とか3組の佐藤さんとか、言う必要があったのでは無いだろうか?selfとは、自分のクラスのという意味である。ちなみに、クラスを複数まとめてさらに大きなクラスを作ったり、まとめる規模が大きくなるとパッケージの様な階層構造になって行くが考え方は同じである。東京都の桜中学の3年のB組の担任というように階層が増えて行くイメージである。 また、先程までdefで定義するのは関数と呼んでいたが、classの中の関数はメソッドと呼ぶ。ただ、これは呼び方だけの問題だと思って差し支えは無いだろう。

class NABEATSU():
    def __init__(self,N):
        self.N = N

    def COUNT(self): ## 桂N度を関数にする。
        for count in range(100):
            if count % self.N == 0 and str(self.N) in str(count) : 
                print("・:*+.\(( °ω° ))/.:+  %d !!!"%count)
            elif count % self.N == 0 : 
                print("( ´∀`) %d !" % count) 
            elif str(self.N) in str(count) : 
                print("( ´∀`) %d !" % count) 
            else: 
                print(count)

    def YOSE(self): ## 挨拶するプログラムを作る。
        print("どうも〜、桂%d度です〜"%self.N) 

Nabeatsu = NABEATSU(N = 3) ## 桂三度を呼び出す。
Nabeatsu.YOSE()
Nabeatsu.COUNT()

実行結果

どうも〜、桂3度です〜
( ´∀`) 0 !
1
2
・:*+.\(( °ω° ))/.:+  3 !!!
4
5
( ´∀`) 6 !
7
8
( ´∀`) 9 !
10
11
( ´∀`) 12 !
( ´∀`) 13 !
14
( ´∀`) 15 !

=== 以下省略 ===

オブジェクト指向プログラミングとは

世の中には様々なプログラミング言語が存在するが、Pythonは分類で言うとオブジェクト指向プログラムに属する。オブジェクト指向プログラミングにおいて、重要なクラスと言う概念が出て来たので簡単にオブジェクト指向プログラミングについて触れておく。先程、世の中には様々なプログラミング言語があると書いたが、何故それ程多くのプログラミング言語があるのだろうか?それは、バグの少ないコードを書くためにプログラミング言語自体を工夫して行った結果である。では規模の大きなプログラムを書く場合、つまりプログラムで解決しようとする課題が難しい場合、どの様に解決して行くだろうか?通常は、難しい課題に直面した時は、簡単な課題に分解して行くのが普通ではないでしょうか?それをオブジェクト指向プログラミングでは担当者に分担するようなイメージで分解して行く。つまり、classが担当者のイメージである。担当者が出来る事がメソッドである。オブジェクト指向において、プログラミングをするという事は新人を育てて、一人前の担当者に育て上げる事に似ている。まずはclassを定義し、どの様な業務を担当して欲しいか考える。その業務に必要な作業をメソッドとして教え込む。必要なメソッドを教え込む事が出来れば、それで立派な担当者となってくれる。実際のプログラムで、例えばエクセルのデータを処理するプログラムを作る場合、

* エクセルを読み込むクラス
* データを処理するクラス
* データをエクセルに書き出すクラス

のように作業を幾つかのクラスに分担して、必要なメソッドを実装して行くと、効率良く間違えにくいプログラミングをすることが出来る。

まとめ

世界のナベアツを実装することから始まり、オブジェクト指向的なプログラムの書き方まで一気に進めた。但し、内容はかなり端折っていて、細かいことにはかなり目を瞑って進めた。実際にプログラムを進めるためには他にも様々なことを知る必要はあるものの、ある程度プログラミングの全体像を学ぶことは出来たと思う。