Pythonの基礎を学ぼう【#3】

# はじめに
早いもので今回が3回目です。
引き続きPythonについて学んでいきます。
前回の続きはこちら→　[Pythonの基礎を学ぼう【#2】](https://qiita.com/Hoshinon/items/72e0ef8873d042121c24)
環境はGoogle Colaboratoryを使います。

# クラスとは？
今まで学んできたプログラムをもとに、ひとまとまりにして効率よく扱うために「クラス」という機能があります。「データの設計図」とも呼ばれ、データのパラメータや、どんな機能を持っているかが書いてあります。
クラスは前回登場した「関数」よりさらに大きい概念となり、関数を複数持つことが出来ます。
「変数」も一緒に持つことができ、イメージとしては「変数」＋「関数」の集まりといえます。

![クラスの説明.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3903628/3751dc53-cd90-46a4-8d1d-e06aa6914c56.png)

# 実際に使ってみる

ここでは普通のスピードが出る黒色の車をクラスとして作ります。

```diff_python
class car:
    color = "black" #メンバ変数
    def speed(self): #メソッド
        return "normal"
```

次にcarクラスを使うためにインスタンス化します（carという変数に入れる）

```diff_python
car = car()
```

次にcarクラスの中身を確認します。すると先ほど作ったクラスの内容が表示されます。

```diff_python
print(car.color)
print(car.speed())
```

# ここで問題！
foodクラスを作りなさい。ただし、メンバ変数をtaste（味）, メソッドをcalorie（カロリー）とする。
変数やメソッドの内容は自由とする。

<!-- open属性なし -->
<details><summary>解答はこちら（解いてから見る）</summary>

一般的なおにぎり一個が170kcal程度とのこと。

```diff_python
class food:
    taste = "delicious" #メンバ変数
    def calorie(self): #メソッド
        return "170kcal"
```

</details>


# オブジェクト（もの）について
オブジェクトとは「データとメソッドのセット」を表します。
例えば下記コードを実行します。

```diff_python
taste = "delicious"
taste.upper()
```

すると、```delicious```が```DELICIOUS```と大文字になって出力されます。

この```taste```は```delicious```という文字列データを持っている上で、```upper```というメソッドも持っています。これがオブジェクトになります。
もちろんクラスも変数とメソッドを持っているのでオブジェクトと呼ぶことが出来ます。

# selfの意味
先ほどのcarクラスをもう一度確認します。

```diff_python
class car:
    color = "black" #メンバ変数
    def speed(self): #メソッド
        return "normal"
```

このメソッドで出てくる```self```は何なのでしょうか？

そこで理解を深めるために、この```self```を使用したpersonクラスを作ります。

```diff_python
class person:
  name = "taro"
  age = "15"
  def introduce(self):
    print(f"My name is {name} and I am {age} years old.")
```

```diff_python
person = person()
```

```diff_python
person.introduce()
```

一見すると動きそうです…が
このコードを実行してみるとエラーが出ます。その理由は```name```と```age```を自分のクラスから
参照できていないためです。

クラス内の変数を呼び出すときは

```diff_python
class person:
  name = "taro"
  age = "15"
  def introduce(self):
    print(f"My name is {self.name} and I am {self.age} years old.")
```

とこのように```self```を使うことによって自身の変数を利用できるようになります。
この名前は```self```以外の名前でも動きますが、読みやすさも含めて統一しておくのがおすすめです。

# __init__メソッドを使う

クラスでよく見るこのメソッド。Pythonではコンストラクタやイニシャライザと呼ばれたりします（他の言語では区別されていたりする）。ざっくり一言で表すと「初期設定用の関数」となります。例えば先ほどのpersonクラスを

```diff_python
class person:
    def __init__(self, name, age):
        self.name = name      # nameを初期化
        self.age = age        # ageを初期化

    def introduce(self):
        print(f"My name is {self.name} and I am {self.age} years old.")

```

__init__を使ってこのように表すことが出来ます。

# ここで問題！
```taro```さん、```jiro```さん、```saburo```の力を借ります。
上記の```person```クラスを使って3名を呼び出し、それぞれ自己紹介をさせなさい。
（年齢は自由です。）

<!-- open属性なし -->
<details><summary>解答はこちら（解いてから見る）</summary>

これで全員の自己紹介が出来ました。

```diff_python
class person:
    def __init__(self, name, age):
        self.name = name      # nameを初期化
        self.age = age        # ageを初期化

    def introduce(self):
        print(f"My name is {self.name} and I am {self.age} years old.")
```

```diff_python
person1 = person("taro", 10)
person2 = person("jiro", 20)
person3 = person("saburo", 30)
```

```diff_python
person1.introduce()
person2.introduce()
person3.introduce()
```

</details>

# 引き継がれし能力「継承」
ここまでクラスを作成して効率よくコードをかけるようになってきました。
さらにここからは親クラスと子クラスの考え方を身につけていきます。親クラスの機能を子クラスに引き継がせることで共通した部分はそのまま利用し、そこから派生させることが可能になります。
例えば

```diff_python
# 親クラス（スーパークラス）を定義
class Hero:
    def __init__(self, name, level):
        self.name = name
        self.level = level
    
    def introduce(self):
      print(f"私は勇者の{self.name}です。レベルは{self.level}です。")

    def attack(self):
        print(f"{self.name}は攻撃！")


# 子クラス（サブクラス）を定義し、親クラスのメソッドをオーバーライド
class Wizard(Hero):
    def introduce(self):
        print(f"私は魔法使いの{self.name}です。レベルは{self.level}です。")

    def attack(self):
        print(f"{self.name}はファイアボールを唱えた！")
```

このように```Hero```という親クラスと、その親クラスを継承した```Wizard```を作ります。
キャラクターを作成する際、名前とレベルは共通で設定する変数になるため、親クラスを使うことで子クラスでもそのまま使えるようになります。

またオーバーライドと書いてありますが、これは親クラスで定義したメソッドを子クラスで上書きするという意味になります。
今回の場合、```introduce```と```attack```メソッドは魔法使いの表現に合わせています。


# ここで問題！
「レベル50の勇者シロ」と「レベル60の魔法使いクロ」を召喚したい。上記コードを使って自己紹介と攻撃文を表示させなさい。

<!-- open属性なし -->
<details><summary>解答はこちら（解いてから見る）</summary>

便利な継承。使っていきましょう。

```diff_python
hero = Hero("シロ", 50)
hero.introduce() 
hero.attack() 
```

```diff_python
wizard = Wizard("クロ", 60)
wizard.introduce()
wizard.attack()
```

</details>

# ★最終問題★
継承で使ったコードを参考に自分の好きな親クラス、子クラスを1つずつ作成せよ。

# 便利な標準ライブラリ紹介
## datetime(ZoneInfo利用)
現在時刻を取得したいときに使用。

```diff_python
from datetime import datetime
from zoneinfo import ZoneInfo

now = datetime.now(ZoneInfo("Asia/Tokyo"))
print("現在の日時（JST）:", now)
```

## time
特にWebスクレイピングやAPI通信(データをやり取りするための仕組み)を行う際、過度なアクセスによるサーバーへの負荷を防ぐために```time.sleep```を使用する。

```diff_python
import time

print("3秒待つ…")
time.sleep(3)
print("再開！！")
```

## random
このコードでは1から100までのランダムな整数を生成する。ランダムな数字を使うゲームをプログラムする際によく使う。

```diff_python
import random

random_int = random.randint(1, 100)
print("ランダムな整数:", random_int)
```

## calendar
年や月単位のカレンダーを表示できる。「あの日何曜日だっけ…」という疑問をコード書きながらさっと解決することが出来る。

```diff_python
import calendar
calendar.prcal(2025) 
```

```diff_python
print(calendar.month(2025, 6))
```

# 参考文献
この記事は以下の情報を参考にして執筆しました。


[確かな力が身につくPython「超」入門 (確かな力が身につく「超」入門シリーズ)](https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FPython%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8F%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E9%8E%8C%E7%94%B0-%E6%AD%A3%E6%B5%A9/dp/4797384409)

[スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BPython%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8B%E5%85%A5%E9%96%80%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%9B%BD%E6%9C%AC-%E5%A4%A7%E6%82%9F/dp/4295016365/ref=pd_lpo_d_sccl_1/357-4097415-1030165?pd_rd_w=Bff0K&content-id=amzn1.sym.855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_p=855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_r=6P5B2BTEV9JTKQAXEDRV&pd_rd_wg=pGnzd&pd_rd_r=f0b33b55-8669-49f5-8027-49649fe1966c&pd_rd_i=4295016365&psc=1)