フィールドアクセスの可読性を簡単に向上させる方法
Pythonの辞書でフィールドにアクセスする場合、可読性が悪いという問題があります。他の言語に慣れている余計にです。
クラスはインスタンス変数に.
ドットアクセス可能なため可読性が上がりますが、定義が面倒です。
辞書
キー(フィールド)に、.
ドットアクセスができない。
point = { 'x': 0, 'y': 0 }
print(point) # {'x': 0, 'y': 0}
print(point.x) # NameError: name 'x' is not defined
代入はできる。
point = { 'x': 0, 'y': 0 }
print(point['x'], point['y']) # 0 0
point['x'] = 1
print(point) # {'x': 1, 'y': 0}
クラス
定義が面倒。
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
p = Point(0, 0)
print(p) # Point(x=0, y=0)
代入はできる。
p = Point(0, 0)
p.x = 1
print(p) # Point(x=1, y=0)
これらの解決策として、namedtuple
とdataclass
があります。
namedtuple
namedtuple
はタプルのサブクラスで、フィールドに名前を付けることができるデータ構造です。
namedtuple
を使うと、.
ドットアクセス可能なオブジェクトが簡単に作成できます。
ただし、不変(イミュータブル)なため、フィールドの値の変更はできません。
データが変更されては困る場合に利用できます。
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p1 = Point(1,1)
print(p1) # Point(x=1, y=1)
p1.x = 9 # AttributeError
変数自体の入れ替えはもちろん可能。
p1 = Point(1,1)
print(p1) # Point(x=1, y=1)
p2 = Point(2,2)
p1 = p2
print(p1) # Point(x=2, y=2)
dataclass
Python 3.7以降では、dataclasses
モジュールを使用して、可変(ミュータブル)なデータクラスを簡単に定義できます。
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p1 = Point(1,1)
print(p1) # Point(x=1, y=1)
p1.x = 9
print(p1) # Point(x=9, y=1)
p2 = Point(2,2)
p1 = p2
print(p1) # Point(x=2, y=2)
__init__()
や __repr__()
のような特殊メソッドを自動で生成してくれるので、クラス定義が簡潔になります。