2023/09/24 (日) done

Python クラスで遊ぶ

サイコロを実装化して、出目がどうなるのかを調べるクラスを作成してみよう。若干、コードにはPythonで必須のループの機能を持った  forループ が出てくる。これについては簡単だが最後尾で説明は加えておこう。
すぐにサイコロは6面体だと思い浮かべるであろうから、親属性のオプション引数で sides=6 とします。クラス名はキャメルケースでDieとする。サイコロの単数形dieを用いている。サイコロを振ることになるので、振る回数が属性になる。それを、メソッドの属性とし、__init__()メソッドでの属性に追記する。サイコロを振ることに偏向性がないものと考えれば、出目は無作為抽出であるから、CPUに1~6までの数字を無作為に選んでもらう操作で代替する。そのために、ライブラリーにあるrandomモジュールからrandint関数をインポートする。例えばrandint(4, 10)は4=< x <=10の整数値xをランダムに返す機能を持つ。説明が前後するが、range()関数を用いている。range(1, 4)は1=< x < 4の整数値であり4を含まない。ここでは、通常の意識として1回振るとのことから引数を(1, self.num + 1)としている。しかし、PCの0は単なる0ではなく、何らかの内部の数字が割り振られている。その事実を考慮に入れて、range(0, self.num)としても良い。


#サイコロの出目を調べる
from random import randint

class Die:
    def __init__(self, sides=6):
       """属性を初期化する"""
        self.sides = sides
        self.num = 0

    def roll_die(self, num):
       """振る回数設定と回数に応じた出目データの抽出"""
        self.num = num
        for i in range(1, self.num + 1):
            print(randint(1, self.sides))

my_die = Die()
my_die.roll_die(10)

#実行結果
1
5
4
5
5
1
4
5
1
2

Die()に引数が入っていないが、これは__init__()の引数にオプションとしてsides=6が指定されているからである。実はオプションと述べているように、Die(8), Die(20)とすれば八面体、二十面体を指定したことになり、オプション引数はオプションということで否定される。my_die.roll_die()で10を引数にしているが10回サイコロを振ったということで、実行結果も10個のデータが得られている。CPUの性能に依存するだろうが、一億回振ってのデータはかかる時間に目をつぶれば容易に得られる。時間がかかるようであれば、idleの対話型シェルではctrlキー + cキーでKeyboardInterruptが出て実行中止できる。
forループ
forを使えば指定した要素の間で順番に命令処理を継続して実行する機能があり、これをループ処理と呼ぶ。通常、リスト要素の処理操作によく利用されます。参照する要素が無くなれば自動でストップする。ただ、コードによっては無限ループになる可能性がある。idleでは先述の操作で解消する。違うアプリで行う際はショートカットキーの機能を確認しておいた方が宜しかろう。ここでは、簡単な例示を示しておくが、ググって参照されて下さい。なお、下のコード表記はIDLE Shell 3.11.4からペーストしたもの。


#1から100までの数字で6の倍数を見つけ出力

six_times = []

for i in range(1, 101):
    k = i % 6
    if k == 0:
        six_times.append(i)

print(six_times)

[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]

上のコードを関数で定義したものに変えたものにしてみよう。


#倍数を発見する。a:倍数値. b:正の整数かつ最大値とする.
#aの倍数値をリスト表示で出力する.

def value_times(a, b):
    value = [ i for i in range(1, b +1) if i % a == 0]
    return value

my_value = value_times(6, 100)
print(my_value)

[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]

my_value = value_times(126, 1000)
print(my_value)

[126, 252, 378, 504, 630, 756, 882]

my_value = value_times(1967, 50000)
print(my_value)

[1967, 3934, 5901, 7868, 9835, 11802, 13769, 15736, 17703, 19670,
 21637, 23604, 25571, 27538, 29505, 31472, 33439, 35406, 37373, 39340, 41307, 43274, 45241, 47208, 49175]

k = i % 6 はiを6で除した剰余をkに代入. k ==0 kがゼロに等しい.six_times.append(i) "kがゼロになるときの"iをリストsix_timesに追加せよ.
関数で書き換えたコードでvalue = [ i for -----]とあるが、リスト内包表記と呼ばれるもの。 kという変数の節約にもなっている。この方法は慣れれば難しいものではなかろう。エクセルでもあるが条件式のネストを利用している。
▲ トップへ戻る


戻る
カテゴリー