【Python初心者】クラスの正体をシンプルに理解する4つの要素

Pythonでクラスを学び始めたとき、「なんとなく難しそう…」と感じる方も多いと思います。  
ですが、クラスを構成する要素をシンプルに4つに分けて考えると、一気に理解しやすくなりました。

この記事は、学習記録として「クラスの中身は何でできているか？」を整理したものです。  
同じように迷っている方の参考になれば幸いです。

## 1. 属性（attribute）

**✔️ 役割：** オブジェクトの状態（データ）を保持する

Pythonでは、属性とは「名前付きの値」のことで、主に2種類あります：

- **インスタンス変数（instance variable）**：インスタンスごとに異なる値  
- **クラス変数（class variable）**：クラス全体で共有される値

### ■ インスタンス変数の例（コンストラクタで設定）

```python
class Dog:
    def __init__(self, name):
        self.name = name  # ← インスタンス変数（個別の状態）

dog1 = Dog("ポチ")
dog2 = Dog("ハチ")

print(dog1.name)  # ポチ
print(dog2.name)  # ハチ
```

インスタンス変数は、**各オブジェクトごとに異なる状態を持たせる**ための属性です。`self.変数名` の形で定義されます。

### ■ クラス変数の例

```python
class Dog:
    species = "犬"  # ← クラス変数（全てのインスタンスで共有）

print(Dog.species)  # 犬

a = Dog()
b = Dog()
print(a.species)  # 犬
print(b.species)  # 犬
```

クラス変数は、**すべてのインスタンスで共通**のデータです。`クラス名.変数名` でもアクセスできます。

### ✔️ 補足：どちらも「属性」

Pythonでは、クラス変数・インスタンス変数のどちらも「属性」に分類されます。  
実際に `vars(obj)` や `dir(obj)` などで調べると、属性として一覧に出てきます。

## 2. メソッド（method）

**✔️ 役割：** クラスに関連する処理を定義する関数

```python
class Person:
    def greet(self):
        print("こんにちは！")

p = Person()
p.greet()  # こんにちは！
```

関数 `greet` のように、クラス内で `def` で定義された関数は「メソッド」と呼ばれます。  
引数に `self` をとることで、インスタンスの状態にアクセスできます。

## 3. プロパティ（property）

**✔️ 役割：** 属性のように見えるが、裏で処理を行う関数

```python
class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def area(self):
        return 3.14 * (self._radius ** 2)

c = Circle(5)
print(c.area)  # 78.5 ← ()なしでアクセスできる
```

`@property` を使うことで、値のようにアクセスできる「処理付き属性」を作ることができます。  
ユーザーに「これは関数です」と意識させず、**自然な属性のように使える**のがメリットです。

## 4. 特殊メソッド（special method）

**✔️ 役割：** Pythonの内部動作と連携するためのメソッド

```python
class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"Person(name={self.name})"

p = Person("たろう")
print(p)  # Person(name=たろう)
```

特殊メソッドは `__init__`, `__str__`, `__len__` など、`__〇〇__` の形をしており、  
Pythonの組み込み関数や演算子の動作をカスタマイズできます。  
このような特殊メソッドは「ダンダーメソッド（dunder method）」と呼ばれることもあります。

## メソッドとプロパティの見分け方・使い分け

初心者のうちは「メソッドとプロパティってどう違うの？」と迷いやすいので、ここで簡単に整理します。

| 比較項目 | メソッド | プロパティ |
|----------|----------|------------|
| 呼び出し方 | `obj.method()` | `obj.prop`（`()` なし） |
| 見た目 | 関数っぽい | 値っぽい |
| 引数 | 必要に応じて渡せる | 引数は渡せない |
| 目的 | 明確な処理を実行したいとき | 値を取得・設定したいとき（処理を隠したいとき） |
| 定義方法 | `def method(self):` | `@property` をつけた `def` |

### ✔️ 使い分けの目安

- 「これは**操作・動作**だな」と思うなら → メソッド（関数）
- 「これは**データっぽい**な」と思うなら → プロパティ（`@property`）


### ✔️ 例

```python
class Dog:
    def __init__(self, birth_year):
        self._birth_year = birth_year

    def bark(self):  # 処理を実行 → メソッド
        print("わん！")

    @property
    def age(self):  # 値を取得するだけ → プロパティ
        return 2025 - self._birth_year        
```

使うとき：

```python
dog = Dog(2020)
dog.bark()      # ← 動作なので()が必要
print(dog.age)  # ← 値なので()は不要
```

## クラスは「属性と処理のかたまり」

クラスとは、ざっくり言えば、

**属性（データ）と処理（メソッド）をまとめた設計図**です。  
さらにプロパティや特殊メソッドを使うことで、より直感的で安全なクラス設計が可能になります。

## まとめ

| 要素         | 説明                              | キーワード・記法             |
|--------------|-----------------------------------|------------------------------|
| 属性         | オブジェクトが持つ値              | `self.name`, `Dog.species`   |
| メソッド     | クラスに属する関数（処理）        | `def greet(self):`           |
| プロパティ   | 属性のようにアクセスできる関数    | `@property`                  |
| 特殊メソッド | 特別な意味を持つ組み込み連携用関数 | `__init__`, `__str__`, etc.  |

## 最後に

クラスの中身をこの4つに分けて考えることで、「クラスって何？」という漠然としたモヤモヤがだいぶスッキリしました。

特に、**メソッドとプロパティの違い**を意識することで、設計がきれいになり、コードも読みやすくなります。

次は、クラスを使用するには欠かせない「ドット（.）の使い方」についても整理してみたいと思います。