Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. functools xaritasi
- 2.2. Kesh va konkurentlik
- 2.3. Kesh kaliti va turlar
- 2.4. singledispatch chuqur
- 2.5. total_ordering narxi
- 2.6. cmp_to_key
- 2.7. reduce va o'rnatilgan funksiyalar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Kesh va konkurentlik
- Misol 2 — singledispatch chuqur
- Misol 3 — total_ordering, cmp_to_key, reduce
- Misol 4 — Amaliy: valyuta xizmati
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
15.10-dars: functools to'liq
15-QISM — STANDART KUTUBXONA · 10-dars
1. Kirish va motivatsiya
functools bilan kurs davomida ko'p marta uchrashdik: wraps 10.11-bob, cache, partial, reduce 10.13-bob, singledispatch 8.9-bob, total_ordering 8.12-bob, cached_property 8.15-bob. Har biri o'z mavzusi ichida o'rganildi.
Bu dars — yakuniy xarita. Uch maqsad:
- Modulning barcha vositalarini bitta jadvalda ko'rish: nima uchun, qachon va qayerda o'rganilgan.
- Hali ko'rilmagan nozik joylar: kesh va konkurentlik (
asyncio, iplar),singledispatchning noaniq tanlovi,total_orderingnarxi,cmp_to_key. - Vositalarni birgalikda ishlatish — real xizmatda.
Real vaziyat. Valyuta kurslari xizmatida tashqi API chaqiruvi @functools.cache bilan keshlandi:
@cache
async def kurs_ol(valyuta: str) -> float:
...Lokal testda bitta so'rov — hammasi ishladi. Ishlab chiqarishda ikkinchi so'rov RuntimeError: cannot reuse already awaited coroutine bilan yiqildi. Sabab: cache natijani emas, korutina obyektini saqlagan edi — uni esa faqat bir marta await qilish mumkin.
Xuddi shu xizmatda iplar bilan ishlaydigan qismda lru_cache "bir marta hisoblash"ni kafolatlaydi deb o'ylashdi. Kesh bo'shligida 8 ta so'rov bir vaqtda kelganda tashqi API 8 marta chaqirildi va limitdan oshib, bloklandi.
Bu darsda shunday nozik joylarni o'lchaymiz va hammasini birlashtirgan xizmat quramiz.
Bu darsda:
-
functoolsxaritasi: 13 ta vosita bir jadvalda - Kesh va konkurentlik:
asyncfunksiya, iplar,cached_property(3.12 o'zgarishi) - Kesh kaliti va turlar:
1,1.0,True,typed=True -
singledispatchchuqur: MRO, ABC, noaniq tanlov, birlashma turlar,singledispatchmethod total_orderingnarxi vaNotImplementedcmp_to_key— taqqoslash funksiyasidan kalitga; o'zbek alifbosi bo'yicha saralashreduceva o'rnatilgan funksiyalar- Amaliy: valyuta xizmati — vositalarni birgalikda ishlatish
2. Nazariya — chuqur tushuntirish
2.1. functools xaritasi
| Vosita | Nima qiladi | Qayerda o'rganildi |
|---|---|---|
wraps, update_wrapper |
O'ramga asl funksiya metama'lumotini ko'chiradi | 10.11 |
cache |
Chegarasiz kesh | 10.13 |
lru_cache(maxsize, typed) |
LRU kesh, statistika | 10.13, 15.7 |
cached_property |
Bir marta hisoblanadigan atribut | 8.15, 10.17 |
partial |
Argumentlarni oldindan bog'lash | 10.13 |
partialmethod |
Metodlar uchun partial |
10.13 |
Placeholder (3.14) |
partial da pozitsion argumentni o'tkazib yuborish |
10.13 |
reduce |
Chap yig'ish | 7.12, 10.13 |
singledispatch |
Birinchi argument turi bo'yicha yuborish | 8.9 |
singledispatchmethod |
Metodlar uchun | 8.9, 8.16 |
total_ordering |
Bitta taqqoslashdan qolganlarini yasash | 8.12 |
cmp_to_key |
Eski uslubdagi taqqoslash funksiyasini key ga |
6.3, bu dars |
WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES |
wraps nimani ko'chirishini belgilovchi konstantalar |
10.11 |
2.2. Kesh va konkurentlik
| Holat | Nima bo'ladi | Yechim |
|---|---|---|
@cache + async def |
Korutina obyekti keshlanadi → ikkinchi await da RuntimeError |
Natijani keshlash: lug'at + asyncio.Lock, yoki async kesh kutubxonasi |
lru_cache + iplar, bo'sh kesh |
Ichki tuzilma ip-xavfsiz, lekin funksiya bir necha marta bajarilishi mumkin ("cache stampede") | Kalit bo'yicha qulf |
cached_property + iplar |
3.12 dan beri qulf yo'q — bir necha marta hisoblanishi mumkin | Kerak bo'lsa o'z qulfingiz |
cached_property + __slots__ |
TypeError: __dict__ yo'q |
__slots__ ga "__dict__" qo'shish yoki lru_cache li metod |
lru_cache natijaning to'g'riligini kafolatlaydi (oxir-oqibat bitta qiymat saqlanadi), lekin chaqiruvlar sonini kafolatlamaydi.
2.3. Kesh kaliti va turlar
Kesh kaliti argumentlardan yasaladi 10.13-bob. Bir argumentli chaqiruvda int va str uchun tezkor yo'l bor — kalit argumentning o'zi; boshqa turlar kortejga o'raladi. Natijada:
@cache
def tur(x): return type(x).__name__
tur(1) # 'int'
tur(1.0) # 'float' — 1 bilan teng bo'lsa ham alohida kalit
tur(True) # 'float' — ⚠️ (True,) == (1.0,) → 1.0 ning natijasi| Sozlama | Xulq |
|---|---|
typed=False (sukut) |
Teng qiymatlar bir kalitga tushishi mumkin — tartib va tezkor yo'lga bog'liq |
typed=True |
Tur ham kalitga kiradi — 1, 1.0, True alohida |
Funksiya natijasi argument turiga bog'liq bo'lsa — lru_cache(typed=True).
2.4. singledispatch chuqur
Yuborish (dispatch) birinchi argumentning sinfi MRO si bo'yicha eng mos ro'yxatdan o'tgan turni topadi. ABC lar (Sized, Iterable) ham hisobga olinadi.
| Holat | Natija |
|---|---|
| Aniq tur ro'yxatda | Shu realizatsiya |
| Ota sinf ro'yxatda | MRO bo'yicha eng yaqini |
| Ikki ABC teng darajada mos | RuntimeError: Ambiguous dispatch |
bool qiymat, int ro'yxatda |
int realizatsiyasi — bool — int vorisi |
int | float annotatsiya (3.11+) |
Har ikkala tur ro'yxatga olinadi |
| Hech biri mos emas | Asosiy (object) funksiya |
Noaniqlik ko'rinmas joyda chiqadi: Sized va Iterable ro'yxatdan o'tkazilsa, oddiy list ham ikkalasiga teng mos keladi va RuntimeError beradi. Yechim: umumiyroq (Collection) yoki aniq tur (list) uchun alohida realizatsiya. Collection faqat __len__, __iter__ va __contains__ ga ega sinflarni qamraydi — faqat __len__ va __iter__ li o'z sinfingiz uchun baribir aniq realizatsiya kerak (Misol 2).
| API | Vazifasi |
|---|---|
f.register(tur) / annotatsiya bilan |
Realizatsiya qo'shish |
f.dispatch(tur) |
Qaysi realizatsiya tanlanishini ko'rish |
f.registry |
Barcha ro'yxatdagilar |
singledispatchmethod |
Metodlar — yuborish ikkinchi argument (self dan keyingi) bo'yicha |
singledispatchmethod bilan classmethod/staticmethod birga ishlatilganda @singledispatchmethod tashqarida bo'lishi kerak.
2.5. total_ordering narxi
@total_ordering bitta taqqoslash (__lt__) va __eq__ dan qolgan to'rttasini yasaydi.
| Xususiyat | Tafsilot |
|---|---|
| Qulaylik | Kam kod, xatolar kamroq |
| Narxi | Yasalgan metodlar qo'shimcha chaqiruv qiladi — sekinroq |
NotImplemented |
To'g'ri qaytarilsa, yasalgan metodlar ham uni to'g'ri uzatadi |
| Qachon qo'lda yozish | Juda ko'p taqqoslanadigan "issiq" kod (saralash, heap) |
Zamonaviy muqobil: @dataclass(order=True) — maydonlar kortej sifatida taqqoslanadi 8.17-bob.
2.6. cmp_to_key
Python 2 da sorted(xs, cmp=f) — f(a, b) manfiy, nol yoki musbat qaytarardi. Python 3 da faqat key bor. cmp_to_key eski taqqoslash funksiyasini kalit obyektiga o'raydi.
Qachon cmp_to_key |
Qachon oddiy key |
|---|---|
| Tashqi kutubxonadan taqqoslash funksiyasi | Deyarli har doim |
Juftlik taqqoslash kalitga keltirilmaydi (masalan, a+b va b+a satrlarini solishtirish) |
Kalitni hisoblash mumkin |
key tezroq: har element uchun bir marta hisoblanadi |
2.7. reduce va o'rnatilgan funksiyalar
| Vazifa | reduce bilan |
Yaxshirog'i |
|---|---|---|
| Yig'indi | reduce(add, xs) |
sum(xs) |
| Ko'paytma | reduce(mul, xs) |
math.prod(xs) |
| Maksimum | reduce(max, xs) |
max(xs) |
| Hammasi rostmi | reduce(and_, xs) |
all(xs) |
| Lug'atlarni birlashtirish | reduce(or_, dicts, {}) |
reduce o'rinli |
| Funksiyalar kompozitsiyasi | reduce(lambda f, g: ..., fs) |
O'rinli |
Bo'sh ketma-ketlik va boshlang'ich qiymatsiz — TypeError: reduce() of empty iterable with no initial value.
3. Tez ma'lumotnoma
import functools as ft
@ft.lru_cache(maxsize=1024, typed=True) # tur muhim bo'lsa typed
def hisobla(x): ...
@ft.singledispatch
def formatla(x): return str(x)
@formatla.register
def _(x: int | float): ...
formatla.dispatch(bool) # qaysi realizatsiya?
@ft.total_ordering
class Versiya: ... # __eq__ + __lt__
sorted(sozlar, key=ft.cmp_to_key(taqqosla)) # eski taqqoslash funksiyasi
ft.reduce(lambda f, g: lambda x: g(f(x)), bosqichlar) # kompozitsiyaQoidalar
async funksiyaga @cache qo'ymang
lru_cache chaqiruvlar sonini kafolatlamaydi — stampede
cached_property 3.12+ da qulfsiz
tur muhim — typed=True
singledispatch: teng mos ABC lar — RuntimeError
total_ordering — qulay, lekin sekinroq
key — cmp_to_key dan afzal4. Batafsil misollar
Misol 1 — Kesh va konkurentlik
"""@cache va async funksiya; to'g'ri async kesh; lru_cache va iplar — stampede; kalit bo'yicha qulf; cached_property qulfsizligi; __slots__ bilan cached_property; typed=True."""
import asyncio
import functools as ft
import threading
import time
@ft.cache
async def xato_kurs(valyuta: str) -> float:
await asyncio.sleep(0)
return {"USD": 12_650.0, "EUR": 13_900.0}[valyuta]
class AsyncKesh:
def __init__(self) -> None:
self.natijalar: dict[str, float] = {}
self.qulflar: dict[str, asyncio.Lock] = {}
self.chaqiruvlar = 0
async def kurs(self, valyuta: str) -> float:
if valyuta in self.natijalar:
return self.natijalar[valyuta]
qulf = self.qulflar.setdefault(valyuta, asyncio.Lock())
async with qulf:
if valyuta not in self.natijalar: # qulfdan keyin qayta tekshiruv
self.chaqiruvlar += 1
await asyncio.sleep(0.01)
self.natijalar[valyuta] = {"USD": 12_650.0, "EUR": 13_900.0}[valyuta]
return self.natijalar[valyuta]
async def async_qism() -> None:
birinchi = await xato_kurs("USD")
try:
await xato_kurs("USD")
except RuntimeError as xato:
print(f" @cache + async: birinchi={birinchi}, ikkinchi → RuntimeError: {xato}")
kesh = AsyncKesh()
natijalar = await asyncio.gather(*(kesh.kurs("USD") for _ in range(10)))
print(f" to'g'ri async kesh: 10 so'rov, natijalar bir xil: {len(set(natijalar)) == 1}, API chaqiruvlari: {kesh.chaqiruvlar}")
def main() -> None:
print("=== 1. ⚠️ Asinxron funksiyani keshlash ===")
asyncio.run(async_qism())
print("\n=== 2. ⚠️ lru_cache va iplar: stampede ===")
chaqiruvlar = 0
hisob_qulfi = threading.Lock()
@ft.lru_cache(maxsize=None)
def sekin_kurs(valyuta: str) -> float:
nonlocal chaqiruvlar
with hisob_qulfi:
chaqiruvlar += 1
time.sleep(0.1)
return 12_650.0
iplar = [threading.Thread(target=sekin_kurs, args=("USD",)) for _ in range(8)]
for ip in iplar:
ip.start()
for ip in iplar:
ip.join()
print(f" 8 ip bir vaqtda: funksiya bir martadan ko'p bajarildi: {chaqiruvlar > 1}")
print(f" keshda baribir bitta yozuv: {sekin_kurs.cache_info().currsize == 1}")
print("\n=== 3. Kalit bo'yicha qulf ===")
natijalar: dict[str, float] = {}
qulflar: dict[str, threading.Lock] = {}
qulflar_qulfi = threading.Lock()
haqiqiy = 0
def himoyalangan_kurs(valyuta: str) -> float:
nonlocal haqiqiy
if valyuta in natijalar:
return natijalar[valyuta]
with qulflar_qulfi:
qulf = qulflar.setdefault(valyuta, threading.Lock())
with qulf:
if valyuta not in natijalar:
haqiqiy += 1
time.sleep(0.1)
natijalar[valyuta] = 12_650.0
return natijalar[valyuta]
iplar = [threading.Thread(target=himoyalangan_kurs, args=("USD",)) for _ in range(8)]
for ip in iplar:
ip.start()
for ip in iplar:
ip.join()
print(f" 8 ip: haqiqiy chaqiruvlar = {haqiqiy}")
print("\n=== 4. ⚠️ cached_property: 3.12+ da qulfsiz ===")
hisoblandi = 0
class Hisobot:
@ft.cached_property
def jami(self) -> int:
nonlocal hisoblandi
hisoblandi += 1
time.sleep(0.05)
return 42
h = Hisobot()
iplar = [threading.Thread(target=lambda: h.jami) for _ in range(5)]
for ip in iplar:
ip.start()
for ip in iplar:
ip.join()
print(f" 5 ip: hisoblash bir martadan ko'p: {hisoblandi > 1}, qiymat: {h.jami}")
class Slotli:
__slots__ = ("x",)
@ft.cached_property
def ogir(self) -> int:
return 1
try:
Slotli().ogir
except TypeError as xato:
print(f" __slots__ bilan: TypeError: {xato}")
print("\n=== 5. ⚠️ Kesh kaliti va turlar ===")
@ft.cache
def tur(x: object) -> str:
return type(x).__name__
@ft.lru_cache(typed=True)
def tur_typed(x: object) -> str:
return type(x).__name__
print(f" cache: 1→{tur(1)}, 1.0→{tur(1.0)}, True→{tur(True)}")
print(f" typed=True: 1→{tur_typed(1)}, 1.0→{tur_typed(1.0)}, True→{tur_typed(True)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ Asinxron funksiyani keshlash ===
@cache + async: birinchi=12650.0, ikkinchi → RuntimeError: cannot reuse already awaited coroutine
to'g'ri async kesh: 10 so'rov, natijalar bir xil: True, API chaqiruvlari: 1
=== 2. ⚠️ lru_cache va iplar: stampede ===
8 ip bir vaqtda: funksiya bir martadan ko'p bajarildi: True
keshda baribir bitta yozuv: True
=== 3. Kalit bo'yicha qulf ===
8 ip: haqiqiy chaqiruvlar = 1
=== 4. ⚠️ cached_property: 3.12+ da qulfsiz ===
5 ip: hisoblash bir martadan ko'p: True, qiymat: 42
__slots__ bilan: TypeError: No '__dict__' attribute on 'Slotli' instance to cache 'ogir' property.
=== 5. ⚠️ Kesh kaliti va turlar ===
cache: 1→int, 1.0→float, True→float
typed=True: 1→int, 1.0→float, True→boolNima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 2 — singledispatch chuqur
"""MRO bo'yicha tanlov; ABC lar va noaniq tanlov (list ham!); tuzatish; birlashma turlar; bool va int; dispatch va registry; singledispatchmethod va classmethod."""
import functools as ft
from collections.abc import Collection, Iterable, Mapping, Sized
from datetime import date
from decimal import Decimal
@ft.singledispatch
def tavsif(x: object) -> str:
return "noma'lum"
@tavsif.register
def _(x: Sized) -> str:
return f"o'lchamli ({len(x)})"
@tavsif.register
def _(x: Iterable) -> str:
return "aylanadigan"
class Toplam:
def __len__(self) -> int:
return 3
def __iter__(self):
return iter([1, 2, 3])
class Sanoq:
def __len__(self) -> int:
return 7
@ft.singledispatch
def formatla(x: object) -> str:
return str(x)
@formatla.register
def _(x: int | float) -> str:
return f"{x:,}".replace(",", " ")
@formatla.register
def _(x: bool) -> str:
return "ha" if x else "yo'q"
@formatla.register
def _(x: Decimal) -> str:
return f"{x:.2f} so'm"
@formatla.register
def _(x: date) -> str:
return f"{x:%d.%m.%Y}"
@formatla.register
def _(x: Mapping) -> str:
return ", ".join(f"{k}={formatla(v)}" for k, v in x.items())
class Eksport:
@ft.singledispatchmethod
@classmethod
def qiymat(cls, x: object) -> str:
return f"<{type(x).__name__}>"
@qiymat.register
@classmethod
def _(cls, x: int) -> str:
return f"butun:{x}"
@qiymat.register
@classmethod
def _(cls, x: str) -> str:
return f"satr:{x!r}"
def main() -> None:
print("=== 1. ⚠️ Noaniq tanlov ===")
print(f" Sanoq (faqat __len__): {tavsif(Sanoq())}")
for nom, qiymat in (("Toplam", Toplam()), ("list", [1, 2])):
try:
tavsif(qiymat)
except RuntimeError as xato:
print(f" {nom}: RuntimeError: {str(xato)[:60]}...")
print(f" aniq qiymat: {tavsif.dispatch(Sanoq).__name__} — '_' deb nomlangan realizatsiya")
@tavsif.register
def _(x: Collection) -> str:
return f"to'plam ({len(x)})"
print(f" Collection qo'shilgach: list → {tavsif([1, 2])}")
try:
tavsif(Toplam())
except RuntimeError:
print(f" ⚠️ Toplam hali ham noaniq: __contains__ yo'q → Collection emas: {not issubclass(Toplam, Collection)}")
tavsif.register(Toplam, lambda x: "Toplam (aniq realizatsiya)")
print(f" aniq tur ro'yxatga olingach: {tavsif(Toplam())}")
print("\n=== 2. Birlashma turlar va bool ===")
for x in (1234567, 3.5, True, Decimal("12650.5"), date(2026, 9, 17), "matn", {"narx": 45000, "faol": False}):
print(f" {type(x).__name__:8} → {formatla(x)}")
print(f" ro'yxatdagi turlar: {sorted(t.__name__ for t in formatla.registry)}")
print(f" bool uchun alohida realizatsiya bo'lmasa int ishlardi: {issubclass(bool, int)}")
print("\n=== 3. dispatch() — tanlovni tekshirish ===")
for tur in (int, bool, float, dict, list):
realizatsiya = formatla.dispatch(tur)
print(f" {tur.__name__:5} → asosiy funksiyami: {realizatsiya is formatla.registry[object]}")
print("\n=== 4. singledispatchmethod + classmethod ===")
for x in (42, "Wisar", 3.14):
print(f" Eksport.qiymat({x!r}) → {Eksport.qiymat(x)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ Noaniq tanlov ===
Sanoq (faqat __len__): o'lchamli (7)
Toplam: RuntimeError: Ambiguous dispatch: <class 'collections.abc.Sized'> or <clas...
list: RuntimeError: Ambiguous dispatch: <class 'collections.abc.Sized'> or <clas...
aniq qiymat: _ — '_' deb nomlangan realizatsiya
Collection qo'shilgach: list → to'plam (2)
⚠️ Toplam hali ham noaniq: __contains__ yo'q → Collection emas: True
aniq tur ro'yxatga olingach: Toplam (aniq realizatsiya)
=== 2. Birlashma turlar va bool ===
int → 1 234 567
float → 3.5
bool → ha
Decimal → 12650.50 so'm
date → 17.09.2026
str → matn
dict → narx=45 000, faol=yo'q
ro'yxatdagi turlar: ['Decimal', 'Mapping', 'bool', 'date', 'float', 'int', 'object']
bool uchun alohida realizatsiya bo'lmasa int ishlardi: True
=== 3. dispatch() — tanlovni tekshirish ===
int → asosiy funksiyami: False
bool → asosiy funksiyami: False
float → asosiy funksiyami: False
dict → asosiy funksiyami: False
list → asosiy funksiyami: True
=== 4. singledispatchmethod + classmethod ===
Eksport.qiymat(42) → butun:42
Eksport.qiymat('Wisar') → satr:'Wisar'
Eksport.qiymat(3.14) → <float>Nima ko'rsatdi: 2.4-bo'lim.
Misol 3 — total_ordering, cmp_to_key, reduce
"""total_ordering: to'g'rilik va narx; dataclass(order=True) muqobili; cmp_to_key: eski taqqoslash va eng katta son masalasi; o'zbek alifbosi bo'yicha saralash; reduce: lug'atlar va funksiyalar kompozitsiyasi."""
import functools as ft
import operator
import timeit
from dataclasses import dataclass
@ft.total_ordering
class VersiyaTO:
def __init__(self, satr: str) -> None:
self.qismlar = tuple(int(q) for q in satr.split("."))
def __eq__(self, boshqa: object) -> bool:
if not isinstance(boshqa, VersiyaTO):
return NotImplemented
return self.qismlar == boshqa.qismlar
def __lt__(self, boshqa: object) -> bool:
if not isinstance(boshqa, VersiyaTO):
return NotImplemented
return self.qismlar < boshqa.qismlar
class VersiyaQolda(VersiyaTO):
def __ge__(self, boshqa: object) -> bool:
if not isinstance(boshqa, VersiyaTO):
return NotImplemented
return self.qismlar >= boshqa.qismlar
@dataclass(frozen=True, order=True)
class VersiyaDC:
katta: int
kichik: int
tuzatish: int
ALIFBO = ["a", "b", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "x", "y", "z", "oʻ", "gʻ", "sh", "ch", "ng"]
TARTIB = {harf: i for i, harf in enumerate(ALIFBO)}
def harflarga(soz: str) -> list[str]:
soz = soz.lower().replace("'", "ʻ").replace("‘", "ʻ")
harflar, i = [], 0
while i < len(soz):
ikki = soz[i:i + 2]
if ikki in TARTIB:
harflar.append(ikki)
i += 2
else:
harflar.append(soz[i])
i += 1
return harflar
def ozbek_kaliti(soz: str) -> list[int]:
return [TARTIB.get(h, len(ALIFBO)) for h in harflarga(soz)]
def main() -> None:
print("=== 1. total_ordering ===")
a, b = VersiyaTO("3.12.1"), VersiyaTO("3.9.8")
print(f" 3.12.1 > 3.9.8: {a > b}, <=: {a <= b}, >=: {a >= b} (satr sifatida: {'3.12.1' > '3.9.8'})")
print(f" boshqa tur bilan ==: {a == '3.12.1'}")
try:
a < "3.12.1"
except TypeError:
print(" boshqa tur bilan < → TypeError (NotImplemented to'g'ri uzatildi)")
yasalgan = min(timeit.repeat(lambda: a >= b, number=200_000, repeat=5))
qolda = VersiyaQolda("3.12.1"), VersiyaQolda("3.9.8")
qolda_vaqt = min(timeit.repeat(lambda: qolda[0] >= qolda[1], number=200_000, repeat=5))
print(f" yasalgan __ge__ qo'lda yozilgandan sekinroq: {yasalgan > qolda_vaqt}")
print(f" dataclass(order=True): {VersiyaDC(3, 12, 1) > VersiyaDC(3, 9, 8)}")
print("\n=== 2. cmp_to_key: kalitga keltirib bo'lmaydigan taqqoslash ===")
sonlar = [3, 30, 34, 5, 9]
def juftlik_taqqos(x: str, y: str) -> int:
return (x + y < y + x) - (x + y > y + x) # xy katta bo'lsa x oldinda
eng_katta = "".join(sorted(map(str, sonlar), key=ft.cmp_to_key(juftlik_taqqos)))
oddiy = "".join(sorted(map(str, sonlar), reverse=True))
print(f" {sonlar} dan eng katta son: {eng_katta}")
print(f" oddiy teskari saralash: {oddiy} ← noto'g'ri")
print("\n=== 3. O'zbek alifbosi bo'yicha saralash ===")
sozlar = ["choy", "olma", "shaftoli", "o'rik", "gilos", "g'isht", "anor", "nok", "zira", "sabzi"]
print(f" sorted() (Unicode kodlari): {sorted(sozlar)}")
print(f" o'zbek alifbosi: {sorted(sozlar, key=ozbek_kaliti)}")
def eski_taqqos(x: str, y: str) -> int:
kx, ky = ozbek_kaliti(x), ozbek_kaliti(y)
return (kx > ky) - (kx < ky)
print(f" cmp_to_key bilan bir xil: {sorted(sozlar, key=ft.cmp_to_key(eski_taqqos)) == sorted(sozlar, key=ozbek_kaliti)}")
print("\n=== 4. reduce ===")
sozlamalar = [{"host": "localhost", "port": 5432}, {"port": 6543}, {"debug": True}]
print(f" lug'atlarni birlashtirish: {ft.reduce(operator.or_, sozlamalar, {})}")
bosqichlar = [str.strip, str.lower, lambda s: " ".join(s.split())]
tozala = ft.reduce(lambda f, g: lambda x: g(f(x)), bosqichlar)
print(f" funksiyalar kompozitsiyasi: {tozala(' SALOM DUNYO ')!r}")
try:
ft.reduce(operator.add, [])
except TypeError as xato:
print(f" bo'sh ro'yxat: TypeError: {xato}")
print(f" boshlang'ich qiymat bilan: {ft.reduce(operator.add, [], 0)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. total_ordering ===
3.12.1 > 3.9.8: True, <=: False, >=: True (satr sifatida: False)
boshqa tur bilan ==: False
boshqa tur bilan < → TypeError (NotImplemented to'g'ri uzatildi)
yasalgan __ge__ qo'lda yozilgandan sekinroq: True
dataclass(order=True): True
=== 2. cmp_to_key: kalitga keltirib bo'lmaydigan taqqoslash ===
[3, 30, 34, 5, 9] dan eng katta son: 9534330
oddiy teskari saralash: 9534303 ← noto'g'ri
=== 3. O'zbek alifbosi bo'yicha saralash ===
sorted() (Unicode kodlari): ['anor', 'choy', "g'isht", 'gilos', 'nok', "o'rik", 'olma', 'sabzi', 'shaftoli', 'zira']
o'zbek alifbosi: ['anor', 'gilos', 'nok', 'olma', 'sabzi', 'zira', "o'rik", "g'isht", 'shaftoli', 'choy']
cmp_to_key bilan bir xil: True
=== 4. reduce ===
lug'atlarni birlashtirish: {'host': 'localhost', 'port': 6543, 'debug': True}
funksiyalar kompozitsiyasi: 'salom dunyo'
bo'sh ro'yxat: TypeError: reduce() of empty iterable with no initial value
boshlang'ich qiymat bilan: 0Nima ko'rsatdi: 2.5, 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: valyuta xizmati
Kirishdagi xizmatni to'g'ri quramiz va functools vositalarini birgalikda ishlatamiz: total_ordering li Pul turi, lru_cache(typed=True) va muddatli kesh bilan kurs olish, partial bilan tayyor konvertorlar, singledispatch bilan formatlash, wraps bilan statistika dekoratori, cached_property bilan hisobot va reduce bilan narx quvuri. Vaqt hozir parametri bilan beriladi — natija takrorlanadi.
"""Pul (total_ordering) + kurs kesh (lru_cache, TTL) + partial konvertorlar + singledispatch formatlash + wraps dekorator + cached_property hisobot + reduce quvur."""
import functools as ft
from dataclasses import dataclass
from decimal import ROUND_HALF_UP, Decimal
API_KURSLARI = {"USD": Decimal("12650.00"), "EUR": Decimal("13900.00"), "RUB": Decimal("152.50")}
API_CHAQIRUVLARI: list[str] = []
def statistika(funksiya):
@ft.wraps(funksiya)
def oram(*args, **kwargs):
oram.chaqiruvlar += 1
return funksiya(*args, **kwargs)
oram.chaqiruvlar = 0
return oram
@ft.total_ordering
@dataclass(frozen=True, eq=False)
class Pul:
miqdor: Decimal
valyuta: str = "UZS"
def __eq__(self, boshqa: object) -> bool:
if not isinstance(boshqa, Pul):
return NotImplemented
return somga(self).miqdor == somga(boshqa).miqdor
def __lt__(self, boshqa: object) -> bool:
if not isinstance(boshqa, Pul):
return NotImplemented
return somga(self).miqdor < somga(boshqa).miqdor
def __hash__(self) -> int:
return hash(somga(self).miqdor)
@ft.lru_cache(maxsize=128, typed=True)
def _kurs_oynasi(valyuta: str, oyna: int) -> Decimal:
API_CHAQIRUVLARI.append(f"{valyuta}@{oyna}")
return API_KURSLARI[valyuta]
def kurs(valyuta: str, hozir: float, ttl: int = 300) -> Decimal:
if valyuta == "UZS":
return Decimal(1)
return _kurs_oynasi(valyuta, int(hozir // ttl)) # TTL: har 5 daqiqada yangi kalit
HOZIR = 1_789_635_600.0
def somga(pul: Pul, hozir: float = HOZIR) -> Pul:
miqdor = (pul.miqdor * kurs(pul.valyuta, hozir)).quantize(Decimal("1"), ROUND_HALF_UP)
return Pul(miqdor, "UZS")
@statistika
def konvert(pul: Pul, maqsad: str, hozir: float = HOZIR) -> Pul:
som = somga(pul, hozir).miqdor
return Pul((som / kurs(maqsad, hozir)).quantize(Decimal("0.01"), ROUND_HALF_UP), maqsad)
dollarga = ft.partial(konvert, maqsad="USD")
yevroga = ft.partial(konvert, maqsad="EUR")
@ft.singledispatch
def korsat(x: object) -> str:
return str(x)
@korsat.register
def _(x: Pul) -> str:
butun = f"{x.miqdor:,.2f}".replace(",", " ") if x.valyuta != "UZS" else f"{x.miqdor:,.0f}".replace(",", " ")
return f"{butun} {x.valyuta}"
@korsat.register
def _(x: list) -> str:
return "; ".join(korsat(e) for e in x)
class Hisobot:
def __init__(self, tolovlar: list[Pul]) -> None:
self.tolovlar = tolovlar
self.hisoblashlar = 0
@ft.cached_property
def jami_som(self) -> Pul:
self.hisoblashlar += 1
return Pul(sum((somga(t).miqdor for t in self.tolovlar), Decimal(0)))
def main() -> None:
print("=== 1. Pul va taqqoslash ===")
narx_usd, narx_eur, narx_som = Pul(Decimal("100"), "USD"), Pul(Decimal("90"), "EUR"), Pul(Decimal("1260000"))
print(f" 100 USD = {korsat(somga(narx_usd))}, 90 EUR = {korsat(somga(narx_eur))}")
print(f" eng arzoni: {korsat(min(narx_usd, narx_eur, narx_som))}")
print(f" saralangan: {korsat(sorted([narx_usd, narx_eur, narx_som]))}")
print(f" 100 USD >= 1 265 000 so'm: {narx_usd >= Pul(Decimal('1265000'))}")
print("\n=== 2. Kesh va TTL ===")
API_CHAQIRUVLARI.clear()
_kurs_oynasi.cache_clear() # 1-bo'lim taqqoslashlari keshni to'ldirgan edi
for soniya in (0, 10, 299, 300, 305):
kurs("USD", HOZIR + soniya)
print(f" 5 so'rov, API chaqiruvlari: {len(API_CHAQIRUVLARI)} (oynalar: {API_CHAQIRUVLARI})")
print(f" {_kurs_oynasi.cache_info()}")
print("\n=== 3. partial konvertorlar va wraps ===")
print(f" 1 000 000 so'm → {korsat(dollarga(Pul(Decimal('1000000'))))}")
print(f" 250 USD → {korsat(yevroga(Pul(Decimal('250'), 'USD')))}")
print(f" konvert.__name__ = {konvert.__name__}, chaqiruvlar = {konvert.chaqiruvlar}")
print(f" dollarga.func is konvert: {dollarga.func is konvert}, keywords: {dollarga.keywords}")
print("\n=== 4. cached_property hisobot ===")
hisobot = Hisobot([narx_usd, narx_eur, narx_som, Pul(Decimal("5000"), "RUB")])
for _ in range(3):
jami = hisobot.jami_som
print(f" jami: {korsat(jami)}, hisoblashlar: {hisobot.hisoblashlar}")
del hisobot.jami_som
print(f" del dan keyin qayta: {korsat(hisobot.jami_som)}, hisoblashlar: {hisobot.hisoblashlar}")
print("\n=== 5. reduce: narx quvuri ===")
bosqichlar = [
("chegirma 10%", lambda p: Pul((p.miqdor * Decimal("0.90")).quantize(Decimal("1")), p.valyuta)),
("QQS 12%", lambda p: Pul((p.miqdor * Decimal("1.12")).quantize(Decimal("1")), p.valyuta)),
("yetkazish +25 000", lambda p: Pul(p.miqdor + 25_000, p.valyuta)),
]
boshlangich = somga(narx_usd)
yakuniy = ft.reduce(lambda pul, bosqich: bosqich[1](pul), bosqichlar, boshlangich)
print(f" {korsat(boshlangich)} → {' → '.join(nom for nom, _ in bosqichlar)} → {korsat(yakuniy)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Pul va taqqoslash ===
100 USD = 1 265 000 UZS, 90 EUR = 1 251 000 UZS
eng arzoni: 90.00 EUR
saralangan: 90.00 EUR; 1 260 000 UZS; 100.00 USD
100 USD >= 1 265 000 so'm: True
=== 2. Kesh va TTL ===
5 so'rov, API chaqiruvlari: 2 (oynalar: ['USD@5965452', 'USD@5965453'])
CacheInfo(hits=3, misses=2, maxsize=128, currsize=2)
=== 3. partial konvertorlar va wraps ===
1 000 000 so'm → 79.05 USD
250 USD → 227.52 EUR
konvert.__name__ = konvert, chaqiruvlar = 2
dollarga.func is konvert: True, keywords: {'maqsad': 'USD'}
=== 4. cached_property hisobot ===
jami: 4 538 500 UZS, hisoblashlar: 1
del dan keyin qayta: 4 538 500 UZS, hisoblashlar: 2
=== 5. reduce: narx quvuri ===
1 265 000 UZS → chegirma 10% → QQS 12% → yetkazish +25 000 → 1 300 120 UZSNima ko'rsatdi: 2.1–2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"@cache istalgan funksiyaga qo'yiladi" |
async def da korutina keshlanadi — RuntimeError |
"lru_cache bilan funksiya bir marta bajariladi" |
Bir vaqtdagi chaqiruvlarda bir necha marta |
"cached_property ip-xavfsiz" |
3.12 dan beri qulfsiz |
"cache da 1, 1.0, True doim bir kalit" |
Tezkor yo'lga bog'liq — typed=True bilan aniq |
"singledispatch doim eng mosini topadi" |
Teng mos ABC larda RuntimeError |
"bool uchun int realizatsiyasi ishlamaydi" |
Ishlaydi — bool int vorisi |
"total_ordering bepul" |
Yasalgan metodlar sekinroq |
"cmp_to_key — key bilan bir xil tezlik" |
key tezroq; cmp_to_key — kalit yasab bo'lmaganda |
6. Keng tarqalgan xatolar va yechimlari
1. async funksiyaga @cache
@cache
async def ol(x): ... # ❌
# ✅ natijani lug'atda saqlash + asyncio.Lock (Misol 1)2. Stampede
@lru_cache
def tashqi_api(k): ... # ⚠️ bo'sh keshda parallel chaqiruvlar
# ✅ kalit bo'yicha qulf yoki kesh oldindan to'ldirilishi3. __slots__ va cached_property
class A:
__slots__ = ("x",)
@cached_property
def y(self): ... # ❌ TypeError4. Teng mos ABC lar
@f.register
def _(x: Sized): ...
@f.register
def _(x: Iterable): ... # ⚠️ list → RuntimeError
@f.register
def _(x: Collection): ... # ✅5. singledispatchmethod bezaklari tartibi
@classmethod
@singledispatchmethod # ❌
@singledispatchmethod
@classmethod # ✅6. Qiymat turiga bog'liq keshlash
@cache
def formatla(x): return f"{type(x).__name__}:{x}" # ❌ 1.0 va True aralashadi
@lru_cache(typed=True) # ✅7. reduce bilan yig'indi
reduce(operator.add, sonlar) # ❌ bo'shda xato, sekin
sum(sonlar) # ✅8. Kalit yasash mumkin bo'lganda cmp_to_key
sorted(xs, key=cmp_to_key(lambda a, b: a.yosh - b.yosh)) # ❌
sorted(xs, key=lambda a: a.yosh) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8.9, 8.12, 8.15-darslar (o'tilgan):
singledispatch,total_ordering,cached_property - 10.11, 10.13-darslar (o'tilgan):
wraps,cache,partial,reduce - 14.3, 14.6-darslar (o'tilgan): iplar,
asyncio.Lock - 15.7-dars (o'tilgan): LRU kesh
OrderedDictbilan - 18.7-dars: profiling — keshlash foydasini o'lchash
- 29.3-dars: kesh strategiyalari — stampede
- 23.10-dars: Redis va kesh — taqsimlangan kesh
8. Eng yaxshi amaliyotlar
Keshni qo'yishdan oldin so'rang: funksiya sofmi, argumentlari xeshlanadimi, konkurent chaqiriladimi,
asyncmi?Tur muhim —
typed=True.Tashqi resurs keshida — stampede himoyasi.
singledispatch— umumiyroq ABC dan aniqrog'iga qarab ro'yxatdan o'tkazing vadispatch()bilan tekshiring."Issiq" taqqoslashlarda
total_orderingo'rniga qo'lda yokidataclass(order=True).key— birinchi tanlov,cmp_to_key— faqat kalit yasab bo'lmaganda.reduce— kompozitsiya va birlashtirish uchun; yig'indi va ko'paytma uchun o'rnatilgan funksiyalar.Vaqtga bog'liq keshlarni
hozirparametri bilan testlanadigan qiling.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import functools as ft
1. print(ft.reduce(lambda a, b: a * b, [1, 2, 3, 4]))
2. print(ft.reduce(lambda a, b: a + b, [], 10))
3. print(ft.partial(pow, 2)(5))
4. print(ft.partial(int, base=16)("ff"))
5. @ft.singledispatch
def f(x): return "obj"
@f.register
def _(x: int): return "int"
print(f(True), f(2.0))
6. @ft.lru_cache(typed=True)
def g(x): return type(x).__name__
print(g(1), g(1.0))
7. print(sorted([3, 1, 2], key=ft.cmp_to_key(lambda a, b: b - a)))
8. @ft.total_ordering
class A:
def __init__(self, v): self.v = v
def __eq__(self, o): return self.v == o.v
def __lt__(self, o): return self.v < o.v
print(A(2) >= A(1), A(1) > A(1))
9. class B:
@ft.cached_property
def x(self): return [1]
b = B(); print(b.x is b.x)
10. @ft.cache
def h(n): return n
h(1); h(1); print(h.cache_info().hits)
11. print(ft.reduce(lambda acc, s: acc | s, [{1}, {2}, {1, 3}], set()))
12. @ft.singledispatch
def k(x): return "obj"
@k.register
def _(x: int | str): return "int|str"
print(k("a"), k(3), k(3.0))Javoblar
241032255int obj—boolintvorisiint float[3, 2, 1]True FalseTrue1{1, 2, 3}int|str int|str obj
Vazifa 2: Xatolarni tuzating
1. @functools.cache
async def foydalanuvchi(id_):
return await db.ol(id_)
2. class Model:
__slots__ = ("vaznlar",)
@functools.cached_property
def norma(self):
return hisobla(self.vaznlar)
3. @functools.singledispatch
def serializatsiya(x): raise TypeError(x)
@serializatsiya.register
def _(x: Sized): ...
@serializatsiya.register
def _(x: Iterable): ...
serializatsiya([1, 2])
4. @functools.cache
def kalit_tavsifi(x):
return f"{type(x).__name__}={x}"
kalit_tavsifi(1); kalit_tavsifi(True)
5. class Eksport:
@classmethod
@functools.singledispatchmethod
def yoz(cls, x): ...Javoblar
1. _natijalar, _qulflar = {}, {}
async def foydalanuvchi(id_):
if id_ in _natijalar:
return _natijalar[id_]
async with _qulflar.setdefault(id_, asyncio.Lock()):
if id_ not in _natijalar:
_natijalar[id_] = await db.ol(id_)
return _natijalar[id_]
2. class Model:
__slots__ = ("vaznlar", "__dict__") # yoki cached_property o'rniga
@functools.cached_property # oddiy metod + lru_cache
def norma(self):
return hisobla(self.vaznlar)
3. @serializatsiya.register
def _(x: Collection): ... # yoki list va tuple uchun aniq realizatsiyalar
4. @functools.lru_cache(typed=True)
def kalit_tavsifi(x):
return f"{type(x).__name__}={x}"
5. class Eksport:
@functools.singledispatchmethod
@classmethod
def yoz(cls, x): ...Vazifa 3: Muddatli kesh dekoratori
@ttl_kesh(soniya=60, maxsize=256) dekoratorini yozing:
lru_cacheustida — vaqt oynasi kalitga qo'shilsin (Misol 4 g'oyasi)hozirfunksiyasini sozlash mumkin bo'lsin (testlar uchun)cache_info()vacache_clear()ishlasin,wrapsbilan metama'lumot saqlansin- Kalit bo'yicha qulf bilan stampede himoyasi
async deffunksiyalar uchun alohida variant
Vazifa 4: Tur bo'yicha JSON serializatori
singledispatch bilan jsonga(x):
int,float,str,bool,None,Decimal,date,datetime(ISO, aware UTC)MappingvaSequence— rekursiv (strni ketma-ketlik deb olmang!)dataclasslar —dataclasses.asdictorqali- Noma'lum tur —
TypeErroraniq xabar bilan - Noaniq tanlov holatlarini
dispatch()bilan testlang
Vazifa 5: O'zbek alifbosi bo'yicha lug'at
- Misol 3 dagi kalitni kengaytiring: katta harflar,
ʼ(tutuq belgisi), defis - 500 ta so'zni saralang va
keyhamdacmp_to_keytezligini solishtiring lru_cachebilan kalit hisoblashni keshlash foyda beradimi — o'lchang- Natijani rasmiy imlo lug'ati tartibi bilan solishtiring
Vazifa 6: functools vositalarini o'zingiz yozing
mening_partial—func,args,keywordsatributlari bilanmening_lru_cache(maxsize)—OrderedDictasosida (15.7)mening_singledispatch— faqat aniq tur va MRO bo'yicha (ABC siz)mening_total_ordering—__lt__va__eq__dan qolganlari- Har biri uchun asl bilan solishtiruvchi testlar
Vazifa 7: O'ylash
Python 3.12 da cached_property ichidagi qulf olib tashlandi. Avval u sinf darajasidagi bitta qulf edi: bir obyektning xususiyati hisoblanayotganda, boshqa obyektlarning ham shu xususiyati kutib turardi. Nega bu qaror qabul qilindi va "ip-xavfsizlik" kafolatini olib tashlash qachon to'g'ri muhandislik qarori bo'ladi?
Javob
Qisqa javob: Qulf noto'g'ri darajada edi: u ip-xavfsizlikni ta'minlash o'rniga barcha obyektlar orasida keraksiz raqobat yaratardi — ko'p ipli dasturlarda sekinlik va hatto blokirovkaga olib kelardi. Kafolat faqat qisman ishlagani uchun uni olib tashlab, zarur joyda ilova darajasida aniq qulf qo'yish tavsiya qilindi. Noto'g'ri yoki qimmat kafolat — kafolatsizlikdan yomonroq bo'lishi mumkin.
1. Eski dizaynning muammosi
| Muammo | Tafsilot |
|---|---|
| Sinf darajasidagi qulf | A() va B() — ikki xil obyekt, lekin biri hisoblanayotganda ikkinchisi kutadi |
| Parallellik yo'qoladi | 100 ta so'rov, har biri o'z obyekti — ketma-ket bajariladi |
| Blokirovka xavfi | Hisoblash ichida boshqa cached_property ga murojaat qilinsa |
| Kafolat to'liq emas edi | __set_name__ va meros bilan chegaraviy holatlar |
2. Nega olib tashlandi
- Ko'p ipli ilovalarda (veb-serverlar) haqiqiy sekinlik haqida xabarlar
- Obyekt darajasidagi qulf qo'shish — har obyektga xotira narxi va murakkablik
- Aksariyat foydalanish holatlari bir ipli — qulf ular uchun ortiqcha narx
- Takroriy hisoblash odatda zararsiz (sof funksiya) — faqat vaqt yo'qoladi
- Zararli holatlar (tashqi resurs, yon ta'sir) — ilova qulfni o'zi qo'yishi aniqroq
3. Kafolatni olib tashlash qachon to'g'ri
| Belgi | Izoh |
|---|---|
| Kafolat ko'pchilik uchun keraksiz narx | Oddiy holatni sekinlashtiradi |
| Kafolat to'liq emas | Foydalanuvchini noto'g'ri ishonchga soladi |
| To'g'ri daraja ilovaga ma'lum | Kutubxona uni taxmin qila olmaydi |
| Muqobil oson | Aniq qulf — bir necha qator |
| Hujjatlashtirilgan | O'zgarish "What's New" da e'lon qilingan |
4. O'xshash qarorlar
lru_cachehech qachon "bir marta bajarish"ni kafolatlamagan — faqat ichki tuzilma butunliginidictamallari GIL tufayli atomar, lekin "o'qish → o'zgartirish → yozish" emas (14.3-dars)- Free-threading (3.13t) davrida bunday kafolatlar yana qayta ko'rib chiqilmoqda
5. Amaliy xulosa
- Standart kutubxona vositasining konkurentlik kafolatini hujjatdan tekshiring
- Takroriy hisoblash zararsizmi? — ha bo'lsa, qulf kerak emas
- Zararli bo'lsa (API limiti, pul, yon ta'sir) — kalit yoki obyekt darajasidagi o'z qulfingiz
- O'z kutubxonangizda: yarim kafolatdan ko'ra aniq hujjatlashtirilgan "kafolat yo'q" yaxshiroq
Nimani mustahkamlaydi: 2.1–2.7-bo'limlar.
Xulosa
Bu darsda functools modulini yakuniy xarita sifatida ko'rib chiqdik va konkurentlik bilan bog'liq nozik joylarni o'lchadik.
Eng muhim uch fikr:
Kesh va konkurentlik.
@cacheniasync defga qo'yish korutina obyektini keshlaydi — ikkinchiawaitRuntimeErrorberadi; to'g'ri yo'l — natijani saqlash vaasyncio.Lock.lru_cachenatija butunligini kafolatlaydi, lekin bo'sh keshda bir vaqtdagi chaqiruvlar funksiyani bir necha marta bajaradi (stampede) — tashqi resurs uchun kalit bo'yicha qulf kerak.cached_property3.12 dan beri qulfsiz va__slots__bilan ishlamaydi. Natija argument turiga bog'liq bo'lsa —typed=True.singledispatch— MRO va ABC. Yuborish sinf ierarxiyasi va ABC lar bo'yicha ishlaydi:boolintrealizatsiyasini oladi,int | floatikkala turni ro'yxatga oladi. Lekin teng darajada mos ABC lar (SizedvaIterable) oddiylistda hamRuntimeErrorberadi — umumiyroqCollectionyoki aniq tur bilan hal qilinadi;dispatch()tanlovni oldindan tekshirish imkonini beradi.Vositalar birgalikda.
total_orderingqulay, lekin yasalgan metodlar sekinroq;cmp_to_keyfaqat kalit yasab bo'lmaganda (eng katta son masalasi), aks holdakey— masalan, o'zbek alifbosi bo'yicha saralash;reduce— lug'atlarni birlashtirish va funksiyalar kompozitsiyasi uchun. Valyuta xizmati misolida bularning hammasipartial,wrapsva muddatlilru_cachebilan bitta tizimga birlashdi.
Keyingi darsda os va sys modullariga o'tamiz: muhit o'zgaruvchilari, jarayon ma'lumotlari, buyruq qatori argumentlari va platformalar orasidagi farqlar.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!