Python'dagi nonlocal keyword'i: mutaxassislarimiz tushuntiradi
Nested function'larda scope qoidalari tufayli o'zgaruvchilarni yangilash buziladi. Python'dagi nonlocal keyword'i nima ekanini, undan qachon to'g'ri foydalanishni va uning keng tarqalgan qo'llanishlarini bilib oling.
Muallif: William Imoh
Python o'zgaruvchilarni aniq scope qoidalari asosida boshqaradi. Ko'pincha lokal va global o'zgaruvchilar yetarli bo'ladi. Ammo nested function'lar bilan ishlaganingizda vaziyat o'zgaradi. Sukut bo'yicha ichki funksiyalar tashqi funksiyaning o'zgaruvchilarini o'zgartira olmaydi. Buning sababi shundaki, Python nomlarni LEGB scope qoidalari (Local, Enclosing, Global, Built-in) asosida aniqlaydi, nested function'lar esa "Enclosing" qatlamida joylashadi.
Aynan shu yerda Python'ning nonlocal keyword'i muhim ahamiyat kasb etadi. nonlocal keyword'i ichki funksiyaga o'zini o'rab turgan funksiyada aniqlangan o'zgaruvchiga murojaat qilish va uni yangilash imkonini beradi. Shu sababli u closure'lar, decorator'lar va callback'larga asoslangan mantiq uchun foydali.
Keling, ushbu qo'llanma yordamida Python'da nonlocal qanday ishlashini, undan qachon foydalanish kerakligini va u qanday qilib tozaroq hamda oldindan bashorat qilish oson bo'lgan kod yozishga yordam berishini tushunib olaylik.
Python'dagi nonlocal keyword'i nima?
nonlocal keyword'i Python'ga ichki funksiya ichida ishlatilgan o'zgaruvchi ichki funksiyaning local scope'iga emas, balki eng yaqin o'rab turgan funksiyaga tegishli ekanini bildiradi. nonlocal faqat shu nom allaqachon mavjud bo'lgan eng yaqin o'rab turgan funksiya scope'idagi o'zgaruvchiga ishora qiladi. U istalgan tashqi scope'ga "sakrab o'ta" olmaydi va module darajasidagi o'zgaruvchilar uchun ishlamaydi.
Bu ichki funksiyaga yangi lokal o'zgaruvchi yaratish o'rniga mavjud o'zgaruvchidan qayta foydalanish va uni yangilash imkonini beradi.
nonlocal yordamida global o'zgaruvchilardan foydalanmasdan yoki qiymatlarni return statement'lar orqali qaytarib uzatishga majbur bo'lmasdan, nested function'lar ichida state'ni ulashishingiz va yangilashingiz mumkin.
nonlocal'ni tushunish uchun Python'ning nomlarni qidirish qoidalari bilan qisqacha tanishib chiqishingiz kerak. Python LEGB scope modelidan foydalanadi va nonlocal aynan shu model doirasida ishlaydi.
Python'ning LEGB scope modeli va unda nonlocal qayerda turadi

LEGB — Local, Enclosing, Global, Built-in so'zlarining qisqartmasi. Bu Python funksiya ichidagi nom qaysi o'zgaruvchiga ishora qilishini aniqlash uchun foydalanadigan qoida. Bu nested function'larda muhim, chunki nonlocal aynan Enclosing scope bilan ishlaydi.
Python funksiya ichida biror nomni ko'rganda, uni quyidagi tartibda qidiradi va birinchi topilgan moslikdan foydalanadi:
-
Local (L): Joriy funksiyada yaratilgan o'zgaruvchilar (qiymat berish amallari uchun sukut bo'yicha shu scope ishlatiladi).
-
Enclosing (E): Nested function'lardan foydalanilganda eng yaqin o'rab turgan funksiyadagi o'zgaruvchilar. nonlocal keyword'i aynan shu yerda qo'llaniladi.
-
Global (G): Module darajasidagi o'zgaruvchilar. Global o'zgaruvchilarni o'zgartirish uchun global statement'idan foydalaning. Nonlocal bu yerda ishlamaydi.
-
Built-in (B): Python'ning
print,lenvarangekabi built-inidentifier'lari.
Quyida Python bu scope'larni qanday ketma-ket ko'rib chiqishini ko'rsatadigan qisqa misol keltirilgan:
x = "global value"
def outer():
x = "enclosing value"
def inner():
x = "local value"
print(x)
inner()
outer()
nonlocal statement'i enclosing scope darajasida ishlaydi. Ichki funksiya ichida ishlatilganda u Python'ga yangi lokal o'zgaruvchi yaratish o'rniga eng yaqin o'rab turgan funksiyadagi o'zgaruvchiga murojaat qilishni bildiradi.
def outer():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
Bu yerda count tashqi funksiyada aniqlangan, ichki funksiya ichida unga murojaat qilinadi va global scope'ga tegilmagan holda u to'g'ri yangilanadi. Agar Python o'zgaruvchini birorta ham enclosing scope'da topa olmasa, jimgina yangi o'zgaruvchi yaratish o'rniga SyntaxError chiqaradi.
nonlocal yangi lokal o'zgaruvchi yaratmasdan qanday qilib yangilash imkonini beradi
Sukut bo'yicha funksiya ichida biror nomga qiymat berganingizda, Python o'zining nomlarni qidirish qoidalariga ko'ra uni lokal o'zgaruvchi deb hisoblaydi. Tashqi funksiyada xuddi shu nomli o'zgaruvchi mavjud bo'lsa ham shunday bo'ladi. Nested function'larda bu ko'pincha muammo tug'diradi: siz tashqi o'zgaruvchini o'qiy olasiz, lekin uni yangilashga urinishingiz bilanoq (masalan, value += 5), Python sizni yangi lokal o'zgaruvchini nazarda tutyapti deb hisoblaydi.
nonlocal keyword'i buni o'zgartiradi. U Python'ga eng yaqin o'rab turgan funksiyadagi o'zgaruvchidan foydalanishni bildiradi, shuning uchun yangilashlar yangi lokal o'zgaruvchi yaratish o'rniga mavjud qiymatni o'zgartiradi.
def outer(): value = 10 def inner(): nonlocal value value += 5 inner() print(value) # 15 outer()
Agar bu yerda nonlocal'ni olib tashlasangiz, Python xato chiqaradi, chunki u value'ni inner() ichidagi lokal o'zgaruvchi deb hisoblaydi, lekin unga lokal qiymat berilishidan oldin murojaat qilinadi.
Bu xatti-harakat state chaqiruvlar orasida saqlanib qolishi kerak bo'lgan nested function'larda, masalan, counter'lar yoki boshqa funksiyalarni qaytaradigan funksiyalarda ayniqsa foydali. Keraksiz lokal o'zgaruvchilar yaratilishining oldini olish orqali nonlocal o'zgaruvchilarni yangilashni oldindan bashorat qilinadigan va Python'ning scope qoidalariga mos holda saqlaydi.
Python'da nonlocal'ni qo'llash
nonlocal keyword'i faqat nested function'lar ichida ishlaydi. Boshqacha aytganda, undan faqat tashqi funksiya ichida aniqlangan ichki funksiya bo'lgandagina foydalanishingiz mumkin. U ichki funksiyani enclosing scope'dagi o'zgaruvchi bilan bog'laydi, shuning uchun siz o'sha o'zgaruvchini yangi lokal o'zgaruvchi yaratmasdan yangilay olasiz.
Asosiy sintaksis va xatti-harakat
nonlocal o'zgaruvchini eng yaqin o'rab turgan funksiyadan kelgan deb belgilaydi, shuning uchun qiymat berish amallari yangi lokal o'zgaruvchi yaratish o'rniga o'sha o'zgaruvchining o'zini yangilaydi.
def outer():
x = 10 # variable in enclosing scope
def inner():
nonlocal x
x = x + 5 # updates the same x, not a new local one
return x
result = inner()
print("Inner returned:", result)
print("Outer sees:", x)
outer()
Bu yerda nima sodir bo'ladi:
-
xtashqi funksiyada boshlanadi. -
inner()nonlocal x'ni e'lon qiladi, shuning uchun Python eng yaqin enclosing scope'dan foydalanadi. -
Yangilangan qiymat ham ichki, ham tashqi funksiyada ko'rinadi.
Agar nonlocal x'ni olib tashlab, baribir x = x + 5 deb qiymat bersangiz, Python x nomli yangi lokal o'zgaruvchi yaratishga urinadi va odatda xatoga duch kelasiz, chunki lokal x'ga qiymat berilishidan oldin murojaat qilinadi.
def outer():
x = 10
def inner():
x = x + 5
return x
inner()
outer()
Python chiqaradigan xato:
UnboundLocalError: local variable 'x' referenced before assignment
Nega bu xato yuzaga keladi?
Python'da funksiya ichidagi har qanday qiymat berish amali sukut bo'yicha o'sha o'zgaruvchini lokal qiladi. Shu sababli x tashqi funksiyada mavjud bo'lsa ham, Python inner() ichidagi x'ni yangi lokal o'zgaruvchi deb hisoblaydi. O'ng tomondagi ifoda x'ni o'qishga uringanda, o'sha lokal o'zgaruvchi hali mavjud bo'lmaydi — shuning uchun Python xato chiqaradi.
nonlocal buni qanday tuzatadi
nonlocal x'ni e'lon qilish Python'ga yangi lokal o'zgaruvchi yaratish o'rniga o'rab turgan funksiyadagi o'zgaruvchidan foydalanishni bildiradi. Bu yangilashning kutilganidek ishlashiga imkon beradi.
Closure'lar bilan ishlash

Closure qaytarilgan funksiya tashqi funksiya ishini tugatganidan keyin ham o'zini o'rab turgan funksiyadagi o'zgaruvchilarni eslab qolganda yuzaga keladi. Bu nonlocal foydali bo'ladigan keng tarqalgan holatlardan biri.
nonlocal'dan foydalanadigan counter funksiyasi misoli
def make_counter():
count = 0 # defined in the enclosing function
def increment():
nonlocal count
count += 1
return count
return increment
Bu misolda scope qanday ishlaydi
-
countmake_counter()ichida yaratiladi, shuning uchun u enclosing scope'ga tegishli. -
increment()qaytariladi vamake_counter()ishini tugatganidan keyin ham mavjud bo'lib qoladi. -
increment()count'ga qiymat bergani uchun Python odatdacount'ni lokal o'zgaruvchi deb hisoblagan bo'lardi. -
nonlocal count'ni e'lon qilish Python'ga yangi lokal o'zgaruvchi yaratish o'rniga o'rab turgan funksiyadagicount'dan qayta foydalanishni bildiradi.
Closure'dan foydalanish
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
make_counter() allaqachon qiymat qaytargan bo'lsa ham, har bir chaqiruv o'sha bitta count qiymatini yangilaydi. Bu ishlaydi, chunki closure enclosing scope'ni saqlab qoladi, nonlocal esa o'sha saqlangan o'zgaruvchini yangilash imkonini beradi.
Nega bu yerda nonlocal zarur
nonlocal bo'lmasa, count += 1 qiymat berish amali increment() ichida yangi lokal o'zgaruvchi yaratib, counter'ni buzadi va xato chiqaradi. nonlocal scope'lar orasidagi bog'liqlikni aniq ko'rsatadi va closure'lar ichida state'ni xavfsiz yangilash imkonini beradi.
Amaliy xulosa: Nested mantiqda global o'zgaruvchidan foydalanmasdan va o'zgaruvchilarni har safar uzatib yurmasdan umumiy state kerak bo'lganda nonlocal'dan foydalaning. U state'ni o'zi tegishli bo'lgan funksiyaga yaqin saqlaydi, bu esa kodingizni qo'llab-quvvatlashni osonlashtiradi.
nonlocal'dan foydalanishdagi keng tarqalgan xatolar
nonlocal statement'i oddiy, lekin scope bilan bog'liq xatolar tez-tez uchraydi. Bu xatolar odatda shuning uchun yuzaga keladiki, Python funksiya ichidagi qiymat berish amallarini, agar siz to'g'ri scope'ni aniq ko'rsatmasangiz, yangi lokal o'zgaruvchi yaratish deb hisoblaydi.
Bundan tashqari, nonlocal bilan bog'liq ko'plab xatolar Python funksiya tanasini compile qilayotganda (funksiya amalda ishga tushishidan oldin) aniqlanadi, chunki scope erta aniqlanadi.
Enclosing o'zgaruvchisiz nonlocal'dan foydalanish
nonlocal faqat o'zgaruvchi o'rab turgan funksiyada (enclosing scope'da) allaqachon mavjud bo'lgandagina ishlaydi. Agar nom eng yaqin enclosing scope'da mavjud bo'lmasa, Python compile vaqtida xato xabarini chiqaradi.
def outer():
def inner():
nonlocal x # x does not exist in any enclosing function scope
x = 1
inner()
outer()
Odatiy xato xabari:
SyntaxError: no binding for nonlocal 'x' found
Tuzatish: Avval o'zgaruvchini ota funksiyada aniqlang.
def outer():
x = 0 # defined in enclosing scope
def inner():
nonlocal x
x += 1
inner()
print(x)
outer()
Bu nonlocal x aniqlanmagan nomga emas, balki enclosing scope'dagi haqiqiy o'zgaruvchiga ishora qilishini ta'minlaydi.
Global o'zgaruvchilarni beixtiyor o'zgartirishga urinish
Keng tarqalgan chalkashliklardan biri — nonlocal global scope bilan ishlaydi deb kutish. Unday emas. nonlocal o'z dizayniga ko'ra global emas. U faqat tashqi funksiya scope'laridagi o'zgaruvchilarni nishonga oladi. Agar o'zgaruvchi module darajasida joylashgan bo'lsa, global o'zgaruvchilarni o'zgartirish uchun global statement'idan foydalaning.
x = 10 # global one (module level)
def outer():
def inner():
nonlocal x # ❌ x is global, not in an enclosing function
x += 1
inner()
outer()
Bu ishlamaydi, chunki x'ni saqlaydigan enclosing funksiya scope'i yo'q.
Global uchun to'g'ri yondashuv:
x = 10
def update():
global x
x += 1
update()
print(x) # 11
Amaliy maslahat__: Agar encapsulate qilingan kod istasangiz, global o'zgaruvchilardan qoching. Ayniqsa counter'lar va state uchun nonlocal ishlatilgan o'rab turgan funksiyani afzal ko'ring.
Chuqur nested tuzilmalarda nonlocal'dan tushunarsiz tarzda foydalanish
Bir nechta nested function'lar bo'lganda nonlocal har doim shu nomli eng yaqin enclosing o'zgaruvchini nishonga oladi. Bir nechta tashqi scope'larda bir xil nomli o'zgaruvchi bo'lsa, bu chalkash bo'lib qolishi mumkin.
def outer():
x = "outer current value"
def middle():
x = "middle current value"
def inner():
nonlocal x # links to middle's x (nearest enclosing scope)
x = "inner modified value"
inner()
print("middle:", x)
middle()
print("outer:", x)
outer()
Natija:
middle: inner modified value
outer: outer current value
Bu to'g'ri xatti-harakat, lekin real source code'da uni noto'g'ri tushunish oson.
Buni aniqroq qiling:
-
Chuqur nested mantiq bo'lganda noyob o'zgaruvchi nomlaridan foydalaning.
-
Iloji boricha nesting'ni sayoz saqlang.
-
Agar bu o'qilishni yaxshilasa, ayniqsa o'zgaruvchilarni uzatish data flow'ni ravshan qilsa, o'zgaruvchilarni argument sifatida uzatish yoki qiymatlarni qaytarishni ko'rib chiqing.
Tezkor checklist (scope bug'laridan qochish uchun)
-
nonlocal'dan faqat enclosing scope'da mavjud bo'lgan, nested function'lar ichidagi o'zgaruvchilar uchun foydalaning. -
Global scope qiymatlari uchun
nonlocal'dan foydalanmang; global statement'ini faqat kerak bo'lgandagina ishlating. -
Bir nechta nested function'larda
nonlocalsiz "nazarda tutgan" yuqoriroq scope'ga emas, eng yaqin enclosing scope'ga bog'lanishini yodda tuting. -
Turli scope'larda bir xil nom ishlatilishiga e'tibor bering. "Nega u yangilanmadi?" degan bug'larning aksariyati aynan shundan kelib chiqadi.
Python'da nonlocal va global: farqlarni tushunish

nonlocal ham, global ham funksiyaga o'zining local scope'idan tashqarida aniqlangan o'zgaruvchilarni o'zgartirish imkonini beradi, lekin ular Python'ning scope tizimining butunlay turli darajalarida ishlaydi. Asosiy farq har bir keyword qanchalik uzoqqa yeta olishi va qaysi scope'ni o'zgartirishga ruxsat berilganida.
Noto'g'risini tanlash data flow'ning tushunarsiz bo'lishiga va debug qilish qiyin bo'lgan kodga olib kelishi mumkin.
Python'da nonlocal
nonlocal keyword'i nested function'lar ichida o'rab turgan funksiya scope'ida aniqlangan o'zgaruvchilarni yangilash uchun ishlatiladi. U ichki funksiyaga yangi lokal o'zgaruvchi yaratish o'rniga mavjud o'zgaruvchidan qayta foydalanish va uni o'zgartirish imkonini beradi. Bu state'ni module darajasida ochib qo'ymasdan, funksiya ichida lokal saqlaydi.
Qachon nonlocal to'g'ri tanlov bo'ladi?
nonlocal'dan quyidagi hollarda foydalaning:
-
Siz nested function'lar bilan ishlayotgan bo'lsangiz.
-
Funksiya chaqiruvlar orasida state'ni eslab qolishi yoki yangilashi kerak bo'lsa.
-
State o'rab turgan funksiyaning ichida private bo'lib qolishi kerak bo'lsa.
Misol: counter yordamida state'ni lokal saqlash
def make_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
Nega bu mos keladi:
-
countglobal scope'da emas, o'rab turgan funksiyada joylashgan. -
Qaytarilgan funksiya har bir chaqiruvda o'sha bitta qiymatni yangilaydi.
-
State encapsulate qilingan holda qoladi va uni tushunish oson.
Bu pattern counter'lar, closure'lar va function factory'larda keng tarqalgan.
Python'da global
global keyword'i funksiyaga module darajasida aniqlangan o'zgaruvchilarni o'zgartirish imkonini beradi. nonlocal'dan farqli o'laroq, u nested function'larni talab qilmaydi va butun faylga ta'sir qiladi.
Qachon global o'rinli?
global'dan quyidagi hollarda foydalaning:
-
O'zgaruvchi ilovaning umumiy state'ini ifodalasa.
-
Qiymatga bir nechta funksiyalar bo'ylab murojaat qilish yoki uni yangilash kerak bo'lsa.
-
O'zgaruvchi mantiqan bitta funksiyaga emas, module'ga tegishli bo'lsa.
Misol: module darajasidagi o'zgaruvchini yangilash
total_requests = 0
def track_request():
global total_requests
total_requests += 1
Nega bu mos keladi:
-
O'zgaruvchi ilovaning global ma'lumotlarini ifodalaydi.
-
Bir nechta funksiyalarga unga murojaat kerak bo'lishi mumkin.
-
State module darajasida ataylab ulashiladi.
Bu konfiguratsiya flag'lari, counter'lar yoki butun muhitga oid qiymatlar uchun keng tarqalgan.
nonlocal va global: taqqoslash jadvali
Quyidagi jadval nonlocal va global'ni yonma-yon taqqoslaydi:
| Jihat | nonlocal |
global |
|---|---|---|
| Scope qamrovi | O'rab turgan funksiya scope'i | Module darajasidagi (global) scope |
| Nested function'larni talab qiladimi | Ha | Yo'q |
| State'ni lokal saqlaydimi | Ha | Yo'q |
| Butun module'ga ta'sir qiladimi | Yo'q | Ha |
| Eng mos keladi | Closure'lar, counter'lar, qaytariladigan funksiyalar | Module'ning umumiy state'i |
| O'qilishga ta'siri | Yuqori aniqlik | Aniqlikni pasaytirishi mumkin |
| Testlashga ta'siri | Ajratib olish osonroq | Mock qilish qiyinroq |
| Side effect xavfi | Past | Yuqoriroq |
nonlocal'ning amaliy qo'llanishlari
nonlocal keyword'i state saqlanib qolishi kerak bo'lgan, lekin global scope'ga chiqib ketmasligi lozim bo'lgan kichik, aniq maqsadli dizaynlarda eng qimmatli. Quyida nonlocal aniqlik, xavfsizlik va qo'llab-quvvatlashni qachon yaxshilashini ko'rsatadigan keng tarqalgan, real hayotdagi qo'llanishlar keltirilgan.
Nested function'lar ichida counter'lar yaratish
Counter'lar nonlocal uchun tabiiy mos keladi, chunki ular state chaqiruvlar orasida saqlanib qolishini va shu bilan birga funksiya ichida private bo'lib qolishini talab qiladi.
def visit_counter():
visits = 0
def count():
nonlocal visits
visits += 1
return visits
return count
Bu yerda nima sodir bo'lyapti
-
visitstashqi funksiyada yaratiladi. -
count()bir necha marta ishga tushadi vavisits'ni yangilashi kerak. -
nonlocal visitsPython'ga yangi o'zgaruvchi yaratish o'rniga tashqi o'zgaruvchidan qayta foydalanishni bildiradi. -
count()'ning har bir chaqiruvi o'sha bittavisitsqiymatini oshiradi.
Bu global o'zgaruvchilardan foydalanmasdan counter'lar yaratishning toza usuli.
Oddiy memoization pattern'larini yaratish
Memoization bir xil ishni takrorlamaslik uchun natijalarni saqlab qo'yadi. nonlocal bilan yozilgan closure'lar buni amalga oshirishning yengil usuli.
def memoized_square():
cache = {}
def square(n):
nonlocal cache
if n not in cache:
cache[n] = n * n
return cache[n]
return square
Bu yerda nima sodir bo'lyapti
-
cachetashqi funksiyada joylashgan va oldingi natijalarni saqlaydi. -
square()hisoblashni bajarishdan oldin keshni tekshiradi. -
nonlocal cacheo'sha bitta dictionary'ni yangilash imkonini beradi. -
Qiymat saqlangach, keyingi chaqiruvlar uni darhol qaytaradi.
Bu keshlash mantiqini lokal saqlaydi va global maydonni ifloslantirmaydi.
Closure'larda umumiy state'ni boshqarish
Ba'zi yordamchi vositalarga umumiy yoqish-o'chirish yoki holat qiymati kerak bo'ladi. nonlocal ichki funksiyalarga o'sha umumiy state'ni xavfsiz yangilash imkonini beradi.
def toggle_flag():
enabled = False
def toggle():
nonlocal enabled
enabled = not enabled
return enabled
return toggle
Bu kodda,
-
enabledtashqi funksiyadaFalseqiymati bilan boshlanadi. -
toggle()har safar ishga tushganda qiymatni teskarisiga o'zgartiradi. -
nonlocal enabledo'sha bitta o'zgaruvchi yangilanishini ta'minlaydi. -
State chaqiruvlar orasida saqlanib qoladi.
Bu pattern feature flag'lar va almashtirgichlar uchun yaxshi ishlaydi.
Kichik yordamchi vositalarda global o'zgaruvchilardan qochish
Kichik kuzatuv vositalari ko'pincha dasturchilarni global o'zgaruvchilardan foydalanishga undaydi. nonlocal hamma narsani bir joyda jamlab turadi.
def request_tracker():
total = 0
def track():
nonlocal total
total += 1
return total
return track
Bu yerda nima sodir bo'lyapti
-
totaltrack()necha marta chaqirilganini sanaydi. -
Qiymat tracker ichida private bo'lib qoladi.
-
nonlocalyangilashlar o'sha bitta counter'ga ta'sir qilishini ta'minlaydi. -
Hech qanday global state ochib qo'yilmaydi.
Bu o'qilishni yaxshilaydi va testlashni osonlashtiradi.
Python'da nonlocal'dan qachon foydalanish kerak
nonlocal keyword'i ichki funksiya global o'zgaruvchilarga tegmasdan tashqi funksiyada aniqlangan state'ni yangilashini istaganingizda foydali. U nested function'lar ichida ma'lumotlarni ulashish va o'zgartirish imkonini beradi, shu bilan birga o'sha state'ni private va nazorat ostida saqlaydi.
Aniqlikni yaxshilaganda nonlocal'dan foydalaning
nonlocal quyidagi vaziyatlarda yaxshi tanlov:
-
Kichik yordamchi vositalarda state'ni saqlash: Funksiya counter'lar, almashtirgichlar yoki tracker'lar kabi ma'lumotlarni chaqiruvlar orasida eslab qolishi kerak bo'lganda,
nonlocalstate'ni undan foydalanadigan mantiqqa yaqin saqlaydi. -
Oddiy state uchun sinflardan qochish: Agar sizga ozgina state kerak bo'lsa, closure ichida
nonlocal'dan foydalanish to'liq sinf yaratishdan ko'ra soddaroq va o'qilishi osonroq bo'lishi mumkin. -
Callback'lar va handler'larni refactoring qilish: Event-driven yoki callback'larga asoslangan kodda
nonlocalichki funksiyalarga o'zgaruvchilarni argumentlarning bir nechta qatlami orqali uzatmasdan umumiy state'ni yangilash imkonini beradi. -
State'ni global scope'dan tashqarida saqlash:
Nonlocalo'zgaruvchilarni qayerda o'zgartirish mumkinligini cheklab, tasodifiy side effect'larning oldini oladi, bu esa kodni testlash va tushunishni osonlashtiradi.
Qachon muqobillarni ko'rib chiqish kerak
Nonlocal har doim ham eng yaxshi yechim emas. Quyidagi hollarda boshqa dizaynlarni ko'rib chiqing:
-
Mantiq chuqur nested bo'lib ketganda: Nested function'larning bir nechta darajasi o'qilishni pasaytirishi mumkin. Bunday hollarda o'zgaruvchilarni aniq uzatish yoki sinfdan foydalanish tushunarliroq bo'lishi mumkin.
-
State keng doirada ulashilishi kerak bo'lganda: Agar module bo'ylab ko'plab funksiyalarga bir xil ma'lumotga murojaat kerak bo'lsa, nonlocal juda cheklovchi bo'lishi mumkin. Sinf yoki yaxshi aniqlangan global state o'rinliroq bo'lishi mumkin.
-
Data flow aniq bo'lishi kerak bo'lganda: Argumentlarni uzatish va qiymatlarni qaytarish, ayniqsa kattaroq codebase'larda, bog'liqliklarni ravshanroq qilishi mumkin.
Amaliy qoida
State funksiyaga tegishli bo'lsa va unga yaqin qolishi kerak bo'lsa, nonlocal'dan foydalaning. State'ga kengroq murojaat kerak bo'lganda yoki nesting kodni kuzatishni qiyinlashtirganda nonlocal'dan qoching.
Ehtiyotkorlik bilan ishlatilganda nonlocal aniqlikni yaxshilaydi, side effect'larni cheklaydi va Python kodini toza hamda qo'llab-quvvatlash oson holda saqlaydi.
nonlocal'dan foydalanishda yodda tutish kerak bo'lgan best practice'lar
nonlocal keyword'i kuchli, lekin u ongli ravishda ishlatilganda eng yaxshi natija beradi. Bir nechta best practice'larga amal qilish yashirin bug'lardan qochishga va kodingizni tushunarli saqlashga yordam beradi.
Refactoring aniqlikni yaxshilaganda nonlocal'dan foydalaning
nonlocal ko'pincha argumentlarni takroran uzatishga yoki keraksiz global o'zgaruvchilarga tayanadigan kodni refactoring qilishda foydali. Agar kichik yordamchi vosita yoki callback umumiy state'ga muhtoj bo'lsa, nonlocal'dan foydalanish dizaynni soddalashtirishi va boilerplate'ni kamaytirishi mumkin.
Biroq har doim o'zingizdan refactoring haqiqatan ham o'qilishni yaxshilayaptimi, deb so'rang. Agar mantiqni kuzatish qiyinlashsa, boshqa dizayn yaxshiroq bo'lishi mumkin.
Hidden state'ga haddan tashqari tayanishdan qoching
nonlocal ichki funksiyalarga tashqi o'zgaruvchilarni o'zgartirish imkonini bergani uchun u hidden state'ni yuzaga keltirishi mumkin. Bu pattern'dan haddan tashqari ko'p foydalanish qiymatlar qayerda o'zgarishini kuzatishni qiyinlashtiradi.
Agar state murakkablashsa yoki kodning ko'p qismlariga ta'sir qilsa, quyidagilardan foydalanishni ko'rib chiqing:
-
Funksiyaning aniq argumentlari va qaytariladigan qiymatlari
-
State'ni boshqarish uchun kichik sinf
Aniq data flow'ni qo'llab-quvvatlash ko'pincha yashirin yangilashlarga qaraganda osonroq.
nonlocal faqat nested function'larda ishlashini yodda tuting
nonlocal keyword'i faqat nested function'lar ichida ishlaydi. Uni oddiy funksiyada ishlatib bo'lmaydi va u global scope o'zgaruvchilariga taalluqli emas.
Agar o'zgaruvchini aniqlaydigan o'rab turgan funksiya bo'lmasa, nonlocal xato chiqaradi. Undan foydalanishdan oldin har doim o'zgaruvchi enclosing scope'da mavjudligiga ishonch hosil qiling.
Xulosa
nonlocal boshqa funksiya ichidagi funksiya bilan ishlayotganingizda va ichki funksiya tashqi scope'da aniqlangan o'zgaruvchini o'zgartirishi kerak bo'lganda o'rinli. U o'sha state'ni global scope'ga sizdirib yubormasdan, o'zi tegishli bo'lgan funksiya ichida private saqlaydi.
nonlocal'ni ko'pincha counter'lar, callback'lar va state funksiya chaqiruvlari orasida saqlanib qolishi, lekin private bo'lib qolishi kerak bo'lgan oddiy yordamchi vositalar kabi pattern'larda ko'rasiz. Mantiqingiz murakkablashgani sari bu keyword qiymatlarni aniq qaytarish yoki kichik sinf kiritish kabi tushunarliroq muqobillarga o'tish vaqti kelganini anglashga ham yordam beradi.
Scope, funksiyalar va closure'lar kabi Python'ning asosiy tushunchalarini chuqurroq, bosqichma-bosqich tushunish uchun Python roadmap'iga nazar tashlang.