Pythonでmapオブジェクトを複数回使おうとしたら怒られた

# 該当のコード

```python
data=[(155,48),(154,43),(157,46),(165,58),(161,49),(160,51),(158,44),(175,60),(163,47),(159,43),(159,44),(163,45),(155,44),(149,46),(160,48),(168,49),(163,55),(153,47),(162,51),(160,50),(159,47),(148,42),(165,56),(158,48),(170,54),(161,44)]
bmi = lambda x:round(x[1] / ((x[0]/100) ** 2))
map_obj=map(bmi,data)

print("最小BMI:",min(map_obj),
      "最大BMI:",max(map_obj))
```

これを実行するとエラーになります。

```
Traceback (most recent call last):
  File "t.py", line 6, in <module>
    "最大BMI:",max(map_obj))
ValueError: max() arg is an empty sequence
```

# なぜか
5行目のところですでにmapオブジェクト（イテレータ）が消費されているため、メモリからなくなっている。
なので6行目ではmax関数に渡せるものがなくなりエラーになる。

# どうすべきか
listを使う


```python
data=[(155,48),(154,43),(157,46),(165,58),(161,49),(160,51),(158,44),(175,60),(163,47),(159,43),(159,44),(163,45),(155,44),(149,46),(160,48),(168,49),(163,55),(153,47),(162,51),(160,50),(159,47),(148,42),(165,56),(158,48),(170,54),(161,44)]
bmi = lambda x:round(x[1] / ((x[0]/100) ** 2))
bmi_list=list(map(bmi,data))

print("最小BMI:",min(bmi_list),
      "最大BMI:",max(bmi_list))
```

# Q:何でlist返さないの？
A:イテレータを使うほうがメモリに優しいから

listを返すとなると元のリストから加工したリストを全部メモリに保持しなくてはならない。
イテレータなら都度計算するのでメモリに優しい

# 比較してみる
for xxx in yyy のように普通のループとして使われるとメモリにどのような差があるのかを調べる。
<font color="White">999999回計算されるアイドルのBMI</font>

## リストを使う

```python

from memory_profiler import profile
import time

data = [(155, 48)] * 999999


@profile
def main():
    start_time = time.perf_counter()

    def bmi(x): round(x[1] / ((x[0]/100) ** 2))
    list_obj = list(map(bmi, data))
    for result in list_obj:
        pass
    end_time = time.perf_counter()
    elapsed_time = end_time - start_time
    print("processed time:", elapsed_time)

main()

```

## listを使わない

```python

from memory_profiler import profile
import time

data = [(155, 48)] * 999999


@profile
def main():
    start_time = time.perf_counter()

    def bmi(x): round(x[1] / ((x[0]/100) ** 2))
    map_obj = map(bmi, data)
    for result in map_obj:
        pass
    end_time = time.perf_counter()
    elapsed_time = end_time - start_time
    print("processed time:", elapsed_time)

main()


```

## 結果

### listなし

```
processed time: 239.2219612
Filename: test.py

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
     7     26.8 MiB     26.8 MiB           1   @profile
     8                                         def main():
     9     26.8 MiB      0.0 MiB           1       start_time = time.perf_counter()
    10
    11     26.8 MiB -75115.5 MiB     1999999       def bmi(x): round(x[1] / ((x[0]/100) ** 2))
    12     26.8 MiB      0.0 MiB           1       map_obj = map(bmi, data)
    13     26.8 MiB -37557.8 MiB     1000000       for result in map_obj:
    14     26.8 MiB -37557.8 MiB      999999           pass
    15     26.8 MiB     -0.1 MiB           1       end_time = time.perf_counter()
    16     26.8 MiB      0.0 MiB           1       elapsed_time = end_time - start_time
    17     26.8 MiB      0.0 MiB           1       print("processed time:", elapsed_time)
```

### listあり

```
processed time: 238.8371256
Filename: test.py

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
     7     26.8 MiB     26.8 MiB           1   @profile
     8                                         def main():
     9     26.8 MiB      0.0 MiB           1       start_time = time.perf_counter()
    10
    11     35.2 MiB -92447.4 MiB     1999999       def bmi(x): round(x[1] / ((x[0]/100) ** 2))
    12     35.2 MiB      0.0 MiB           1       list_obj = list(map(bmi, data))
    13     35.2 MiB      0.0 MiB     1000000       for result in list_obj:
    14     35.2 MiB      0.0 MiB      999999           pass
    15     35.2 MiB      0.0 MiB           1       end_time = time.perf_counter()
    16     35.2 MiB      0.0 MiB           1       elapsed_time = end_time - start_time
    17     35.2 MiB      0.0 MiB           1       print("processed time:", elapsed_time)
```

### 感想
listを使った場合のほうがMem usageが増えています。
メモリをより動かすのはlistを使ったほうなのでしょうか。
ただ速度面で差はでていないのであまり考えるだけ無駄かも。