Замыканні ў Python

Пад замыканнем (closure) маюць на ўвазе функцыю разам з усімі знешнімі зменнымі, якія ёй даступныя.

У Python часцей за ўсё, кажучы "замыканне функцыі", маюць на ўвазе не самую гэтую функцыю, а менавіта яе знешнія зменныя.

Хай у нас ёсць наступная функцыя outer, у якой аб'яўлена зменная i і унутраная функцыя inner. У ёй да i будзе дадавацца адзінка. Каб зменная i карэктна працавала, дадаем да яе інструкцыю nonlocal:

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

Цяпер давайце пакладзем знешнюю функцыю ў зменную res і выклічам яе з круглымі дужкамі:

pythonres = outer()
res() # выведзе 1

Давайце некалькі разоў выклічам res. Пасля выканання кода кожны раз лічыльнік i будзе павялічвацца на адзінку:

pythonres() # выведзе 2
res() # выведзе 3
res() # выведзе 4

Аднак тут ёсць важны нюанс - кожны выклік функцыі outer будзе павялічваць свой лічыльнік. Давайце першы выклік outer запішам у зменную res1, а другі выклік - у зменную 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

Зрабіце функцыю, якая будзе выдаваць выпадковае цэлае лік у прамежку, але так, каб два разы запар не было аднолькавых.