【Python】僕と僕たちの青春劇。Part. 1

前回の記事では、ミュータブルとイミュータブルの中身が非常にうまく組み合わさってPython言語は作られていることが分かりました。

もし、前回の記事を見られていない方は以下からぜひご参照ください。

恐らく、初期化を行わないことを考えるのであれば
オブジェクト指向タイプの言語では、同じ挙動になるのでは?と思わなくもありません。

と思って別の記事を探したら、案の定でした。

(Qiitaの記事を勝手にリンクするのはアウトなんでしょうか?ダメだったら消すのでどなたか教えてください。

こちらのコメント欄で、Javaにて同じ挙動を確認されている方がいらっしゃいました。
また、前回記事よりも専門的な用語と手法で概ね同じことが、きちんと説明されていますので、更に詳しく知りたい方はこちらの記事もご参照ください。


インスタンス変数とかクラス変数の扱い方は、Pythonだと隠蔽されているので少し混乱しやすいところ。

上記Qiita記事のコメントで扱われていたJavaのコードだと、露骨にstaticキーワードを付けないと同様の挙動は再現できていません。


個人的に、ミュータブルとイミュータブルの挙動が面白かったので前回記事は、その観点でご参考になれば幸いです。


///

0. 物語は突然に

今回は少し趣向を変えて、昔懐かしい中学校を題材にしてPythonの世界に浸りたいと思います。
少し長くなったので、数回に分けて進めていきますのでお付き合い頂ければ幸いです。

注意:この物語はフィクションです。実在の人物、団体とは一切関係がありません。

"""

仮にケンジ、略してKがこの物語の主人公です。

彼は、とある中学校の学生です。

彼には、幼馴染が二人。
眉目秀麗、頭脳明晰、冷静沈着、ちょっぴり天然なモトキ君、略してM
容姿端麗、公明正大、英俊豪傑、イケメン女子のリンネさん、略してR


さて
ちょうど彼らの学校では期末試験が終わり、テスト返却が行われていました。
学校では5教科。国語、数学、英語、社会、理科のテストが行われており
点数の合計で順位が付けられます。

彼らのテストの順位は、常にM,K,RまたはM,R,Kの順番に並んでいます。

また、KはMより社会が得意で、RはKより英語が得意であり
点数もその通りに反映されています。

今回の試験でも、彼らのセオリーが大きく変わることはないでしょう。


全体の平均点が発表されたあとに、KはMとRにある提案をします。

K「最も高い点数の教科で競い合って、一番の奴に他2人はジュースを奢るってのはどうよ?」

M「そう言って、ジュースを奢ってもらうのは何回目になるかな?」

R「そうだぞ!私まで巻き込まれていい迷惑だ!」

M「そう言いながら、付き合ってあげるところがりんねの良いとこだよね。」

R「私は勝負事からは逃げない。売られた勝負は買うのが礼儀というものだ」

K「よし!負け犬りんねも参加だな。モトキももちろんやるよな?」

R「お!い!誰が負け犬か!誰が!身の程を叩き込んでやろうか!」

M「はっはっはっ、まあまあ。じゃあ、点数をK「ちょっと待った」

K「どうせモトキには正攻法で勝てない。どうせ100点もあるだろうからな!よって、モトキは全教科を合計して5で割った平均点で戦ってもらう。拒否権はない!」

R「ほう?ケンジにしては考えたじゃないか。よし!それなら私にも勝ち目がありそうだな」

M「また勝手に。まあ、別に構わないけど」

K「余裕ぶってられるのも今の内だ!今回こそは俺が勝つ!」

R「勝つのは私だ!なんども土を付けられてたまるものか!」

M「はいはい。お熱い二人の意見は分かったから、ほら一番良い点数出してよ」

さて、この勝負を制したのは・・・。

"""

っと、中々青春な匂いがしますね。(知らんけど


1. データ構造を組み立てる

今回はパート1と題してデータ構造を少し考えてみようと思います。

データ構造は、頭の体操にもちょうど良いですし
これから記載するのは、私なりの構造なので
皆さんもぜひ自分なりの構造を考えてみてくださいね。

最終的にK、M、Rのそれぞれの点数をランダムで生成して、点数の勝負を行うようなプログラムを作ることを目標に進んでいきます。


2. ベースを決める

それぞれの登場人物の特徴をよく表すように構造を作っても良いですし、必要最低限を盛り込むだけでも十分です。

今回は、必要最低限の情報だけを盛り込んでみたいと思います。
登場人物をCharacterとした時に、CharacterにはテストのScoreが必要でしょう。
では、そんなクラスを2つ、まずは作ってみます。

import random 

class Character:
  def __init__(self):
    self.score = Score()


class Score:
  def __init__(self):
    self.reset_japanese()
    self.reset_math()
    self.reset_english()
    self.reset_social()
    self.reset_science()

  def reset_japanese(self, min=0, max=100):
    self.japanese = random.randint(min, max)
 
  def reset_math(self, min=0, max=100):
    self.math = random.randint(min, max)
 
  def reset_english(self, min=0, max=100):
    self.english = random.randint(min, max)
 
  def reset_social(self, min=0, max=100):
    self.social = random.randint(min, max)
 
  def reset_science(self, min=0, max=100):
    self.science = random.randint(min, max)
 
  def print_score(self):
    print("国語:{}".format(self.japanese))
    print("数学:{}".format(self.math))
    print("英語:{}".format(self.english))
    print("社会:{}".format(self.social))
    print("理科:{}".format(self.science))
 
K = Character()
K.score.print_score()

各教科の点数をランダムで決められるようにしてみました。

なんだか一杯書いてありますが、やってることは非常に単純です。


1. CharacterクラスとScoreクラスを作る。
2. ScoreはCharacter別に保持しているものなので、Characterの変数としてScoreを持たせる。
3. Characterが生み出されると同時にテストの点数が決まるようにする。
4. テストの点数は個別に決定されるようにしておく。
5. テストの点数はランダムで決定されるようにする。

ex. 表示するのが面倒なので、表示する関数もあらかじめ作っておく。


さて

この中ですと、ScoreとCharacterの親子関係の付け方が少し分かり難いでしょうか?
では、逆を考えてみましょう。

もし、Scoreが親でCharacterが子である時
例えば、AというScoreに紐づくCharacterがα, β, γといるのであれば
Scoreを親にした方が扱いやすいかも知れません。


もう少し具体的に図解しましょう。

今回、私が作ったのが以下の構造です。

K ━ Character ━ Score ┳  国語の点数
                                           ┣ 数学の点数
                                           ┣ 英語の点数
                                           ┣ 社会の点数
                                           ┗ 理科の点数

片や逆の場合

A ━ Score ┳ Character ┳ α
                   ┃                   ┣ β
                   ┃                   ┗ γ
                   ┣ 国語の点数
                   ┣ 数学の点数
                   ┣ 英語の点数
                   ┣ 社会の点数
                   ┗ 理科の点数

こんな感じの構造になるでしょうか?

もしくは

A ━ Score ┳ 国語の点数 ━ Character ┳ α
                   ┃                                            ┣ β
                   ┃                                            ┗ γ
                   ┣ 数学の点数 ━ Character ┳ Δ
                   ┃                                            ┣ α
                   ┃                                            ┗ ζ
                   ┣ 英語の点数 ━ Character ┳ η
                   ┃                                            ┣ β
                   ┃                                            ┗ ι
                   ┣ 社会の点数 ━ Character ┳ κ
                   ┃                                            ┣ ε
                   ┃                                            ┗ ι
                   ┗ 理科の点数 ━ Character ┳ α
                                                                   ┣ Δ
                                                                   ┗ ο

これらは用途の違いなので、良いも悪いもありません
こういうデータ構造が使いやすいプログラムも、もちろんあると思います。

ただ、今回はテストの点数で勝負することを目的にするので
CharacterごとにScoreを持っていた方が分かりやすい。
という意味で、Score in Characterにしました。

ScoreとCharacterを逆にしたいとすれば
例えば、点数と人の関係を知りたい場合や特定の点数に属している人を知りたい場合などではないでしょうか?


3. 特徴をよk...え?今回ここまで?

タイトルさん、フライングはいけません。今回はここまで。

パート2は、K, M, Rのそれぞれの特徴をこのデータ構造のScoreに反映させていきたいと思います。

つまり、社会が得意なK英語が得意なR100点もあるらしいMの点数をK, M, Rの点数を用いてより良く表現するように補正を掛けます。

どういうことなんでしょうね?
そして、KとMとRの一体誰がジュースを手に入れられたのでしょうか!?


次回はこちら



では。

この記事が気に入ったらサポートをしてみませんか?