関数とジェネレータの区別
このステップでは、Python の通常の関数とジェネレータの主要な違いを学びます。この違いを理解することは、特に大規模なデータセットや無限シーケンスを扱う場合に、効率的でメモリにやさしいコードを書くために重要です。
関数:
関数は、特定のタスクを実行するコードブロックです。関数が呼び出されると、そのコードが実行され、計算が行われ、値が返されます(明示的な return
文がない場合は None
が返されます)。関数の状態は呼び出し間で保持されません。
ジェネレータ:
ジェネレータは、return
ではなく yield
キーワードを使用する特殊な関数です。ジェネレータが呼び出されると、イテレータオブジェクトが返されます。イテレータから値を要求するたびに、ジェネレータは yield
文に遭遇するまで実行されます。その後、ジェネレータは一時停止し、状態を保存し、値を生成します。次に値が要求されると、ジェネレータは中断したところから再開します。
これを例で説明しましょう。まず、VS Code エディタを使用して、~/project
ディレクトリに function_vs_generator.py
という名前のファイルを作成します。
## ~/project/function_vs_generator.py
## 通常の関数
def square_numbers_function(numbers):
result = []
for number in numbers:
result.append(number * number)
return result
## ジェネレータ関数
def square_numbers_generator(numbers):
for number in numbers:
yield number * number
## 使い方の例
numbers = [1, 2, 3, 4, 5]
## 関数を使用する
function_result = square_numbers_function(numbers)
print("Function Result:", function_result)
## ジェネレータを使用する
generator_result = square_numbers_generator(numbers)
print("Generator Result:", list(generator_result)) ## 出力のためにジェネレータをリストに変換する
次に、Python スクリプトを実行します。
python ~/project/function_vs_generator.py
以下の出力が表示されるはずです。
Function Result: [1, 4, 9, 16, 25]
Generator Result: [1, 4, 9, 16, 25]
関数とジェネレータの両方が同じ結果を生成します。しかし、重要な違いは、それらがこれを達成する方法にあります。関数はすべての平方を計算し、リストに格納してから返します。一方、ジェネレータは要求されたときにのみ、平方を 1 つずつ生成します。
この違いをさらに説明するために、返されるオブジェクトの型を出力するようにスクリプトを変更しましょう。
## ~/project/function_vs_generator.py
## 通常の関数
def square_numbers_function(numbers):
result = []
for number in numbers:
result.append(number * number)
return result
## ジェネレータ関数
def square_numbers_generator(numbers):
for number in numbers:
yield number * number
## 使い方の例
numbers = [1, 2, 3, 4, 5]
## 関数を使用する
function_result = square_numbers_function(numbers)
print("Function Result Type:", type(function_result))
## ジェネレータを使用する
generator_result = square_numbers_generator(numbers)
print("Generator Result Type:", type(generator_result))
再度スクリプトを実行します。
python ~/project/function_vs_generator.py
出力は次のようになります。
Function Result Type: <class 'list'>
Generator Result Type: <class 'generator'>
これは、関数が list
を返し、ジェネレータが generator
オブジェクトを返すことを明確に示しています。ジェネレータは、一度にすべての値をメモリに格納しないため、メモリ効率が良いです。値は必要に応じて生成されます。