クラス
クラス
以下にクラスの定義の仕方の例を示す。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | class ClassName:
# 正確にはクラス属性というらしい
class_member = "クラス変数"
def __init__(self) -> None:
self.__private_member = "プライベート変数"
print("コンストラクタ")
def member_method(self) -> None:
print("メンバーメソッド")
def __private_member_method(self) -> None:
print("プライベートメンバーメソッド")
# getter
@property
def member(self) -> str:
print("ゲッター")
return self.__private_member
# setter
@member.setter
def member(self, value: str) -> None:
print("セッター")
self.__private_member = value
# クラスメソッド
@classmethod
def class_method(cls) -> None:
cls.class_member = "書き換わったクラス変数"
print("クラスメソッドはクラス変数を書き換えられる")
# 静的メソッド
@staticmethod
def static_method() -> None:
print("静的メソッドはクラス変数を書き換えられない")
def main():
c = ClassName()
print(ClassName.class_member)
print(c.member)
c.member = "書き換わったプライベート変数"
print(c.member)
c.member_method()
ClassName.class_method()
print(ClassName.class_member)
ClassName.static_method()
if __name__ == "__main__":
main()
|
抽象クラス(インターフェース)
abc.ABCクラスを継承させることで抽象クラスを定義することができる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | from abc import ABC, abstractmethod
class ReaderGateway(ABC):
@abstractmethod
def read(self) -> str:
pass
class ReaderService(ReaderGateway):
def read(self) -> str:
return input("> ")
def main():
reader_gateway = ReaderService()
reader_gateway.read()
if __name__ == "__main__":
main()
|
データクラス
@dataclassを使うとデータクラスを定義できる。
データクラスはクラスと異なり__init__()、__repr__()、__eq__()などのメソッドが自動生成される。それ以外はクラスと同じのようで、データクラスにメソッドやクラスメソッドをもたせることもできる。
1
2
3
4
5
6
7
8
9
10
11
12 | from dataclasses import dataclass
@dataclass
class Server:
ip_address: str
port: int
# データを格納したいだけならデータクラスを使えばコンストラクタを定義しなくて済む分、楽である
server = Server("127.0.0.1", 80)
print(f"{server.ip_address}:{server.port}")
|
イミュータブルなデータクラスと完全コンストラクタ
@dataclass(frozen=True)を使うとイミュータブルなデータクラスを定義できる。
以下の点でいまいちである。
- ミュータブルなメンバー(例:
list、dict、class)にはイミュータブルは適用されない
- イミュータブルなメンバーを変更するようなコードを書いても VSCode は構文エラーを出してくれず、実行時エラーになる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | from dataclasses import dataclass
from typing import Self
@dataclass(frozen=True)
class Todo:
id: str
status: str
def __post_init__(self: Self) -> None:
# __post_init__でメンバーの値の妥当性をチェックできる
if self.status not in ["notStartedYet", "inProgress", "done"]:
raise Exception("Invalid status")
immutable = Todo("aaa", "notStartedYet")
immutable.status = "bbb"
print(immutable)
|