PythonのNamedTupleとdataclass
Pythonにはデータの保持を目的としたシンプルなクラスのために、NamedTupleまたはdataclassを使うことができる。
どちらも簡潔に書くことができる
__init__メソッドやや __eq__メソッドが自動で生成される
NamedTupleはイミュータブル
dataclassはミュータブル
code:main.py
from typing import NamedTuple, List, Dict
from dataclasses import dataclass
class ImmutablePoint(NamedTuple):
"""
イミュータブルなクラス。フィールドの値を再代入できない。
"""
x: int = 0
y: int = 0
# リストと辞書にデフォルト値を使うことができる
l: Listint = []
d: Dictstr, int = {}
@dataclass
class MutablePoint:
"""
ミュータブルなクラス。フィールドの値を再代入できる。
"""
x: int
y: int
# リストと辞書にデフォルト値を使うことができない
# l: Listint = [] can not use default value for mutable type, because it will be shared between all instances
l: Listint
# d: Dictstr, int = {} can not use default value for mutable type, because it will be shared between all instances
d: Dictstr, int
code:test_main.py
from unittest import TestCase
from main import ImmutablePoint, MutablePoint
class Test(TestCase):
def test_ImmutablePoint(self):
x = 1
y = 2
l = 1, 2
d = {'x': 1, 'y': 2}
p = ImmutablePoint(x, y, l, d)
self.assertEqual(p.x, x)
self.assertEqual(p.y, y)
self.assertEqual(p.l, l)
self.assertEqual(p.d, d)
# raise error if try to change value
with self.assertRaises(AttributeError):
p.x = 3
with self.assertRaises(AttributeError):
p.y = 4
with self.assertRaises(AttributeError):
p.l = 1, 2, 3
with self.assertRaises(AttributeError):
p.d = {'x': 1, 'y': 2, 'z': 3}
# append an item to the list
l.append(3)
self.assertEqual(p.l, 1, 2, 3)
# insert an item to the dictionary
d.update({'z': 3})
self.assertEqual(p.d, {'x': 1, 'y': 2, 'z': 3})
def test_MutablePoint(self):
x = 1
y = 2
l = 1, 2
d = {'x': 1, 'y': 2}
p = MutablePoint(x, y, l, d)
self.assertEqual(p.x, x)
self.assertEqual(p.y, y)
self.assertEqual(p.l, l)
self.assertEqual(p.d, d)
# not raise error if try to change value
p.x = 3
p.y = 4
p.l = 1, 2, 3
p.d = {'x': 1, 'y': 2, 'z': 3}
# append an item to the list
p.l.append(4)
self.assertEqual(p.l, 1, 2, 3, 4)
# insert an item to the dictionary
p.d.update({'z': 4})
self.assertEqual(p.d, {'x': 1, 'y': 2, 'z': 4})