C#エンジニアのためのPythonクラス入門：主要な違いと注意点

C# に慣れた状態で Python を実装する際に戸惑いやすいと思ったクラスに関する違いについて、実例を交えながら解説していきます。

## コンストラクタの記述

C#ではクラス名と同名で定義していたコンストラクタですが、Python では `__init__` というメソッド名を使用します。

```python
# Python
class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

# C#での書き方（参考）
# public class Person
# {
#     private string _name;
#     private int _age;
# 
#     public Person(string name, int age)
#     {
#         this._name = name;
#         this._age = age;
#     }
# }
```

ちなみに python の場合、インスタンス変数の「定義」をすることはできず、代入文を書くことで生成されます。

## クラス変数や定数の扱い

Python では、C# とは異なり `const` や `static` キーワードは存在しません。
代わりに以下のような方法で実現します：

```python
class Configuration:
    # クラス変数（C#でいうstatic変数に相当）
    DEFAULT_PORT = 8080  # 慣習的に大文字で定数のように扱う

    # インスタンス変数
    def __init__(self):
        self.port = Configuration.DEFAULT_PORT


# C#での書き方（参考）
# public class Configuration
# {
#     // staticフィールドとして定義
#     private static readonly int DefaultPort = 8080;
#
#     public int Port { get; private set; }
#
#     public Configuration()
#     {
#         Port = DefaultPort;
#     }
# }
```

クラス変数へのアクセスは `クラス名.変数名` の形で実施します。

注意点として、Python のクラス変数は全インスタンス間で共有されます。これは C# の `static` 変数と同様の動作です。

## 説明用のコメントの書き方、位置

こちらは厳密にはクラスの話ではないですが、クラスを記述する際に意識することが多いため記載しておきます。
Python では、クラスやメソッドの説明には docstring を使用します。これは C# の XML コメントに相当し、クラスやメソッドの**下側に**記述します：

```python
class BankAccount:
    """
    銀行口座を管理するクラス。

    Attributes:
        balance (float): 現在の残高
        account_number (str): 口座番号
    """

    def deposit(self, amount):
        """
        指定された金額を口座に入金する。

        Args:
            amount (float): 入金額

        Returns:
            float: 入金後の残高
        """
        self.balance += amount
        return self.balance

# C#での書き方（参考）
# /// <summary>
# /// 銀行口座を管理するクラス
# /// </summary>
# public class BankAccount
# {
#     /// <summary>
#     /// 口座残高
#     /// </summary>
#     public decimal Balance { get; private set; }
# 
#     /// <summary>
#     /// 指定された金額を口座に入金する。
#     /// </summary>
#     /// <param name="amount">入金額</param>
#     /// <returns>入金後の残高</returns>
#     public decimal Deposit(decimal amount)
#     {
#         this.Balance += amount;
#         return this.Balance;
#     }
# }
```

## 関数パラメータの self

これは多くの C# エンジニアが最初に戸惑うポイントなのではないでしょうか？
Python ではインスタンスメソッド定義時に、最初のパラメータとして明示的に `self` を記述する必要があります：

```python
class Car:
    def __init__(self, model):
        self.model = model

    def start_engine(self):  # selfは必須
        print(f"{self.model}のエンジンを始動")

    @staticmethod  # staticメソッドの場合はselfは不要
    def get_manufacturer():
        return "Example Motors"

# C#での書き方（参考）
# public class Car
# {
#     private string model;
#     
#     public Car(string model)
#     {
#         this.model = model;
#     }
#     
#     public void StartEngine()
#     {
#         Console.WriteLine($"{this.model}のエンジンを始動");
#     }
#     
#     public static string GetManufacturer()  // staticメソッド
#     {
#         return "Example Motors";
#     }
# }
```

### self を使う際の注意点：

- インスタンスメソッドでは必ず第一引数として記述する必要があります
- メソッド呼び出し時には`self`を明示的に渡す必要はありません

## 継承と多重継承

C#では多重継承ができませんが、Python では可能です：

```python
class Animal:
    def eat(self):
        print("eating")

class Flyable:
    def fly(self):
        print("flying")

class Bird(Animal, Flyable):  # 多重継承
    pass
```

## アクセス修飾子の違い

C# の変数では `public`、`private`、`protected` などを明示的に指定してアクセス可能な範囲を制限できますが、Python ではすべての変数が公開されるため命名規則で表現します：

- 慣習的なプライベート: `_name`（アンダースコア 1 つ）
- 名前の衝突を避けられるプライベート: `__name`（アンダースコア 2 つ）
  - 内部的に、「"\_" + <親クラス名> + <プレフィックスを含む変数名>」の形に変換される
- パブリック: プレフィックスなし

詳細は下記を確認してください。

https://docs.python.org/3/tutorial/classes.html#private-variables

## 抽象クラスとインターフェース

C#の `interface` や `abstract` に相当する機能として、Python では [`abc` モジュール](https://docs.python.org/ja/3/library/abc.html) を使用します：

```python
from abc import ABC, abstractmethod

class Vehicle(ABC):
    @abstractmethod
    def start_engine(self):
        pass

    @abstractmethod
    def stop_engine(self):
        pass

    def describe(self):  # 通常のメソッド（オーバーライド任意）
        return "This is a vehicle"

# 具象クラス
class Car(Vehicle):
    def start_engine(self):
        return "Car engine started"

    def stop_engine(self):
        return "Car engine stopped"

# C#での書き方（参考）
# public abstract class Vehicle
# {
#     // 抽象メソッド（実装必須）
#     public abstract void StartEngine();
#     public abstract void StopEngine();
#
#     // 通常のメソッド（オーバーライド任意）
#     public virtual string Describe()
#     {
#         return "This is a vehicle";
#     }
# }
#
# // 具象クラス
# public class Car : Vehicle
# {
#     public override void StartEngine()
#     {
#         Console.WriteLine("Car engine started");
#     }
#
#     public override void StopEngine()
#     {
#         Console.WriteLine("Car engine stopped");
#     }
# }
```