pythonのdataclassまとめ

# はじめに

dataclassの知見が溜まったので、書きたいと思います。

# dataclassとは

通常の場合

```python
class DataClass:
    def __init__(self, name, num):
        self.name = name
        self.num = num
        
dc = DataClass('tom',3)
print(f'私の名前は{dc.name}、IDは{dc.num}です。')
```

```console
私の名前はtom、IDは3です。
```

dataclassの場合

```python
from dataclasses import dataclass

@dataclass
class DataClass:
    name: str
    num: int
        
dc = DataClass('tom',3)
print(f'私の名前は{dc.name}、IDは{dc.num}です。')
```

```console
私の名前はtom、IDは3です。
```

dataclassの利点は、
self.name = nameなどをくり返さなくてもよく、記述量が低下し、かつ
アノテーションがついているので、どういう役割のクラスなのかがわかり、可読性が向上します。

```python
name: str
```

ただし、上記のように型の宣言を必要としています。
ただ、変数の場合は、適当でも大丈夫で、無視して数字を代入しても、エラーは起きません。

```python
@dataclass
class DataClass:
    name: str
    num: int
        
dc = DataClass(4,3)
print(f'私の名前は{dc.name}、IDは{dc.num}です。')
```

```console
私の名前は4、IDは3です。
```

# コンストラクター

```python
@dataclass
class DataClass:
    name: str = 'rebeca'
    num: int = 4
        
dc = DataClass()
print(f'私の名前は{dc.name}、IDは{dc.num}です。')
```

```console
私の名前はrebeca、IDは4です。
```

初期値を設定することも可能

## 片方だけの場合

```python
@dataclass
class DataClass:
    name: str
    num: int = 4

dc = DataClass('rebeca')
print(f'私の名前は{dc.name}、IDは{dc.num}です。')
```

```console
私の名前はrebeca、IDは4です。
```

## 特殊なコンストラクター


```python
def __post_init__(self):
```
を設定することによって、コンストラクター発動後（データ格納後）、そのデータを使って
プログラムを実行できます。

```python
@dataclass
class DataClass: 
    name: str
    num: int

    def __post_init__(self):
        print(f'私の名前は{self.name}、IDは{self.num}です。')
        
dc = DataClass('tom',3)
```

```console
私の名前はtom、IDは3です。
```

## list

```python
from dataclasses import dataclass, field
from typing import List
import numpy as np

@dataclass
class DataClass:
    name : List[List[int]] = field(default_factory=list)
    num : List[List[str]] = field(default_factory=list)
        
    def show(self, name, num):
        self.name.append(name)
        self.num.append(num)
        print('生徒の名前：',self.name)
        print('生徒のID',self.num)
        
data = DataClass()
name = ['tom','mike','jassson']
num = [1,2,3]
data.show(name, num)
```

```console
生徒の名前： [['tom', 'mike', 'jassson']]
生徒のID [[1, 2, 3]]
```

## numpy

```python
from dataclasses import dataclass, field
from typing import List
import numpy as np

@dataclass
class DataClass:
    name : np.ndarray = np.array([])
    num : np.ndarray = np.array([])
        
    def show(self, name, num):
        self.name = np.append(self.name, np.array(name))
        self.num = np.append(self.num, np.array(num))
        print('生徒の名前：',self.name)
        print('生徒のID',self.num)
        
data = DataClass()
name = ['tom','mike','jassson']
num = [1,2,3]
data.show(name, num)
```

```console
生徒の名前： ['tom' 'mike' 'jassson']
生徒のID [1. 2. 3.]
```

```python
num : np.ndarray = np.array([])
```

宣言が特殊ですね。

# 継承

```python
@dataclass
class DataClass:
    name: str = ''
    num: int = 0

class parent(DataClass):
    def __init__(self):
        super().__init__()
    
    def add(self,name):
        self.name = name
        print(f'私の名前は{self.name}、IDは{self.num}です。')
        
p = parent()
p.add('yamaneko')
```

```console
私の名前はyamaneko、IDは0です。
```

dataclassに初期値を設定する必要があります。
残りは通常の継承と同じ。