dataclassデコレータ

クラスの定義にdataclassデコレータを付けることで__init__やら__repr__を自動生成してくれる。

通常のクラスは、

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"{self.__class__.__name__}(x={self.x}, y={self.y})"

    def __add__(self, other):
        self.x += other.x
        self.y += other.y

dataclassを使うと、

from dataclasses import dataclass

@dataclass
class Vector:
    x: float
    y: float

    def __add__(self, other):
        self.x += other.x
        self.y += other.y

コード数がすごい減る。

また、dataclassデコレータはデフォルトではミュータブルであるが、@dataclass(frozen=True)と書けばイミュータブルなオブジェクトとして扱うことができる。

>>> from dataclasses import dataclass
>>> @dataclass(frozen=True)
... class Vector:
...   x: float
...   y: float
...   def __add__(self, other):
...     self.x += x
...     self.y += y
...
>>> v = Vector(1.3, 1.5)
>>> v.x = 1.9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'x'

組み込み関数breakpoint

Python3.7から組み込み関数breakpoint()が追加された。Railsエンジニアにおなじみのbinding.pryみたいに実行を途中で止めて変数の中身を見れたりする。すごい便利。

a = 1.5
b = a * 4
breakpoint() # ここで止まる
print(a * b)

dictionaryの順序保持

dictionaryが順序を保持するようになった。これは地味に嬉しい。

>>> dictionary = {'a': 1, 'b':2, 'c':3, 'd':4, 'e':5}
>>> for key, value in dictionary.items():
...   print(key, value)
...
a 1
b 2
c 3
d 4
e 5