先日Pythonの新機能としてData Classesが採用されました
PEP 557 -- Data Classes accepted: https://t.co/6LDFXMBcLj
— Python Software (@ThePSF) 2017年12月6日
Data Classesとは?
PEP 557のなかで、以下のように述べられている。
Data Classes can be thought of as "mutable namedtuples with defaults". Because Data Classes use normal class definition syntax, you are free to use inheritance, metaclasses, docstrings, user-defined methods, class factories, and other Python class features.
一言で言えば、「デフォルト値があるミュータブルなnamedtuple」。
@dataclass
class InventoryItem:
'''Class for keeping track of an item in inventory.'''
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
のように宣言すると、
def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0) -> None:
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand
def __repr__(self):
return f'InventoryItem(name={self.name!r}, unit_price={self.unit_price!r}, quantity_on_hand={self.quantity_on_hand!r})'
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) == (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __ne__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) != (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) < (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) <= (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) > (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.name, self.unit_price, self.quantity_on_hand) >= (other.name, other.unit_price, other.quantity_on_hand)
return NotImplemented
といったメソッドが自動で生成される。
namedtupleとの違い
- namedtupleは、偶然同じ数のfieldを持つ他のnamedtupleと比較できる。
- Data Classでは、ここでFalseを返す。
>>> Point3D(2017, 6, 2) == Date(2017, 6, 2)
True
- namedtupleは、偶然tupleと比較できる。
- Data Classでは、ここでFalseを返す
>>> Point2D(1,10)==(1,10)
True
- fieldを後から追加するのが難しい
- mutableにできない
- デフォルト値を指定できない
-
__init__
や__repr__
に使われるfiledを制御できない - 継承によるfieldの結合ができない
typing.NamedTupleとの違い
- 型アノテーションを利用できるが、結局はnamedtupleと同じ問題が残る
attrsとの違い
- https://github.com/python-attrs/attrs
- attrsは、validatorsやconverters, metadataなどData Classにはない機能をサポートしている
- Data Classesはこれらの機能を実装しないことでシンプルに保っている
- 以下のissueで色々議論されている
- https://github.com/ericvsmith/dataclasses/issues/19
- attrsを標準に組み込むのはどう?という議論に対して、guidoが反対している
Python 3.7 Release Schedule
予定では2018/6/15がPython3.7のリリース日。
Data Classesは使い勝手が良さそうなので、今から楽しみですね。