Python♪基本:簡単なfor文とrandom関数を使ってグラフを表示しよう

if文もfor文も配列も関数も知らない状況で、なにからPythonを説明するのがいいのでしょう。スマホを使いこなす世代の子供たちにhello Wolrdの出力が面白いのは最初の1度きりです。プログラミングの家庭教師って、思ったよりも難しいのかも。まあ、乱数使ってグラフでも作ってみよっと。

0.ゆうちゃんとPythonシリーズ

この記事は「ゆうちゃんとPythonシリーズ」の記事です。一連の記事は、以下のリンク集を参照してください。

中学生のゆうちゃんとPythonシリーズ

なお、それぞれの記事は、シリーズの中でそれまでに習った文法を使ってサンプルコードを考えています。実際には、もっと、効率のよい書き方があるかもしれませんが、ご了承ください。

1.今回、勉強すること

ゆうちゃん(中1)に何から教えようかと悩みましたが、ランダム関数を使ってグラフを表示することにしました。今回は乱数を発生させるrandom、繰り返し計算を行うfor文、グラフを描画するmatplotlibを使用します。でも、それぞれ、最低限の機能しか説明しません。ここでは、これらを使用することで、「モジュール」「パッケージ」「ライブラリ」の概要を理解します。import文の説明は、普通、後回しにする部分だと思いますが、私は訳の分からないimport文を書くのが苦痛だったので、概要は知っておいた方がよいと思うのです。

また、乱数を最初に勉強することにしました。乱数が使えるとプログラミングの幅が大きくひろがります。ゲームのガチャでモンスターを決めるのも乱数ですし、人工知能にも乱数は必要です。乱数が使えないプログラミングなんて面白くありません。

2.整数を返すrandint関数の使い方

では、さっそくコード01を見てみましょう。このコードは、1以上、10以下の整数の乱数を発生させ、出力するコードです。

2行目の「import random」のrandom(読み:ランダム)は、乱数関連の便利なツールがたくさん入ったツール集の名前です。Pythonではrandomのようなツール集を「モジュール」といいます。

このモジュールには、関数やクラスと呼ばれるツールが入っています。ただ、「関数」って何?「クラス」って何?という話は、後回しにします。とにかく、「モジュール」には便利なツールである「関数」や「クラス」がたくさん入っているということを覚えましょう。

import random では、random(読み:ランダム)という名前のモジュールをimport(読み:インポート)によって読み込んでいます。

pythonで用意される関数やクラスは、最初から使えるものと、importで読み込まなければ使えないものがあります。randomモジュールは使う前にimportで読み込む必要があります。

#コード01
import random

x = random.randint(1, 10)
print(x)
#出力01
3

4行目の関数randint(1, 10)は、1以上、10以下の整数をランダムに発生する関数です。1や10も発生します。randamモジュールの中に入っているrandint()という関数を使うので、半角のドット「.」を使い、random.randint(1, 10)と記述します。

つまり、4行目は1以上10以下の整数をランダムに発生させ、xに代入します。

最後に、5行目では、1以上10以下ランダムな数字が入ったxを出力しています。

出力01は出力例として3が出力されていますが、実行のたびに違う値になります。

いかがでしょうか。以上がrandomモジュールの呼び出し方と、randint(読み:ランドイント)の使い方の流れです。

3.ちょっとだけfor文とインデント

for文は、繰り返し処理を行う非常に重要な命令文です。これが使えなきゃプログラミングする意味がないというぐらい大切です。特にfor文と配列(Pythonではlist等)を組み合わせると強力な武器になります。配列を勉強するのはもう少し先なので、ここでは、ちょこっとだけfor文を使います。

for文を使うためには「インデント」を理解する必要があります。「インデント」とは文のはじめの空白のことです。Pythonでは、for文で繰り返し処理をする範囲を「インデント」で示します。これは他のプログラミング言語にはないPython独特の文法です。なお、全角の空白は使うことができません。必ずtabか半角スペースを使いましょう。半角スペースの数は何個でもかまいませんが、4の倍数にすることが推奨されています。また、tabでもエラーにはなりませんが、推奨されていません。

では、インデントの働きを確認します。まずは、コード02を見てください。どの行も1文字目から始まり、行の最初に空白は挿入されていません。インデントされていない、ごく、普通のコードですね。

#コード02
print('a')
print('b')
print('c')
#出力02
a
b
c

次に、コード03を実行してみてください。エラーが発生して止まりました。エラーの「unexpected indent」をグーグル翻訳で翻訳すると「予期しないインデント」です。Pythonでは、意味もなく、勝手にインデントすることはできません。

#コード03(エラーになります)
print('a')
    print('b')
    print('c')
#出力03
IndentationError: unexpected indent

いよいよ、for文を使ったコードです。for文の機能は繰り返し計算を行う事です。コード04の3~5行目はインデントされていますが、このインデントには意味があります。2行目のfor文の直後でインデントしているので、この範囲を3回繰り返します。for i in range(3):の3の部分を変えれば、例えば1万回でもa,b,cを出力し続けます。

最後に「:」コロンがあることを忘れないようにしましょう。最後のコロン「:」は、この後に、影響を受ける範囲が続くこと示します。

さて、ゆうちゃんは予想どおり、for i in range(9999999):を実行して大喜び。「やるなっていったじゃない(本当は予想してたけどね~)」「どうやってとめるの~(笑笑、やってほしかったんでしょ~)」みたいな感じで、ボケとつっこみをやっております。しばらくほっといたら、ノートパソコンのファンがうなり出したので、IPythonコンソールの画面を1クリックして「ctrl+C」で止めました。お子ちゃまとのfor文の勉強では、「ctrl+C」は必須ですね。

#コード04
for i in range(3):
    print('a')
    print('b')
    print('c')
#出力04
a
b
c
a
b
c
a
b
c

コード05は5行目のインデント幅を変えました。すると、今度はエラーになってしまいます。

コード05のfor文の影響範囲は、for文の直後のインデントが「そろっている」範囲なので、5行目はfor文の影響範囲外になってしまいます。つまり、for文では3~4行目を繰り返すと終了し、次に5行目のprint(‘c’)が実行されます。しかし、5行目はどこともインデント幅がそろっていません。そこで、Pythonでは、意味の無いインデントがあるとして、5行目でエラーになるのです。

#コード05(インデントがそろっていないのでエラーになる)
for i in range(3):
    print('a')
    print('b')
        print('c')

一方、コード06はエラーになりません。for文により、3~4行目の繰り返し処理が終了すると実行が5行目に移りますが、5行目ではインデント幅がゼロにもどっているので、今度はprint(‘c’)が実行可能です。
結果は出力06のようにa, bは3回出力され、cは1度だけ出力されます。

コード06では2~4行目を1つのかたまりとして考えれば、基本的なインデント幅はゼロであり、for文の影響範囲だけをインデントしているのです。

#コード06
for i in range(3):
    print('a')
    print('b')
print('c')
#出力06
a
b
a
b
a
b
c

それでは、for文を使って、乱数を繰り返し出力します。今度は乱数を連続で5回出力することができるようになりました。4行目のrange(5)の5を別な数字にすれば、乱数を出力する回数を変更できます。

#コード07
import random

for i in range(5):
    x = random.randint(1, 10)
    print(x)
#出力07
1
4
4
10
7

4.モジュールとは

モジュールについては、もう少しだけ勉強してみましょう。ここまで勉強してきた人は、自分の書いたコードを〇〇.pyというファイルに保存していると思いますが、実はこの拡張子が.pyのファイルがモジュールです。

pythonを勉強して自分の作ったコードが増えてくると、自分のお気に入りのコードが増えてきます。しかし、毎回コピペするのは大変です。そこで、自分のお気に入りのコードを○○.pyというファイルに集めておけば、randomモジュールと同じように、別のプログラムから呼び出すことができます。このコードが長いコードだったとしても、コピペせずに使えるので、大変便利です。

また、誰かが便利なモジュールをネットで公開すると、みんなでそのモジュールを使うことができるため、Pythonという言語が、どんどん、便利なプログラミング言語に進化します。

ただし、randomモジュールのように、pythonが標準で用意しているモジュールはimportで読み込むだけで使えますが、自分が作ったモジュールは、別の設定が必要な場合もありますので、実際に使うときには、もう少し勉強しましょう。

5.randomモジュールの関数

ここでは、乱数を使うときに便利なrandamモジュールの関数を説明します。

(1) randamモジュールで用意される関数

randint関数は使いましたので、ここでは、random関数、uniform関数を実際に使います。randomモジュールには、以下の関数の他にも便利な関数が多く用意されています。

randint(a, b)  :a以上b以下の整数の乱数を返す。
random()   :0以上1未満の少数の乱数を返す。(1以下ではなく、1未満です。)
uniform(a, b) :a以上b以下の少数の乱数を返す。

(2) random関数

random関数は0以上、1未満の少数の乱数を発生させることができます。1未満なので1は発生しません。また、モジュール名も関数名もrandomなので、混乱しないようにしましょう。

#コード08
import random

for i in range(5):
    x = random.random()
    print(x)
#出力08
0.6932170207027626
0.3450431261096477
0.6041914462545648
0.7300689252945314
0.2901777571692773

(3) uniform関数

uniform(a, b)は、a以上、b以下の少数の乱数を発生します。

#コード09
import random

for i in range(5):
    x = random.uniform(2.0, 5.0)
    print(x)
#出力09
4.317220849807272
4.174714091290028
2.2616063372970197
3.8671481587672925
3.112899363869424

5.ちょっとだけmatplotlib

それでは、グラフを出力するmatplotlib(読み:マットプロットリブ)を使ってみます。

(1) 反比例のグラフ

コード10の3行目ではmatplotlibというパッケージを読み込んでいます。「えっ!モジュールじゃないの?」と思うかもしれませんが、そうなんです。モジュールではなくてパッケージです。実はモジュールが複数集まって、パッケージになります。

では、コードの概要を説明します。
5行目のfor文で6~8行目を10回繰り返します。
6行目で、xに0.1以上1.0以下の少数の乱数を代入します。
7行目では、yに1 / xを代入します。つまり、xとyは反比例の関係です。
8行目で、matplotlibパッケージの中のpyplot(読み:パイプロット)モジュールの中のplot(読み:プロット)関数を使用し、(x, y)の点をグラフに表示する準備をします。準備をするだけなので、まだ画面に表示はされません。for文で繰り返すたびに、ランダムに計算された結果(x, y)をグラフに追加する準備をします。つまり、for文が終了するときには、ランダムに計算された10個の点をグラフに表示する準備が整います。
9行目で、いよいよ、グラフを表示するshow関数を実行します。

なお、7行目の「marker='.'」の部分はマーカーの形を設定します。「.」→ 点、「s」→ 四角、「o」(小文字のオー)→ 丸となります。

#コード10
import random
import matplotlib

for i in range(10):
    x = random.uniform(0.1, 1.0)
    y = 1 / x
    matplotlib.pyplot.plot(x, y, marker='.')
matplotlib.pyplot.show()

じゃじゃ~ん。以下が出力結果です。なんとなく、反比例のグラフになっていませんか?

コード10の5行目のrange(10)をrange(100)にして、for文による繰り返し回数を100回にしてみました。隙間だらけのグラフの形がはっきりしてきました。

for文の繰り返し回数を1000回にしてみました。ランダムに計算する点を増やせば増やすほど、グラフの形がはっきりしてきますね。7行目の「y = 1 / x」の部分を自分が調べたい式に変更すれば、どんな式でも、xとyの関係をグラフにできます。

このように、コンピューターはまじめに繰り返し計算をするのが得意です。コンピューターの長所をいかすためには、for文は必須の命令文です。

(2) importの別の書式「import A as B」

コード10の書式は記述量が多いため、一般には、以下のコード10bのような書き方をします。 コード10bの 3行目と8行目に注目してください。 3行目で「matplotlib.pyplot」に勝手に「plt」という名前をつけ、8行目で実行しています。この例では、17文字が3文字で入力できます。文法的に「plt」の部分は、どんな名前でもつけられるのですが、慣例的に決まった名前をつけることがほとんどなので、参考書などを見ながら慣例にしたがいましょう。

つまり、信頼できる参考書やサイトなどで「import A as B」のような形の表現がでてきたら、AをBという名前に置き換えているということを理解したうえで、次に自分が使うときには、同じ書き方をすればよいと思います。

#コード10b
import random
import matplotlib.pyplot as plt

for i in range(10):
    x = random.uniform(0.1, 1.0)
    y = 1 / x
    plt.plot(x, y, marker='.')
plt.show()

(3) 放物線のグラフ

別のグラフも出力してみましょう。コード11は、xが-1以上、1以下の範囲のy = x ** 2のグラフを出力します。x ** 2は、xの2乗のことですね。

#コード11
import random
import matplotlib

for i in range(1000):
    x = random.uniform(-1.0, 1.0)
    y = x ** 2
    matplotlib.pyplot.plot(x, y, marker='.')
matplotlib.pyplot.show()

y=x**2のグラフがきれいに出力できました。

(4) 方程式の解

ついでに、方程式「(x – 3) * (x + 1) = 0」を求めてみましょう。中学3年生で因数分解を習うとすぐにわかるのですが、この式にx = 3を代入すると、(x – 3)の部分がゼロになり、左辺はゼロになります。また、同様にx = -1を代入しても左辺はぜろになります。つまり、この方程式の解はx =3, -1なのです。

また、 方程式「(x – 3) * (x + 1) = 0」 を解くということは、 「y = (x – 3) * (x + 1)」が「y = 0」の時のxを求めることなので、 「y = (x – 3) * (x + 1)」が「y = 0」 交点のx座標を求めることでもあるのです。

中学1年生には、ちょっと、難しいと思いますので、 交点のxの値が「3」「-1」になっていたら、「拍手~」ぐらいの感じでも全然かまいません。

xが-5以上、5以下の範囲をグラフに出力します。5~8行目は、「y = 0」のグラフ、10~13行目は「y = (x – 3) * (x + 1)」のグラフを出力する準備を行い、15行目でグラフを出力します。

#コード12
import random
import matplotlib

for i in range(1000):
    x = random.uniform(-5, 5)
    y = 0
    matplotlib.pyplot.plot(x, y, marker='.')

for i in range(1000):
    x = random.uniform(-5, 5)
    y = (x - 1) * (x + 3)
    matplotlib.pyplot.plot(x, y, marker='.')

matplotlib.pyplot.show()

下のグラフを見ると、x(横軸)が- 3, 1のところで交わっているのがわかります。 拍手~!

matplotlibは、縦軸、横軸の最大値や最小値の設定、軸ラベルの設定なども指定するとができますが、細かい設定をしなくても、それなりのグラフを出力してくれるので大変便利です。配列(list等)を勉強すると、もっと強力なツールになりますので、使い方を少しずつ覚えましょう。

6.「パッケージ」「モジュール」

拡張子が.pyのファイルが「モジュール」であることは理解しやすいと思いますが、「モジュール」が集まって「パッケージ」になっていると言われても、抽象的すぎて分かりにくいのではないでしょうか。

便利な関数やクラスを集めたファイルが「モジュール」ですが、モジュールの数が増えてくると、似たようなモジュールを同じフォルダにまとめたり、さらにそのフォルダを別のフォルダにまとめたりしたくなります。このように、複数のモジュールをフォルダに入れて整理したものをパッケージといいます。コード12に記述されている以下のコードは、matplotlibパッケージの中にpyplotモジュールがあり、pyplotモジュールの中に記述したplotという名前の関数を使用しています。

matplotlib.pyplot.plot(x, y, marker=".")

私のパソコンの中を調べてみると、AnacondaがインストールされたフォルダAnaconda3の中の、以下の場所にmatplotlibというフォルダがありました。これがmatplotlibパッケージです。

\Anaconda3\Lib\site-packages\matplotlib

そして、matplotlibフォルダの中をのぞいてみると、pyplot.pyというファイルがありました。これが、pyplotモジュールです。pyplotモジュールには4000行を超えるコードが記述されており、中を調べると、plot関数を記述した部分を見つけることができました。

7.「ライブラリ」とは

matplotlibをネットで検索するとmatplotlibを「ライブラリ」と呼んでいる記事も多く見られます。これも、間違いではありません。
実は「ライブラリ」の定義は厳密ではなく、一般には、ライブラリは他のモジュールから呼び出すことを前提に作成された汎用的なプログラムのことを指します。つまり、Pythonでは、特定の「モジュール」を 「ライブラリ」 呼ぶだけではなく、「 関数」「モジュール」「パッケージ」などを広く含めて「ライブラリ」と呼ぶことがあります。

つまり、matplotlibは、Pythonの文法的にはパッケージです。しかし、呼び出すことを前提に作られたプログラムというニュアンスで「ライブラリ」と呼ばれることの方が多いと思いますので、混乱しないようにしましょう。

8.まとめ

(1) randomモジュール

randomモジュールには、以下の関数の他にも便利な関数が多く用意されています。randomモジュールを呼び出すには関数を使う前に「import random」と記述します。

randint(a, b)  :a以上b以下の整数の乱数を返す。
random()   :0以上1未満の少数の乱数を返す。(1以下ではなく、1未満です。)
uniform(a, b) :a以上b以下の少数の乱数を返す。

(2) for文

「for i in range(n):」のnの部分に繰り返す回数を記述することにより、for文のあとのコードを繰り返すことができます。for文の影響範囲はインデントによって設定します。
インデントとは、文の最初の空白のことで、半角の空白やtabを使います。全角の空白は使用できません。半角の空白を4つ用いることが推奨されています。

(2) matplotlibパッケージ

matplotlibパッケージは、グラフを出力するライブラリです。例えば、matplotlibパッケージの中のpyplotモジュールの中のplot関数を使って、グラフを表示することができます。matplotlibパッケージを呼び出すには、「import matplotlib」と記述します。
「matplotlib.pyplot.plot(x, y, marker=’.’)」 では、(x, y)座標をグラフに表示する準備を行います。次に「matplotlib.pyplot.show()」で、実際にグラフを表示します。

matplotlib は「import matplotlib.pyplot as plt」のような形で呼び出すことが多く、その場合には、「matplotlib.pyplot」と書かなければならない部分を「plt」に置き換えられます。

(3) 「モジュール」と「パッケージ」

Pythonのコードが書かれた拡張子が.pyのファイルが「モジュール」です。モジュールに、関数やクラスなど、便利なツールを記述することで、他のモジュールから呼び出すことができます。
一方、複数のモジュールをフォルダで整理し、ひとまとまりにしたものを「パッケージ」といいます。

(4) 「ライブラリ」

「ライブラリ」の定義は厳密ではなく、一般には、ライブラリは他のモジュールから呼び出すことを前提に作成された汎用的なプログラムのことを指します。 つまり、Pythonでは、特定の「モジュール」を 「ライブラリ」 呼ぶだけではなく、「 関数」「モジュール」「パッケージ」などを広く含めて「ライブラリ」と呼ぶことがあります。
randomモジュールも、matplotlibパッケージも、広い意味ではライブラリです。

9.例題

コード11を参考に、xとyの関数「y = x ** 3 – 10 * x ** 2 – 3」において、-5 ≦ x ≦ 10の範囲のグラフを出力してみましょう。また、マーカーの形状を点ではなく、四角にしてみましょう。

また、問題が解けたら、関数を自分が好きな関数に書き換えて、色々なグラフの出力に挑戦してみましょう。

なお、分母がゼロになるような式はエラーになる可能性がありますので注意しましょう。例えば、コード10の反比例(y = 1 / x)のグラフは、x=0にするとエラーになる可能性があります。コード10において、xの範囲を0.1以上、1以下にしたのはxがゼロにならないようにするためです。

解答を表示する
#コード13
import random
import matplotlib

for i in range(200):
    x = random.uniform(-5, 10)
    y = x ** 3 - 10 * x ** 2 - 3
    matplotlib.pyplot.plot(x, y, marker='s')

matplotlib.pyplot.show()

xの3乗の項があるグラフは、こんな、ぐにゃぐにゃのグラフになるんですね。また、マーキングが四角になっていることに注目しましょう。

私が実際に購入した教材のご紹介

以下、私が実際に購入したPythonの教材をまとめてみました。 Pythonを学習する上で、少しでもお役に立つことができればうれしいです。

Python♪私が購入したPythonの書籍のレビュー

UdemyのPythonの動画講座を書籍を買う感覚で購入してみた