Пайтонда closureлар

Closure (closure) денда функция ва унга кириш имкони бўлган барча ташқи ўзгарувчилар назарда тутилади.

Пайтонда, кўпинча "функциянинг closureи" дейилганда, ўзи функция эмас, балки унинг ташқи ўзгарувчиларини назарда тутишади.

Фарз қилайлик, бизда outer номли функция бор, унинг ичида i ўзгарувчиси эълон қилинган ва inner ички функцияси мавжуд. Унда i га битта қўшилади. i ўзгарувчиси тўғри ишлаши учун, унга nonlocal инструкциясини қўшамиз:

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

Энди ташқи функцияни res ўзгарувчисига joyлаймиз ва уни ёйиқ қавс билан чақирамиз:

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

Оралиқда тасодифий бутун сонни чиқарувчи функция яратинг, лекин бир хил сон кетма-кет икки марта чиқмасин.