フィールドアクセスの可読性を簡単に向上させる方法

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)

これらの解決策として、namedtupledataclassがあります。

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__()のような特殊メソッドを自動で生成してくれるので、クラス定義が簡潔になります。

このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です