概要
namedtupleは存在は知ってたけど、使い方を知ったら「すげえ(きめえ)」という感想にしかならなかったので、記事に書きました*1。
namedtupleはクラスではない
普通は、namedtupleというクラスがあると思いませんか? さにあらず、関数です。
>>> from collections import namedtuple >>> namedtuple <function namedtuple at 0x7f8c288800d0>
お、おう。使い方を調べます。
名前付きフィールドを持つタプルのサブクラスを作成するファクトリ関数
>>> # Basic example >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(11, y=22) # instantiate with positional or keyword arguments >>> p[0] + p[1] # indexable like the plain tuple (11, 22) 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> p # readable __repr__ with a name=value style Point(x=11, y=22)
あー、そういうものだったの。
第一引数はクラス名、第二引数は「属性」の名前ですね。はい。こいつはクラスを返します。
大切なことなのでもう一度書きます。namedtupleはクラスを生成して返す関数です。
動的言語の面目躍如という感じ……。
一応タプルらしい
タプルらしく、中身を変えられないし、hashableです。
>>> Hoge = namedtuple("Hoge", "a b") # 空白orカンマ区切り文字列で属性リストにできる >>> h = Hoge(a=1, b=2) >>> h Hoge(a=1, b=2) >>> h[0] = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'Hoge' object does not support item assignment >>> h.a = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>> {h} {Hoge(a=1, b=2)}
だいたい期待する性質は持っていると言っていいでしょう。いや、気持ち悪いですが。
でもしょせんただのクラスなので
継承して好きなメソッドを定義したりできます。すごい!
>>> class Hoge2(Hoge): ... def product_of_a_and_b(self): ... return self.a * self.b ... >>> h2 = Hoge2(a=10, b=100) >>> h2.product_of_a_and_b() 1000
元のクラスが要らなければ、こういう書き方もあります。上のドキュメントに紹介されている例です。
>>> class Point(namedtuple('Point', ['x', 'y'])): ... __slots__ = () ... @property ... def hypot(self): ... return (self.x ** 2 + self.y ** 2) ** 0.5 ... def __str__(self): ... return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot) >>> for p in Point(3, 4), Point(14, 5/7): ... print(p) Point: x= 3.000 y= 4.000 hypot= 5.000 Point: x=14.000 y= 0.714 hypot=14.018
理解はできるけど、すごく○○です……。
まとめ
こういうものだとは知らなかったのと、発想が斜め上を行っているのと、いろいろな意味で驚きました。
クラス定義のコンストラクタ(__init__)の記述を省略したりするのにも使えるそうです。言われるとなるほどと思いますが、pythonはほんと奥が深いですね……。
*1:そんなことも知らないでPython書いてたのかよって感じですが