Nega boshlang`ich-odatiy qiymat ob`yektlar orasida taqsimlanadi?
Bunday xatolik ham boshlovchi dasturchilar orasida tez-tez uchrab turadi. Mana bunday funksiyani qaraylik:
def foo(mydict={}): # xavfli: chaqiruvlar orasida taqsimlangan havola.
... compute something ...
mydict[key] = value
return mydict
Funksiyani birinchi marta chaqirganingizda mydict boshqa qiymatga ega bo`lsa, ikkinchi martada u 2 ta elementga ega bo`ladi, chunki, foo() bajarilishniboshlayotganida mydict allaqachon bir elementga ega bo`ladi.
Ko`pincha funksiyani chaqirish odatiy qiymatlar uchun yangi ob`yektlarni yaratilishiga olib kelishini kutishadi. Lekin, aslida bunday emas. Odatiy qiymatlar faqat bir marta, funksiyani tavsiflanish jarayonida yaratiladi. Agar bu ob`yekt, bizning misolimizdagi lug`at kabi, o`zgaradigan bo`lsa, funksiyaga keyingi murojaatlar o`zgartirilgan ob`yektdan foydalanishadi.
Aslida, o`zgarmaydigan ob`yektlar (sonlar, satrlar, kortejlar va None ob`yektlar) o`zgartirilayotganda xavf tug`dirmaydi. Lug`atlar, ro`yxatlar, foydalanuvchi klasslarining ekzemlyarlari kabi o`zgaradigan ob`yektlarni o`zgartirish esa, kutilmagan oqibatlarga olib kelishi mumkin.
Shuning uchun odatiy qiymatlar sifatida o`zgaradigan ob`yektlardan foydalanmaslik amaliyoti keng tarqalgandir. Buning o`rniga funksiyaning ichida ham Nonedan foydalaning, argumentni None ekanligini tekshiring, yangi ro`yxat/lug`atlar yarating.
Mana bu misoldagidek ish tutmang:
def foo(mydict={}):
...
def foo(mydict=None):
if mydict is None:
mydict = {} # lokal nomlar muhiti uchun yangi lug`at yarating,
Mana bu misoldagidek yo`l tutish mumkin:
Lekin bu xususiyatdan biz o`zimizga kerakli holatlarda unumli foydlanishimiz ham mumkin. Sizda birorta uzoq vaqt bajariluvhci funksiyangiz bor bo`lsa, parametrlar va funksiyaning har bir chaqirilishi natijalarini kesh-xotirada saqlash – keng qo`llaniladigan usullardan biridir.
def expensive(arg1, arg2, _cache={}):
if (arg1, arg2) in _cache:
return _cache[(arg1, arg2)]
# Qiymatni hisoblash
result = ... expensive computation ...
_cache[(arg1, arg2)] = result # Natijani keshga joylashtiramiz
return result
Dostları ilə paylaş: |