【Python】SimplePrograms line 4 フィボナッチ数列を出力する
4行プログラムです。
コード
parents, babies = (1, 1)
while babies < 100:
print ('This generation has {0} babies'.format(babies))
parents, babies = (babies, parents + babies)
実行結果
This generation has 1 babies
This generation has 2 babies
This generation has 3 babies
This generation has 5 babies
This generation has 8 babies
This generation has 13 babies
This generation has 21 babies
This generation has 34 babies
This generation has 55 babies
This generation has 89 babies
解説
フィボナッチ数列です。
フィボナッチ数列というのは、1,2,から始まって、前の2つを足した数値が次の数になります。
1+2 1,2,3,
2+3 1,2,3,5,
3+5 1,2,3,5,8,
5+8 1,2,3,5,8,13,
という風に、どんどん続いていきます。
今回は、この数列を生成するプログラムです。
ではまず、1行目。
parents, babies = (1, 1)
こんな風にまとめて設定できるんですねぇ。
C++ だと
int parents, babies = 1;
こんな風に書くことができました。
だけど、この書き方はあまり評判がよくなくて、実は「parents」は初期化できていない。でも、見た目は初期化しているように見えます。そこに間違いが潜みやすい。
その点、Python では次のような書き方ではエラー「TypeError: cannot unpack non-iterable int object」になるようです。
parents, babies = 1
きっちりと、変数の数分の初期値を書かないといけません。
C++ の問題点が改良されているような感じでしょうか。
次の行です。
while babies < 100:
次は「while」文。
「babies」が 100 より小さい間はずっと繰り返す。
そういうプログラムです。
「while」文の中で「babies」が更新されなければなりません。
でないとこの繰り返しから抜け出ることはできません。
いわゆる、無限ループになります。
次は「print」文。
また様変わりしていますね。
print ('This generation has {0} babies'.format(babies))
文字列「' '」内の「{ }」は「置換フィールド」でした。
前回は「{name}」などのようにシンボルが書かれていましたが、
今度は「{0}」と数値です。
この「0」は何を意味するのでしょうか。
「format」に並べる引数の順番のようです。
例えば、こんな風に書くと・・・
a, b, c, d, e = (10, 11, 12, 13, 14)
print('{2}, {1}, {4}, {0}, {3}, {2}'.format(a, b, c, d, e))
実行結果は次のようになります。
12, 11, 14, 10, 13, 12
「{0}」は0番目の引数、
「{1}」は1番目の引数、
「{2}」は2番目の引数、・・・
ということのようです。
今回の場合、引数は「babies」だけですから、「{0}」は「babies」に置き換えられることになります。
そして最後の行なんですが。
parents, babies = (babies, parents + babies)
これ・・・難しいですね。
これは、
「2行のコードを1行にまとめて書くことができます」
ということだけではありません。
次の2つのどちらの書き方とも違うものです。
parents = babies
babies = parents + babies
babies = parents + babies
parents = babies
例えば、
parents = 3
babies = 5
だとしましょう。
parents = babies # 5
babies = parents + babies # 10
最初に「parents」を「5」置き換えてしまった場合、
その次の「babies」の計算では新しい「parents=5」と計算してしまします。
本当は、計算するまえの「parents」である「3」と加算しないといけないのですが、そうはなりません。
babies = parents + babies # 8
parents = babies # 8
逆に「babies」を先に計算してしまってもやはりダメです。
今度は「babies」は正しい値になりますが、
次の「parents」が新しい「babies」と同じになってしまいます。
こちらも本当は、計算するまえの「babies」である「5」でなければなりません。
parents, babies = (babies, parents + babies) # parents = 5 babies = 8
でもこの場合は違います。
「parents」も「babies」も、今の「parents = 3」「babies = 5」をもとに決定します。
「parents」を計算してから「babies」を計算するのでも、
「babies」を計算してから「parents」を計算するのでもないのです。
ということは、こんな書き方ができるわけです。
a,b = (b,a)
「a」と「b」をひっくり返すプログラムです。
a,b = (1,2)
が、たった一行で
a,b = (2,1)
に置き換わります。
これまでのプログラミング言語では、3行でないと書けないというのが多かったのではないでしょうか。
a_old = a
a = b
b = a_old
あるいは、こう書いた方がわかりやすいかもしれません。
でもそうすると、4行が必要になります。
a_old = a
b_old = b
a = b_old
b = a_old
それを
a,b = (b,a)
というたった一行で表現するとは、考えたものです。
間違いや改善方法、追加情報などありましたら、是非是非コメントくださいませ。