こんにちは。明月です。
この投稿はPythonのジェネレータ(Generator)に関する説明です。
ジェネレータ(Generator)という辞典的な意味は生成するという意味です。Pythonでもジェネレータ(Generator)は生成する意味ではないことではないですが、繰り返し(ループ)文法でイテレータ(iterator)パターンを実装するような機能です。
少し説明が難しくなりますが、関数を呼び出すたびに結果が違うような機能です。
# 関数生成
def example(first, last, step):
# numberの数を正義する。
number = first
# last値まで繰り返す。
while number < last:
# 現在のnumber値を返却する。
yield number
# number値をstep値ほど加算する。
number += step
# example関数を呼び出す。
data = example(1,10,1)
# コンソール出力 - dataはジェネレータタイプ
print(data)
# dataは1から9まで1ずつ増加するジェネレータ
# for를 사용해서 루프를 돌리면 10까지 데이터가 돌아가고 현재의 값이 i가 나온다.
for i in data:
# コンソール出力
print(i)
# 改行
print()
# これはrangeの値を出力した。
for i in range(1,10,1)
# コンソール出力
print(i)
上の例はジェネレータでrange関数と同じ結果が出るように実装しました。range関数も1から9まで出力して1ずつ増加します。
ジェネレータは上の例みたいに関数で使えますが、実はコンプリヘンションでよく使います。
# range関数を利用して1から9までのリストを生成する。
list1 = list(range(1,10))
# list1の値で偶数の値をリストに作成する。
listret = [x for x in list1 if x%2 == 0]
# list1の値で数の値をジェネレータに作成する。
generator = (x for x in list1 if x%2 == 0)
# 偶数リストを出力する。
for i in listret:
# コンソール出力
print(i)
# 改行
print()
# 偶数ジェネレータを出力する。
for i in generator:
# コンソール出力
print(i)
参考 - [Python] 05. コンプリヘンション(Comprehension)を使用する方法
上の例をみれば同じ結果になります。コンプリヘンションを利用してリストを作ることとジェネレータを作ることは差がないです。
そうすればジェネレータは別に意味がなさそうです。
でも、パフォーマンスに大幅差があります。
import sys;
# 確実な差異を確認するため、一万まで登録した。
list1 = list(range(1,10000))
# list1の値で偶数の値をリストに作成する。
listret = [x for x in list1 if x%2 == 0]
# list1の値で数の値をジェネレータに作成する。
generator = (x for x in list1 if x%2 == 0)
# データサイズを出力する。
print(sys.getsizeof(listret));
print(sys.getsizeof(generator));
メモリをみればリストは43,000バイトを使うしジェネレータは120バイトです。
なんでこの差が出るでしょう。
リストの場合はコンプリヘンションで計算した結果をすべて持っていることです。でも、ジェネレータの場合はデータをメモリに持っていることではなく、構造的なオブジェクトでデータを呼び出す時だけ返却するのでこの結果になりました。(構造的なオブジェクトとは値を持っていることではなく、関数のスタックを持っていることです。)
なので、一回性のデータならリストにデータを格納することではなく、ジェネレータを使うほうがパフォーマンスを上げることができます。
ジェネレータはリストによる短所もあります。
# range関数を利用して1から9までのリストを生成する。
list1 = list(range(1,10))
# list1の値で数の値をジェネレータに作成する。
generator = (x for x in list1 if x%2 == 0)
# 生成されたデータを出力する。
for i in generator:
# コンソール出力
print(i)
# 生成されたデータを出力する。
for i in generator:
# コンソール出力
print(i)
再使用ができないことです。なので結果は一回だけ出力されました。
ジェネレータはループだけ使うことではありません。
# range関数を利用して1から9までのリストを生成する。
list1 = list(range(1,10))
# 生成されたデータを出力する。
generator = (x for x in list1 if x%2 == 0)
# next関数を利用すれば一つずつ取得ができる。
# コンソール出力
print(next(generator))
# コンソール出力
print(next(generator))
# コンソール出力
print(next(generator))
# コンソール出力
print(next(generator))
# 値は総4個があるが、5回目に取得すればどんな結果になるだろう?
print(next(generator))
next関数で2,4,6,8のデータを一つずつ出力しました。8の以降はデータがないので、エラーが発生します。
ここまでPythonのジェネレータ(Generator)に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [Python] 15. クラスを継承する方法2020/06/15 18:20:07
- [Python] 14. クラスプロパティ(Property)2020/06/12 17:45:13
- [Python] 13. クラス関数(class method)とダック・タイピング、そして特殊メソッド2020/06/11 19:42:29
- [Python] 12. クラス(Class)を使う方法2020/06/10 19:33:33
- [Python] 11. デコレーター(Decorator)を使う方法2020/06/09 17:27:18
- [Python] 10. モジュールとパッケージ(import)2020/06/08 19:07:50
- [Python] 09. 例外処理する方法2020/06/05 17:11:47
- [Python] 08. ジェネレータ(Generator)2020/06/04 18:46:08
- [Python] 07. globalとnonlocal2020/06/03 20:34:49
- [Python] 06. 関数(function) - インライン関数、callbak、ラムダ(lambda)そしてクロージャ2020/06/02 20:51:22
- [Python] 05. コンプリヘンション(Comprehension)を使用する方法2020/06/01 19:38:58
- [Python] 04. 制御文(if, while, for, break, continue)とインデント2020/05/29 21:09:08
- [Python] 03. Pythonでリスト(list)とタプル(tuple)、そしてディクショナリ(dictionary)、セット(set)2020/05/27 18:49:08
- [Python] 02. データタイプ、変数宣言そしてコメントする方法2020/05/26 18:16:52
- [Python] 01. Python3をインストールする方法(Anacondaインストール)2020/05/25 19:02:44
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07