この記事は Pythonのコードを短く簡潔に書くテクニック Advent Calendar 2017 の2日目です。
はじめに
データベースなどから読み込んだレコードを格納するような所謂バリューオブジェクトと呼ばれる、データを格納するだけのクラスを作りたいときがあります。
Pythonでこのクラスを作ると、__init__
でself.xxx = xxx
という冗長なコードを書かなくてはならないのですが、namedtuple(名前付きタプル)を使うと簡単に作れます。
[2018/07/16 追記]
Python3.7以降ではdataclassを使うほうが便利です。
Python3.7からは「Data Classes」がクラス定義のスタンダードになるかもしれない - Qiita
クラスで作った場合
class Item:
def __init__(self, title, url, user, body):
self.title = title
self.url = url
self.user = user
self.body = body
namedtupleで作った場合
from collections import namedtuple
Item = namedtuple('Item', ('title', 'url', 'user', 'body'))
第一引数がクラス名、第二引数がフィールド名のリストです。
namedtupleの特徴
普通のクラスと同じようにオブジェクトを作成できます。
また、__str__
メソッドを定義しなくても中身が確認できます。
>>> Item('item1', 'http:example.com/item1', 'user1', 'body1')
Item(title='item1', url='http:example.com/item1', user='user1', body='body1')
>>> Item(title='item1', url='http:example.com/item1', user='user1', body='body1')
Item(title='item1', url='http:example.com/item1', user='user1', body='body1')
フィールドには属性名でアクセスできます。
>>> item = Item(title='item1', url='http:example.com/item1', user='user1', body='body1')
>>> item.title
'item1'
タプルなのでインデックスでもアクセスできます。
>>> item[0]
'item1'
タプルはイミュータブルなので値の変更はできません。
>>> item.title = 'item2'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
JSONに変換もできます。
>>> import json
>>> json.dumps(item)
'["item1", "http:example.com/item1", "user1", "body1"]'
>>> json.dumps(item._asdict())
'{"title": "item1", "url": "http:example.com/item1", "user": "user1", "body": "body1"}'