Asosiy mazmunga o'tish

14-dars: Qamrov va chaqiruv steki

4-blokO'z buyruqlaringizni yasash13–16 darslar

Bu darsdan keyin siz

  • funksiya ichidagi va tashqarisidagi bir nomdagi o’zgaruvchilarni ajratasiz
  • chaqiruv steki qanday to’planib bo’shashini tushuntirasiz
  • xato izlaganda traceback dagi chaqiruv zanjirini o’qiy olasiz

Funksiya chaqirilganda Python unga alohida joy — kadr — ajratadi. Funksiya ichida yaratilgan barcha nomlar shu kadrda yashaydi va funksiya tugaganda kadr bilan birga yo’qoladi.

kadrframe

Bitta funksiya chaqiruvi uchun ajratilgan joy: parametrlar va lokal nomlar shu yerda saqlanadi. Chaqiruv tugashi bilan kadr bo’shatiladi.

Python nomni izlaganda avval joriy kadrga qaraydi, keyin tashqi (global) joyga. Shu sababli funksiya global o’zgaruvchini o’qiy oladi, lekin unga qiymat yozsa — global emas, yangi lokal nom yaratadi.

qamrovscope

Nomning ko’rinish hududi. Lokal qamrov — funksiya ichi, global qamrov — modul darajasi.

oqish.py
soliq = 12          # global nomdef hisobla(narx):  # global soliq ni O'QIYDI — bu ishlaydi  return narx * (1 + soliq / 100)print(hisobla(1000))     # 1120.0

Funksiya boshqa funksiyani chaqirsa, kadrlar bir-birining ustiga to’planadi. Bu to’da chaqiruv steki deb ataladi va u har doim teskari tartibda bo’shaydi: oxirgi ochilgan kadr birinchi yopiladi.

chaqiruv stekicall stack

Bajarilayotgan chaqiruvlar to’dasi. Xato yuz berganda traceback aynan shu stekni ko’rsatadi.

Bu tuzilma yangi emas: CF 9-darsda ko’rgan protsessor stekining o’zi. Python darajasida u kadrlarni saqlaydi, apparat darajasida esa qaytish manzillarini.

Xato chiqqanda Python butun stekni chop etadi: eng tashqi chaqiruvdan eng ichkarigacha. Shuning uchun traceback pastdan yuqoriga o’qiladi — pastda xato joyi, yuqorida u qanday chaqirilgani. Bunga 17-darsda alohida to’xtalamiz.

Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.

Bashorat qiling
x = 10def ozgartir():  x = 99  print("ichkarida:", x)ozgartir()print("tashqarida:", x)
Javobni ko'rish
ichkarida: 99
tashqarida: 10

Funksiya ichidagi x = 99 yangi lokal nom yaratdi. Global x hech qachon tegilmadi — funksiya tugagach lokal x yo'qoldi.

Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.

Bashorat qiling
def ichki():  return "ichki tugadi"def tashqi():  natija = ichki()  return "tashqi: " + natijaprint(tashqi())
Javobni ko'rish
tashqi: ichki tugadi

Stek uch kadrga yetdi: modul, tashqi, ichki. Keyin teskari tartibda bo'shadi — ichki birinchi qaytdi.

Ikki variantni ham qadamlab chiqing. «Qamrov» variantining uchinchi qadami darsning markazi: aynan o’sha joyda ikkinchi x paydo bo’ladi.

Stek kuzatuvchi

Variantni tanlab qadamlang: kadrlar to'planadi va bo'shaydi. Klaviatura: → keyingi qadam.

Bu simulyatorda chaqiruv steki qadamlab to'planadi va bo'shaydi. Har kadr o'z o'zgaruvchilarini ko'rsatadi, shuning uchun bir xil nomdagi ikki o'zgaruvchining nega bir-birini buzmasligi ko'rinadi.

JavaScript'siz mashq: salomlash("Aziza") chaqirilganda stek uch kadrga yetadi — modul, salomlash, tayyorla. Ular qaysi tartibda yopiladi? Javob: teskari tartibda, oxirgi ochilgani birinchi yopiladi.

    Chaqiruv steki (yuqorisi — joriy)

    Terminal

    Bu kod ataylab buzuq — xatoni toping

    Buzuq kod
    def hisobla():  jami = jami + 100  return jamijami = 0print(hisobla())

    Python shunday javob beradi:

    Traceback (most recent call last):
    File "hisob.py", line 5, in <module>
      print(hisobla())
    File "hisob.py", line 2, in hisobla
      jami = jami + 100
    UnboundLocalError: cannot access local variable 'jami' where it is not associated with a value
    Sababi va tuzatish

    Funksiya ichida jami ga qiymat yozilgani uchun Python uni LOKAL nom deb hisobladi. O'ng tomondagi jami esa hali yaratilmagan.

    Python funksiyani bajarishdan oldin butun tanasini ko’rib chiqadi: jami = ... uchraydi, demak jami lokal. Global jami esa endi ko’rinmaydi — hatto o’qish uchun ham.

    Ikki yechim bor va birinchisi deyarli har doim to’g’ri:

    tuzatilgan.py
    def hisobla(jami):  return jami + 100jami = 0print(hisobla(jami))     # 100

    Ikkinchi yo’l — global jami deb e’lon qilish. U ishlaydi, lekin funksiyani tashqi holatga bog’lab qo’yadi va shu sababli undan qochish kerak: parametr orqali berish har doim aniqroq.

    1Kadr nima va qachon yo'qoladi?

    Javobni ko'rish

    Bitta funksiya chaqiruvi uchun ajratilgan joy. Funksiya tugaganda kadr va undagi barcha lokal nomlar bo’shatiladi.

    2Funksiya global o'zgaruvchini o'qiy oladimi, o'zgartira oladimi?

    Javobni ko'rish

    O’qiy oladi. Unga qiymat yozsa esa yangi lokal nom yaratadi — global tegilmaydi.

    3Ikki funksiyada bir xil nomdagi parametr bo'lsa, ular to'qnashadimi?

    Javobni ko'rish

    Yo’q. Har chaqiruv o’z kadrida yashaydi, demak ular butunlay boshqa nomlar.

    4Chaqiruv steki qanday tartibda bo'shaydi?

    Javobni ko'rish

    Teskari tartibda: oxirgi ochilgan kadr birinchi yopiladi. Shu sababli stekni «oxirgi kirgan — birinchi chiqadi» qoidasi boshqaradi.

    5UnboundLocalError nimani bildiradi?

    Javobni ko'rish

    Funksiya ichida o’zgaruvchiga qiymat yozilgani uchun u lokal deb hisoblangan, lekin qiymat berilishidan oldin o’qilgan. Yechim: qiymatni parametr orqali berish.

    Topshiriq — darajangizni tanlang

    Asos · 5–7-sinf — Vizual va aniq ko'rsatmali

    Uchta funksiya yozing: salomlash(ism), xayrlashish(ism) va suhbat(ism). Uchinchisi birinchi ikkisini chaqirsin. Daftaringizga chaqiruv stekini qo’lda chizib chiqing: qaysi kadr qachon ochiladi va qachon yopiladi.

    Mustahkam · 8–9-sinf — Matnli masala, o'zingiz tuzasiz

    UnboundLocalError ni ataylab chaqirib ko’ring, keyin uni ikki xil tuzatib qo’ying: parametr orqali va global orqali. Ikki variantni solishtirib, qaysi biri afzalligini izohda yozing — kamida ikki sabab keltiring.

    Chuqur · 10–11-sinf — Algoritmik, chegara holatlari bilan

    Bir-birini chaqiradigan uch funksiya yozing va ichkarisida ataylab xato chiqaring (masalan nolga bo’lish). Chiqqan traceback ni qatorma-qator izohlang: qaysi qator qaysi kadrga tegishli. Keyin savolga javob bering: traceback nega pastdan yuqoriga o’qiladi va bu tartib nimani osonlashtiradi?

    Darsni belgilash uchun JavaScript kerak. Bu progressni saqlash uchun ishlatiladi — darslikning o'zi JavaScript'siz ham to'liq o'qiladi.