python3.7の新機能を使ってみる(dataclass, breakpoint)

## 1.はじめに
python3.7で増えた機能の主要なところを実際に使って見たまとめ．

全体についてはこの辺が良い．->[Python3.7の新機能](https://qiita.com/ksato9700/items/35a0bdc04693b3b09757)

## 2.environment
- python 3.7.0(pyenvで入れる)

## 3.install

pyenvを更新したら3.7.0もインストール可能なリストに出てくる．

```shell
$ git clone git://github.com/yyuu/pyenv-update.git ~/.pyenv/plugins/pyenv-update
$ pyenv update
```

```shell
$ pyenv install -list
Available versions:
  3.7.0
  3.7-dev
  3.8-dev
```

## 4.dataclasses
### 4.1.dataclassの何が嬉しいか
dataclassは自分用のデータ型の定義の新しいやり方．
`@dataclass`でデコレートするようにして使う．
そうすると，`@dataclass(order=True)`というように引数のbool値を変えるだけで，そのクラスの特殊メソッドを生やすことができる．
具体的には以下のような感じ．

```python
from dataclasses import dataclass
from dataclasses import field
from typing import List

@dataclass(init=True, order=True)
class HyperParams():
    init_val: float = field(default_factory=float, compare=True)
    iter_num: int = field(default_factory=int, compare=True)
    tol: float = field(default_factory=float, compare=True)
    logging: List[int] = field(default_factory=list, compare=False)

```

`order=True`とすると，比較演算子が使えるようになる．
`field`の`compare=True`で比較演算子を用いた時のその変数を比較対象にするか否かを選べる．
`logging`は`compare=False`で比較対象から抜いている．

```python
params1 = HyperParams(10, 20, 30, 10)
params2 = HyperParams(500, 200, 300, 100)
params1 <= params2
# True
```

### 4.2.dataclassを使わずに書くと
ちなみにこの`order=True`で`__le__`の特殊メソッドを生やしていて，これによって比較演算子`<=`が使えるようになる．dataclassを使わずに書くと以下のようになる．

```python
class HyperParams_oldstyle(object):
    def __init__(self, init_val: float, iter_num: int, tol: float, logging: list):
        self.init_val = init_val
        self.iter_num = iter_num
        self.tol = tol
        self.logging = logging

    def __le__(self, other):
        if other.__class__ is self.__class__:
            return (self.init_val, self.iter_num, self.tol) <= (other.init_val, other.iter_num, other.tol)

params_old1 = HyperParams_oldstyle(10, 20, 30, 10)
params_old2 = HyperParams_oldstyle(500, 200, 300, 100)
params_old1 <= params_old2
# True
```

こう比べると確かに引数の`True, False`だけで色々いじれるdataclass便利そうと思える．

### 4.3.その他の機能
あと`frozen=True`で変更不可になる．これも時々使いそう．

```python
@dataclass(frozen=True)
```

他の機能についてはこの辺が参考になりそう．
[Python3.7からは「Data Classes」がクラス定義のスタンダードになるかもしれない](https://qiita.com/tag1216/items/13b032348c893667862a)


### 4.4.参考
- [30.6. dataclasses — Data Classes — Python 3.7.0 documentation](https://docs.python.org/3/library/dataclasses.html)

- [PEP 557 -- Data Classes | Python.org](https://www.python.org/dev/peps/pep-0557/#abstract)


## 5.breakpoint
### 5.1.breakpointの何が嬉しいか
コードの途中でpbdモードに入る．
built-inに入っているので，わざわざ`pbd`をimportしなくてもよくなった．

`for`文の途中でも入れるので1ステップずつ挙動を確認したいときとかに便利そう．

```python
i_list = []
for i in range(10):
    i_list.append(i)
    breakpoint()
```

```python
>>> i_list = []
>>> for i in range(10):
...     i_list.append(i)
...     breakpoint()
...
> <stdin>(1)<module>()
(Pdb) i_list
[0]
(Pdb) continue
# continueでまたbreakpoint()から再度実行．
> <stdin>(1)<module>()
(Pdb) i_list
[0, 1]
(Pdb) continue
> <stdin>(1)<module>()
(Pdb) i_list
[0, 1, 2]
```

### 5.2.参考
- [PEP 553 -- Built-in breakpoint() | Python.org](https://www.python.org/dev/peps/pep-0553/)

- [Python 3.7’s new builtin breakpoint — a quick tour – Hacker Noon](https://hackernoon.com/python-3-7s-new-builtin-breakpoint-a-quick-tour-4f1aebc444c)
  - コマンドラインからの実行時にbreakpointのskipもできるようだ．