functools — partial, reduce, lru_cache
Muammodan boshlaylik
def narx_formatla(summa, valyuta, ajratuvchi, kasr):
...
narx_formatla(1500000, "so'm", " ", 0)
narx_formatla(250000, "so'm", " ", 0)
narx_formatla(85000, "so'm", " ", 0)
Har safar bir xil uchta argument. Boshqa muammo: kursni API dan oladigan funksiya bir xil valyuta uchun soniyasiga yuzlab marta chaqiriladi — har safar tarmoq so'rovi. Va ro'yxatni bitta qiymatga "yig'ish" kerak — sum va max dan boshqa amal bilan.
functools — funksiyalar bilan ishlaydigan funksiyalar moduli.
Hayotiy o'xshatma
Ustaxona moslamalari. partial — oldindan sozlangan asbob: kerakli razmerdagi uchni bir marta mahkamlab qo'yasiz va keyin faqat ishlatasiz. lru_cache — ustaning daftari: bir marta hisoblangan o'lchamni qayta hisoblamaydi, yozib qo'ygan. reduce — bir qop yong'oqni bittalab chaqib, bitta kosaga yig'ish.
partial — argumentlarni oldindan to'ldirish
from functools import partial
def narx_formatla(summa, valyuta="so'm", ajratuvchi=" ", kasr=0):
satr = f"{summa:,.{kasr}f}".replace(",", ajratuvchi)
return f"{satr} {valyuta}"
somda = partial(narx_formatla, valyuta="so'm", ajratuvchi=" ")
dollarda = partial(narx_formatla, valyuta="quot;, ajratuvchi=",", kasr=2)
print(somda(1500000)) # 1 500 000 so'm
print(dollarda(1234.5)) # 1,234.50 $
partial(f, ...) — ba'zi argumentlari "mahkamlangan" yangi funksiya.
Foydali joylar
from functools import partial
# int ni boshqa sanoq tizimi bilan
ikkilikdan = partial(int, base=2)
print(ikkilikdan("1010")) # 10
# map, sorted, callback larga uzatish
def kopaytir(x, k):
return x * k
print(list(map(partial(kopaytir, k=3), [1, 2, 3]))) # [3, 6, 9]
# tugma bosilganda argument bilan chaqiriladigan funksiya
tugma.on_click(partial(ochir, mahsulot_id=42))
Lambda ham shunday qila oladi (lambda x: kopaytir(x, k=3)), lekin partial ning nomi va argumentlari ko'rinib turadi va sikldagi lambda tuzog'iga (20-dars) tushmaydi.
reduce — ketma-ketlikni bitta qiymatga yig'ish
from functools import reduce
sonlar = [1, 2, 3, 4, 5]
kopaytma = reduce(lambda a, b: a * b, sonlar)
print(kopaytma) # 120
Qanday ishlaydi:
reduce(f, [1, 2, 3, 4, 5])
f(1, 2) = 2
f(2, 3) = 6
f(6, 4) = 24
f(24, 5) = 120
Boshlang'ich qiymat bilan (bo'sh ro'yxatda xato bermasligi uchun):
reduce(lambda a, b: a * b, [], 1) # 1
Ichma-ich lug'atdan qiymat olish
from functools import reduce
malumot = {"user": {"manzil": {"shahar": "Toshkent"}}}
yol = ["user", "manzil", "shahar"]
print(reduce(lambda d, kalit: d[kalit], yol, malumot)) # Toshkent
[!TIP]
reduceko'pincha o'qish uchun qiyin. Ko'p vazifalar uchun aniqroq muqobillar bor:sum(),max(),min(),any(),all(),"".join(),math.prod()(ko'paytma), yoki oddiyforsikl.reduceni haqiqatan "zanjirli yig'ish" kerak bo'lganda ishlating.
import math
math.prod([1, 2, 3, 4, 5]) # 120 — reduce siz
lru_cache — natijalarni eslab qolish
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(200)) # bir zumda (22-dars — memoization)
Bir xil argumentlar bilan qayta chaqirilsa — funksiya bajarilmaydi, natija keshdan olinadi.
maxsize — kesh hajmi
@lru_cache(maxsize=128)
def kurs(valyuta):
print(f"API ga so'rov: {valyuta}")
return api_dan_kurs_ol(valyuta)
kurs("USD") # API ga so'rov: USD
kurs("USD") # — keshdan, so'rov yo'q
kurs("EUR") # API ga so'rov: EUR
print(kurs.cache_info()) # CacheInfo(hits=1, misses=2, maxsize=128, currsize=2)
kurs.cache_clear() # keshni tozalash
LRU — "Least Recently Used": kesh to'lganda eng uzoq vaqt ishlatilmagan natija chiqarib tashlanadi. maxsize=None — chegarasiz (xotira o'sishi mumkin).
@cache (Python 3.9+) — @lru_cache(maxsize=None) ning qisqa shakli.
Qachon ishlatish va ehtiyot choralari
✅ Mos:
- Pure funksiyalar — natija faqat argumentlarga bog'liq (rekursiv hisoblar, parsing, og'ir matematik hisoblar)
- Bir xil argumentlar ko'p takrorlanadi
❌ Mos emas:
- Natija vaqt bilan o'zgaradi —
datetime.now(), bazadagi o'zgaruvchan ma'lumot, valyuta kursi (kesh hech qachon yangilanmaydi —cache_clear()yoki vaqt bilan yangilanadigan kesh kerak) - Side effect lar (email yuborish) — ikkinchi chaqiruvda bajarilmaydi
- Argumentlar o'zgaruvchan (list, dict)
[!WARNING]
lru_cacheargumentlar hashable bo'lishini talab qiladi:@lru_cacheli funksiyani ro'yxat bilan chaqirsangiz —TypeError: unhashable type: 'list'. Tuple ga aylantiring. Va metodlarga (selfbilan) qo'llashda ehtiyot bo'ling: kesh ob'ektga havolani ushlab turadi va u xotiradan tozalanmaydi.
wraps — dekoratorlar uchun
23-darsda ko'rgan:
from functools import wraps
def log(f):
@wraps(f) # f ning nomi va docstring ini saqlash
def orovchi(*args, **kwargs):
print(f"{f.__name__} chaqirildi")
return f(*args, **kwargs)
return orovchi
Boshqa foydali funksiyalar
total_ordering
29-darsda: __eq__ va __lt__ dan barcha taqqoslash operatorlarini yaratadi.
cached_property
from functools import cached_property
class Hisobot:
def __init__(self, sotuvlar):
self.sotuvlar = sotuvlar
@cached_property
def jami(self):
print("Hisoblanmoqda...")
return sum(self.sotuvlar)
h = Hisobot([100, 200, 300])
print(h.jami) # Hisoblanmoqda... 600
print(h.jami) # 600 — qayta hisoblanmaydi
Bir marta hisoblanadigan og'ir property (28-dars) uchun.
singledispatch — tur bo'yicha har xil funksiya
from functools import singledispatch
@singledispatch
def formatla(qiymat):
return str(qiymat)
@formatla.register
def _(qiymat: float):
return f"{qiymat:.2f}"
@formatla.register
def _(qiymat: list):
return ", ".join(formatla(x) for x in qiymat)
print(formatla(3.14159)) # 3.14
print(formatla([1, 2.5, "a"])) # 1, 2.50, a
if isinstance(...) zanjirlari o'rniga.
Tez-tez uchraydigan xatolar
Vaqtga bog'liq funksiyani keshlash — eskirgan ma'lumot abadiy qaytadi.
lru_cache ga list uzatish — TypeError: unhashable type.
reduce ni sum o'rniga:
reduce(lambda a, b: a + b, sonlar) # ishlaydi, lekin
sum(sonlar) # ✅ aniqroq va tezroq
Xulosa
functools — funksiyalarni sozlash, keshlash va birlashtirish vositalari.
Eslab qoling:
partial(f, ...)— argumentlari oldindan to'ldirilgan yangi funksiyareduce(f, iterable, boshlang'ich)— bitta qiymatga yig'ish; ko'pinchasum/math.prod/sikl aniqroq@lru_cache(maxsize=...)/@cache— pure funksiya natijalarini keshlash;cache_info(),cache_clear()- Kesh — faqat hashable argumentlar va vaqtga bog'liq bo'lmagan natijalar uchun
@wraps,@total_ordering,@cached_property,@singledispatch
Keyingi dars
48-dars: Type hints — list[int], Optional, Union, dict[str, int], TypeVar