Pythonにおけるクロージャー

クロージャー(closure)とは、 関数と、その関数がアクセス可能なすべての 外部変数をまとめたものを意味します。

Pythonでは、「関数のクロージャー」と言う場合、 多くの場合、その関数自体ではなく、 まさにその外部変数を指しています。

ここに、変数iを宣言し、 内部関数innerを持つ関数outerがあるとします。 内部関数内ではiに1が加算されます。 変数iが正しく動作するために、 キーワードnonlocalを追加します:

pythondef outer():
  i = 0
  def inner():
    nonlocal i
    i += 1
    print(i)

  return inner

では、外側の関数を変数resに代入し、 括弧を付けて呼び出してみましょう:

pythonres = outer()
res() # 1を出力

resを数回呼び出してみましょう。 コードを実行するたびに、カウンターiが 1ずつ増加します:

pythonres() # 2を出力
res() # 3を出力
res() # 4を出力

しかし、ここには重要なニュアンスがあります。 関数outerを呼び出すたびに、それぞれ独自のカウンターが 増加します。最初のouterの呼び出しを 変数res1に、2回目の呼び出しを 変数res2に代入してみましょう。 次に、それらを順番にコンソールに出力します:

pythonres1 = outer()
res1() # 1を出力
res1() # 2を出力
res1() # 3を出力

res2 = outer()
res2() # 1を出力
res2() # 2を出力
res2() # 3を出力
Задание 1

次のコードがあります:

pythondef outer():
  i = 10

  def inner():
    nonlocal i
    i -= 2
    print(i)
  return inner

res1 = outer()
res1()
res1()

res2 = outer()
res2()
res2()
res2()

コンソールに何が出力されるか答えてください。

Задание 2

呼び出されるたびに次のフィボナッチ数を返す 関数を作成してください。

Задание 3

ある範囲内でランダムな整数を生成する関数を作成してください。 ただし、連続して同じ数が2回出ないようにしてください。