Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Yaratish
- 2.2. Nega hashlanadi
- 2.3. Nima bor va nima yo'q
- 2.4. set va frozenset aralashuvi
- 2.5. Xotira va tezlik
- 2.6. frozenset vs tuple
- 2.7. Amaliy naqshlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Asoslar va farqlar
- Misol 2 — Konstanta optimallashtirish
- Misol 3 — frozenset vs tuple
- Misol 4 — Amaliy: teglar tizimi
- 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
6.9-dars: frozenset — o'zgarmas to'plam
6-QISM — MA'LUMOT TUZILMALARI · 9-dars
1. Kirish va motivatsiya
To'plam elementlari hashlanishi kerak (6.7-dars). Lekin to'plamning o'zi hashlanmaydi:
{1, 2} # ✅ to'plam
{{1, 2}} # ❌ TypeError: unhashable type: 'set'
{{1, 2}: "qiymat"} # ❌ TypeErrorYa'ni to'plamlar to'plami yoki to'plam kaliti yaratib bo'lmaydi. Bu — real muammo:
# Guruhlarni saqlash
guruhlar = {
{"Aziz", "Bobur"}, # ❌
{"Aziza", "Dilnoza"},
}
# Kesh: qaysi teglar kombinatsiyasi qaysi natijani beradi
kesh = {
{"python", "veb"}: [...], # ❌
}Yechim — frozenset:
guruhlar = {
frozenset({"Aziz", "Bobur"}), # ✅
frozenset({"Aziza", "Dilnoza"}),
}
kesh = {
frozenset({"python", "veb"}): [...], # ✅
}frozenset — set ning o'zgarmas versiyasi. tuple list ga qanday munosabatda bo'lsa, frozenset set ga shunday munosabatda.
Bu darsda:
frozensetyaratish va farqlari- Nega hashlanadi va hash qanday hisoblanadi
- Barcha amallar (
setbilan bir xil,-updatemetodlarisiz) setvafrozensetaralashuvi — qaysi tur qaytadi- Amaliy naqshlar: kesh kaliti, guruhlar, o'zgarmas konfiguratsiya
frozensetvstuple— qachon qaysi biri
2. Nazariya — chuqur tushuntirish
2.1. Yaratish
Faqat konstruktor bilan — maxsus sintaksis yo'q:
frozenset() # bo'sh
frozenset([1, 2, 3]) # ro'yxatdan
frozenset({1, 2, 3}) # to'plamdan
frozenset("abc") # {'a', 'b', 'c'}
frozenset(range(3)) # {0, 1, 2}
frozenset({"a": 1}) # {'a'} — kalitlar
frozenset(x for x in [1, 2]) # generatordanYo'q:
f{1, 2} # ❌ bunday sintaksis yo'q
frozen{1, 2} # ❌tuple da (1, 2) bor, frozenset da esa hech narsa yo'q. Sabab: frozenset ancha kam ishlatiladi, alohida sintaksis berish tilni murakkablashtirardi.
repr shakli:
print(frozenset([1, 2, 3])) # frozenset({1, 2, 3})
print(frozenset()) # frozenset()Bo'sh frozenset — singleton emas (endi):
a = frozenset()
b = frozenset([])
print(a is b) # False — Python 3.14 daEski CPython versiyalarida bo'sh frozenset yagona obyekt edi va bu True qaytarardi; hozir unday emas. Bo'sh tuple esa hamon yagona obyekt. Bu — amalga oshiruv tafsiloti: to'plamlarni doim == bilan solishtiring.
2.2. Nega hashlanadi
frozenset o'zgarmas → hash barqaror → hashlanadi.
f = frozenset([1, 2, 3])
hash(f) # ✅ ishlaydi
{f} # ✅ to'plam ichida
{f: "qiymat"} # ✅ lug'at kalitiHash tartibga bog'liq emas:
hash(frozenset([1, 2, 3])) == hash(frozenset([3, 2, 1])) # True
frozenset([1, 2, 3]) == frozenset([3, 2, 1]) # TrueBu — tuple dan asosiy farq:
(1, 2, 3) == (3, 2, 1) # False — tartib muhim
hash((1,2,3)) == hash((3,2,1)) # FalseQanday hisoblanadi:
CPython frozenset hash'ini elementlar hash'laridan tartibdan mustaqil funksiya bilan hisoblaydi (XOR va aralashtirish asosida):
# Soddalashtirilgan g'oya:
h = 0
for x in elementlar:
h ^= aralashtir(hash(x)) # XOR — kommutativ va assotsiativXOR kommutativ bo'lgani uchun tartib ahamiyatsiz. Amalda CPython murakkabroq aralashtirish ishlatadi — to'qnashuvlarni kamaytirish uchun.
Elementlar hashlanishi kerak:
frozenset([1, 2]) # ✅
frozenset([[1, 2]]) # ❌ TypeError: unhashable type: 'list'
frozenset([{1, 2}]) # ❌ set hashlanmaydi
frozenset([frozenset([1, 2])]) # ✅ ichma-ich frozensetHash keshlanadi:
f = frozenset(range(1_000_000))
hash(f) # birinchi marta — O(n)
hash(f) # keyin — O(1), keshdanCPython hash'ni obyekt ichida saqlaydi. Shuning uchun katta frozenset ni lug'at kaliti sifatida ishlatish samarali.
2.3. Nima bor va nima yo'q
Ishlaydi (o'zgartirmaydigan hamma narsa):
f = frozenset([1, 2, 3])
g = frozenset([3, 4])
len(f) # 3
2 in f # True
for x in f: ... # iteratsiya
f | g, f & g, f - g, f ^ g # amallar
f <= g, f < g, f >= g, f > g # solishtirish
f.isdisjoint(g)
f.union(g), f.intersection(g)
f.difference(g), f.symmetric_difference(g)
f.issubset(g), f.issuperset(g)
f.copy()
min(f), max(f), sum(f), sorted(f)
hash(f) # ⭐ set da yo'qYo'q (barcha o'zgartiruvchi metodlar):
f.add(4) # ❌ AttributeError
f.remove(1) # ❌
f.discard(1) # ❌
f.pop() # ❌
f.clear() # ❌
f.update(g) # ❌
f.intersection_update(g) # ❌
f |= g # ❌ TypeErrorMetodlar solishtirilishi:
set_metodlari = {m for m in dir(set) if not m.startswith("_")}
frozenset_metodlari = {m for m in dir(frozenset) if not m.startswith("_")}
print(sorted(set_metodlari - frozenset_metodlari))
# ['add', 'clear', 'difference_update', 'discard',
# 'intersection_update', 'pop', 'remove',
# 'symmetric_difference_update', 'update']
print(sorted(frozenset_metodlari - set_metodlari))
# [] ← frozenset da qo'shimcha metod YO'Q copy() — frozenset uchun o'zini qaytaradi:
f = frozenset([1, 2])
f.copy() is f # True — nusxa kerak emas, o'zgarmastuple da ham shunday: o'zgarmas obyektni nusxalash ma'nosiz.
2.4. set va frozenset aralashuvi
Bu — eng nozik mavzu. Qaysi tur qaytadi?
Qoida: CHAP operandning turi.
s = {1, 2}
f = frozenset([2, 3])
type(s | f) # set ← chap set
type(f | s) # frozenset ← chap frozenset
type(s & f) # set
type(f & s) # frozenset
type(s - f) # set
type(f - s) # frozensetMetodlar bilan ham shunday:
type(s.union(f)) # set
type(f.union(s)) # frozensetSolishtirish tur bilan bog'liq emas:
{1, 2} == frozenset([1, 2]) # True ⭐
{1, 2} <= frozenset([1, 2, 3]) # True
hash({1,2}) == hash(frozenset([1,2])) # ❌ set hashlanmaydi set va frozenset teng bo'lishi mumkin — bu list va tuple dan farqli:
[1, 2] == (1, 2) # False
{1, 2} == frozenset([1, 2]) # True ⭐Sabab: ikkalasi ham collections.abc.Set ABC ni amalga oshiradi va tenglik faqat elementlarga qaraydi.
Amaliy oqibat — lug'atda:
d = {frozenset([1, 2]): "qiymat"}
d[frozenset([1, 2])] # ✅ "qiymat"
d[{1, 2}] # ❌ TypeError: unhashable type: 'set'Teng bo'lsa ham, set hashlanmagani uchun kalit sifatida ishlamaydi.
Joyida amallar:
s = {1, 2}
s |= frozenset([3]) # ✅ s — set, o'zgaruvchan
print(type(s)) # set
f = frozenset([1, 2])
f |= {3} # ⚠️ ishlaydi, lekin YANGI obyekt
print(type(f)) # frozensetOxirgi holat tuple dagi += bilan bir xil: f |= {3} aslida f = f | {3}.
2.5. Xotira va tezlik
import sys
sys.getsizeof(set([1, 2, 3])) # 216
sys.getsizeof(frozenset([1, 2, 3])) # 216Xotira deyarli bir xil — ichki tuzilma bir xil hash jadvali.
Tezlik:
| Amal | set vs frozenset |
|---|---|
| Yaratish | Bir xil |
in |
Bir xil |
| Amallar | Bir xil |
hash() |
Faqat frozenset |
frozenset set dan tezroq emas. tuple list dan yaratishda tezroq edi (konstanta optimallashtirish), lekin frozenset uchun bunday optimallashtirish yo'q — chunki u literal sintaksisga ega emas.
# Konstanta frozenset kompilyatsiya paytida yaratilmaydi
%timeit frozenset([1, 2, 3]) # ~150 ns
%timeit {1, 2, 3} # ~50 ns Bitta istisno: in tekshiruvida CPython optimallashtirishi bor:
if x in {1, 2, 3}: # konstanta to'plam → frozenset ga aylantiriladi!
...import dis
dis.dis("x in {1, 2, 3}")
# LOAD_CONST (frozenset({1, 2, 3})) ← frozenset!
# CONTAINS_OPPeephole optimizator konstanta set ni frozenset ga aylantiradi va uni konstanta sifatida saqlaydi. Bu — haqiqiy tezlik yutug'i:
# ✅ Har chaqiruvda to'plam qayta yaratilmaydi
def tekshir(x):
return x in {"a", "b", "c"}
# Aynan shunday tez:
RUXSAT = frozenset({"a", "b", "c"})
def tekshir(x):
return x in RUXSATFaqat konstantalar uchun:
x in {1, 2, 3} # ✅ optimallashtiriladi
x in {a, b, c} # ❌ o'zgaruvchilar — har safar quriladi2.6. frozenset vs tuple
Ikkalasi ham o'zgarmas va hashlanadi. Farqi:
tuple |
frozenset |
|
|---|---|---|
| Tartib | Muhim | Yo'q |
| Takrorlar | ||
| Indeks | t[0] |
|
in |
O(n) | O(1) |
| To'plam amallari | ||
| Xotira (3 element) | 64 B | 216 B |
| Yaratish | Tezroq | Sekinroq |
| Hash tartibga bog'liq |
Qachon tuple:
# Tartib muhim
koordinata = (10, 20)
kesh[(foydalanuvchi_id, sahifa, versiya)] = natija
# Kam element, tartib bilan
rgb = (255, 0, 0)Qachon frozenset:
# Tartib muhim EMAS, tarkib muhim
teglar = frozenset({"python", "veb"})
# {"python","veb"} va {"veb","python"} — BIR XIL kalit
# Ko'p element + `in` kerak
RUXSAT_ETILGAN = frozenset({...100 element...})
# To'plam amallari kerak
guruh_a & guruh_bAsosiy farq — kanonik shakl:
# tuple bilan
kesh[("python", "veb")] = 1
kesh[("veb", "python")] # ❌ KeyError — boshqa kalit
# frozenset bilan
kesh[frozenset(["python", "veb"])] = 1
kesh[frozenset(["veb", "python"])] # ✅ 1 — bir xil kalitTartibsiz to'plamni kalit sifatida ishlatish kerak bo'lsa, frozenset — yagona to'g'ri tanlov. (Muqobil: tuple(sorted(...)) — lekin u sekinroq va elementlar solishtirilishi kerak.)
2.7. Amaliy naqshlar
1. To'plamlar to'plami:
guruhlar = {
frozenset({"Aziz", "Bobur"}),
frozenset({"Aziza", "Dilnoza"}),
frozenset({"Bobur", "Aziz"}), # ⚠️ birinchisi bilan bir xil!
}
print(len(guruhlar)) # 2 — takror yo'qoldi2. Tartibsiz kesh kaliti:
from functools import lru_cache
def kesh_kaliti(**kwargs) -> frozenset:
return frozenset(kwargs.items())
KESH = {}
def qidiruv(**filtrlar):
kalit = frozenset(filtrlar.items())
if kalit in KESH:
return KESH[kalit]
natija = ogir_hisob(**filtrlar)
KESH[kalit] = natija
return natija
qidiruv(shahar="Toshkent", yil=2026)
qidiruv(yil=2026, shahar="Toshkent") # ✅ keshdan!3. O'zgarmas konfiguratsiya:
class Sozlamalar:
RUXSAT_ETILGAN_TURLAR = frozenset({"jpg", "png", "webp"})
XAVFLI_KENGAYTMALAR = frozenset({"exe", "bat", "sh", "dll"})
Sozlamalar.RUXSAT_ETILGAN_TURLAR.add("exe") # ❌ AttributeError ✅set bo'lganda bu jimgina ishlab ketardi — xavfsizlik teshigi.
4. Grafik — qirralar (yo'naltirilmagan):
qirralar = {
frozenset({"A", "B"}),
frozenset({"B", "C"}),
frozenset({"B", "A"}), # ⚠️ birinchisi bilan bir xil
}
print(len(qirralar)) # 2Yo'naltirilmagan grafda A→B va B→A bir xil qirra. frozenset buni tabiiy ifodalaydi.
5. Sinf atributi sifatida:
class Hujjat:
HOLATLAR = frozenset({"qoralama", "korikda", "chop_etilgan"})
def __init__(self, holat: str):
if holat not in self.HOLATLAR:
raise ValueError(f"Noto'g'ri holat: {holat}")
self.holat = holat6. Sukut argument qiymati:
def qayta_ishla(malumot, teglar=frozenset()): # ✅ xavfsiz
...
def qayta_ishla(malumot, teglar=set()): # ⚠️ o'zgaruvchan sukut
...O'zgaruvchan sukut argument — Pythondagi klassik tuzoq (7-qism).
7. dict qiymati sifatida — o'zgarmas kafolat:
ROL_RUXSATLARI = {
"admin": frozenset({"oqish", "yozish", "ochirish"}),
"user": frozenset({"oqish"}),
}
# Foydalanuvchi kodini tasodifan o'zgartira olmaydi
ROL_RUXSATLARI["user"].add("ochirish") # ❌ AttributeError ✅3. Tez ma'lumotnoma
Yaratish
frozenset() bo'sh
frozenset([1, 2]) iterable'dan
frozenset("abc") {'a','b','c'}
frozenset({1, 2}) set'dan
⚠️ Maxsus sintaksis YO'Q — faqat konstruktorHashlanadi
hash(f) ✅
{f}, {f: "qiymat"} ✅
hash(frozenset([1,2])) ==
hash(frozenset([2,1])) True — tartib MUHIM EMAS
Solishtiring:
hash((1,2)) == hash((2,1)) False — tuple da tartib muhimNima yo'q
add, remove, discard, pop, clear,
update, *_update metodlari, |=, &=, -=, ^=
f.copy() is f True — o'zgarmasAralashuv — CHAP operand turi
{1,2} | frozenset([3]) → set
frozenset([1]) | {2} → frozenset
{1,2} == frozenset([1,2]) True ⭐ teng!
d[{1,2}] ❌ set hashlanmaydiKonstanta optimallashtirish
if x in {1, 2, 3}: → LOAD_CONST frozenset({1,2,3})
konstanta, har safar qurilmaydi ⭐
if x in {a, b, c}: → har safar quriladifrozenset vs tuple
tartib muhim, kam element → tuple
tartib muhim emas, `in` ko'p → frozenset
to'plam amallari kerak → frozenset
kanonik kalit kerak → frozenset ⭐4. Batafsil misollar
Misol 1 — Asoslar va farqlar
"""frozenset va set — barcha farqlar."""
import sys
print("=== 1. Yaratish ===")
USULLAR = [
("frozenset()", frozenset()),
("frozenset([1, 2, 3])", frozenset([1, 2, 3])),
("frozenset({1, 2, 3})", frozenset({1, 2, 3})),
("frozenset('abc')", frozenset("abc")),
("frozenset(range(3))", frozenset(range(3))),
("frozenset({'a': 1})", frozenset({"a": 1})),
("frozenset(x for x in [1,1,2])", frozenset(x for x in [1, 1, 2])),
]
for kod, f in USULLAR:
print(f" {kod:<34} → {f}")
print(f"\n ⚠️ Maxsus sintaksis yo'q — {{1,2}} har doim set")
print(f" Bo'sh frozenset yagona obyektmi 3.14-bob: "
f"frozenset() is frozenset([]) = {frozenset() is frozenset([])}")
print("\n=== 2. ⭐ Hashlanish ===")
f1 = frozenset([1, 2, 3])
f2 = frozenset([3, 2, 1])
s = {1, 2, 3}
t1, t2 = (1, 2, 3), (3, 2, 1)
print(f" frozenset([1,2,3]) == frozenset([3,2,1]): {f1 == f2}")
print(f" hash teng: {hash(f1) == hash(f2)}")
print(f"\n (1,2,3) == (3,2,1): {t1 == t2}")
print(f" hash teng: {hash(t1) == hash(t2)}")
print(f"""
⭐ frozenset hash'i TARTIBDAN MUSTAQIL —
u XOR asosida hisoblanadi (kommutativ amal).
tuple hash'i tartibga BOG'LIQ.
""")
print(f" set hashlanmaydi:")
try:
hash(s)
except TypeError as x:
print(f" hash({{1,2,3}}) → ❌ {x}")
print("\n=== 3. To'plamlar to'plami ===")
print(f" ❌ set bilan:")
try:
guruhlar = {{"Aziz", "Bobur"}, {"Aziza"}}
except TypeError as x:
print(f" {{{{'Aziz','Bobur'}}, ...}} → TypeError: {x}")
print(f"\n ✅ frozenset bilan:")
GURUHLAR = {
frozenset({"Aziz", "Bobur"}),
frozenset({"Aziza", "Dilnoza"}),
frozenset({"Bobur", "Aziz"}), # birinchisi bilan bir xil
frozenset({"Eldor"}),
}
print(f" 4 ta qo'shildi, qoldi: {len(GURUHLAR)}")
for g in sorted(GURUHLAR, key=lambda x: sorted(x)):
print(f" {sorted(g)}")
print(f"\n ⭐ {{'Aziz','Bobur'}} va {{'Bobur','Aziz'}} — BIR XIL frozenset")
print("\n=== 4. Metodlar farqi ===")
set_m = {m for m in dir(set) if not m.startswith("_")}
frozen_m = {m for m in dir(frozenset) if not m.startswith("_")}
print(f" set metodlari: {len(set_m)}")
print(f" frozenset metodlari: {len(frozen_m)}")
print(f"\n Faqat set da ({len(set_m - frozen_m)}):")
for m in sorted(set_m - frozen_m):
print(f" • {m}")
print(f"\n Faqat frozenset da: {sorted(frozen_m - set_m) or '— (yo`q)'}")
print(f" Umumiy ({len(set_m & frozen_m)}): {', '.join(sorted(set_m & frozen_m))}")
print("\n=== 5. O'zgartirishga urinish ===")
f = frozenset([1, 2, 3])
print(f" f = {f}\n")
URINISHLAR = [
("f.add(4)", lambda: f.add(4)),
("f.remove(1)", lambda: f.remove(1)),
("f.discard(1)", lambda: f.discard(1)),
("f.pop()", lambda: f.pop()),
("f.clear()", lambda: f.clear()),
("f.update({4})", lambda: f.update({4})),
]
for kod, fn in URINISHLAR:
try:
fn()
natija = "✅ ishladi (?!)"
except AttributeError as x:
natija = f"❌ AttributeError"
print(f" {kod:<18} {natija}")
print(f"\n ⚠️ |= ishlaydi, lekin YANGI obyekt yaratadi:")
g = frozenset([1, 2])
eski_id = id(g)
g |= {3}
print(f" f |= {{3}} → {g}, yangi obyektmi: {id(g) != eski_id}")
print(f"\n copy() — o'zini qaytaradi:")
h = frozenset([1, 2])
print(f" f.copy() is f → {h.copy() is h}")
print("\n=== 6. ⭐ Aralashuv — qaysi tur qaytadi ===")
s = {1, 2, 3}
f = frozenset([3, 4, 5])
AMALLAR = [
("s | f", s | f),
("f | s", f | s),
("s & f", s & f),
("f & s", f & s),
("s - f", s - f),
("f - s", f - s),
("s ^ f", s ^ f),
("f ^ s", f ^ s),
("s.union(f)", s.union(f)),
("f.union(s)", f.union(s)),
]
print(f" s = {s} (set), f = {f} (frozenset)\n")
print(f" {'Amal':<16} {'Turi':<12} Natija")
print(" " + "─" * 50)
for kod, natija in AMALLAR:
print(f" {kod:<16} {type(natija).__name__:<12} {sorted(natija)}")
print(f"""
⭐ Qoida: CHAP operandning turi qaytadi.
""")
print(f" Solishtirish tur bilan bog'liq emas:")
print(f" {{1,2}} == frozenset([1,2]): {({1,2}) == frozenset([1, 2])}")
print(f" {{1,2}} <= frozenset([1,2,3]): {({1,2}) <= frozenset([1, 2, 3])}")
print(f" [1,2] == (1,2): {[1, 2] == (1, 2)} ← list/tuple FARQLI")
print(f"\n ⚠️ Lekin lug'at kaliti sifatida:")
d = {frozenset([1, 2]): "qiymat"}
print(f" d[frozenset([1,2])] → {d[frozenset([1, 2])]!r}")
try:
d[{1, 2}]
except TypeError as x:
print(f" d[{{1,2}}] → ❌ {x}")
print("\n=== 7. Xotira ===")
print(f" {'n':>7} {'set':>9} {'frozenset':>11} {'tuple':>9}")
print(" " + "─" * 40)
for n in [0, 1, 3, 10, 100, 1000]:
s = set(range(n))
f = frozenset(range(n))
t = tuple(range(n))
print(f" {n:>7} {sys.getsizeof(s):>9,} {sys.getsizeof(f):>11,} "
f"{sys.getsizeof(t):>9,}")
print("""
⭐ set va frozenset — bir xil ichki tuzilma (hash jadvali).
tuple — oddiy massiv, ancha tejamli, lekin `in` O(n).
""")Natijaning muhim qismi:
=== 2. ⭐ Hashlanish ===
frozenset([1,2,3]) == frozenset([3,2,1]): True
hash teng: True
(1,2,3) == (3,2,1): False
hash teng: False
=== 4. Metodlar farqi ===
Faqat set da (9):
• add
• clear
• difference_update
• discard
• intersection_update
• pop
• remove
• symmetric_difference_update
• update
=== 6. ⭐ Aralashuv — qaysi tur qaytadi ===
Amal Turi Natija
──────────────────────────────────────────────────
s | f set [1, 2, 3, 4, 5]
f | s frozenset [1, 2, 3, 4, 5]
s & f set [3]
f & s frozenset [3]Nima ko'rsatdi: 2.1, 2.2, 2.3, 2.4, 2.5-bo'limlar.
Misol 2 — Konstanta optimallashtirish
"""Nega `x in {1, 2, 3}` tez."""
import dis
import timeit
print("=== 1. Bytecode ===")
print(" x in {1, 2, 3} (konstantalar):")
dis.dis("x in {1, 2, 3}")
print("\n x in {a, b, c} (o'zgaruvchilar):")
dis.dis("x in {a, b, c}")
print("""
⭐ Konstanta to'plam KOMPILYATSIYA paytida frozenset ga
aylantiriladi va LOAD_CONST bilan yuklanadi.
O'zgaruvchili to'plam har safar BUILD_SET bilan quriladi.
""")
print("\n=== 2. Tezlik farqi ===")
SOZLASH = """
a, b, c = 1, 2, 3
x = 2
KONSTANTA = frozenset({1, 2, 3})
ROYXAT = [1, 2, 3]
TUPLE = (1, 2, 3)
"""
SINOVLAR = [
("x in {1, 2, 3} konstanta set", "x in {1, 2, 3}"),
("x in {a, b, c} o'zgaruvchili", "x in {a, b, c}"),
("x in KONSTANTA oldindan", "x in KONSTANTA"),
("x in (1, 2, 3) tuple", "x in (1, 2, 3)"),
("x in [1, 2, 3] list", "x in [1, 2, 3]"),
("x in ROYXAT o'zgaruvchi list", "x in ROYXAT"),
]
natijalar = []
for nom, kod in SINOVLAR:
vaqt = timeit.timeit(kod, setup=SOZLASH, number=5_000_000)
natijalar.append((nom, vaqt))
eng_tez = min(v for _, v in natijalar)
print(f" 5M marta tekshiruv:\n")
print(f" {'Ifoda':<38} {'Vaqt':>9} {'Nisbat':>9}")
print(" " + "─" * 60)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
print(f" {nom:<38} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")
print("\n\n=== 3. Katta to'plamda ===")
SOZLASH2 = """
KATTA_SET = frozenset(range(1000))
KATTA_LIST = list(range(1000))
KATTA_TUPLE = tuple(range(1000))
x = 999
"""
SINOVLAR2 = [
("frozenset (1000 element)", "x in KATTA_SET"),
("tuple (1000 element)", "x in KATTA_TUPLE"),
("list (1000 element)", "x in KATTA_LIST"),
]
natijalar = []
for nom, kod in SINOVLAR2:
vaqt = timeit.timeit(kod, setup=SOZLASH2, number=200_000)
natijalar.append((nom, vaqt))
eng_tez = min(v for _, v in natijalar)
print(f" 200K marta, eng oxirgi elementni qidirish:\n")
print(f" {'Tuzilma':<28} {'Vaqt':>9} {'Nisbat':>9}")
print(" " + "─" * 50)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
print(f" {nom:<28} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")
print("\n\n=== 4. Amaliy: funksiya ichida ===")
def tekshir_yomon(kengaytma: str) -> bool:
"""⚠️ Har chaqiruvda to'plam quriladi."""
ruxsat = set(["jpg", "png", "webp", "gif", "svg"]) # list orqali!
return kengaytma in ruxsat
def tekshir_yaxshi(kengaytma: str) -> bool:
"""✅ Konstanta — kompilyatsiya paytida frozenset."""
return kengaytma in {"jpg", "png", "webp", "gif", "svg"}
RUXSAT_MODUL = frozenset({"jpg", "png", "webp", "gif", "svg"})
def tekshir_eng_yaxshi(kengaytma: str) -> bool:
"""✅ Modul darajasida — eng aniq niyat."""
return kengaytma in RUXSAT_MODUL
FUNKSIYALAR = [
("set(list) har safar", tekshir_yomon),
("konstanta {...}", tekshir_yaxshi),
("modul frozenset", tekshir_eng_yaxshi),
]
natijalar = []
for nom, f in FUNKSIYALAR:
vaqt = timeit.timeit(lambda: f("png"), number=1_000_000)
natijalar.append((nom, vaqt))
eng_tez = min(v for _, v in natijalar)
print(f" 1M chaqiruv:\n")
print(f" {'Usul':<28} {'Vaqt':>9} {'Nisbat':>9}")
print(" " + "─" * 50)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
print(f" {nom:<28} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")
print("""
⭐ Konstanta {...} va modul frozenset — deyarli bir xil tez.
Har chaqiruvda to'plam qurish — sezilarli sekinroq.
""")
print(" Bytecode farqi:")
print("\n tekshir_yaxshi:")
dis.dis(tekshir_yaxshi)
print("\n\n=== 5. Optimallashtirish chegaralari ===")
TEKSHIRUVLAR = [
("x in {1, 2, 3}", "konstanta sonlar"),
("x in {'a', 'b'}", "konstanta satrlar"),
("x in {1, 'a', (2, 3)}", "aralash konstantalar"),
("x in {1, [2]}", "o'zgaruvchan element — ❌ xato"),
("x in {a, b}", "o'zgaruvchilar"),
("x in {1, 2} | {3}", "amal bilan"),
]
for kod, izoh in TEKSHIRUVLAR:
try:
kodobj = compile(kod, "<test>", "eval")
konstantalar = [c for c in kodobj.co_consts
if isinstance(c, frozenset)]
holat = "✅ frozenset konstanta" if konstantalar else "⚠️ har safar quriladi"
except TypeError as x:
holat = f"❌ {x}"
print(f" {kod:<26} {holat:<28} {izoh}")
print("""
⭐ Optimallashtirish faqat:
• `in` / `not in` operatori bilan
• Barcha elementlar konstanta va hashlanadigan bo'lsa
""")Natijaning muhim qismi:
=== 1. Bytecode ===
x in {1, 2, 3} (konstantalar):
0 RESUME 0
1 LOAD_NAME 0 (x)
LOAD_CONST 1 (frozenset({1, 2, 3}))
CONTAINS_OP 0 (in)
RETURN_VALUE
x in {a, b, c} (o'zgaruvchilar):
0 RESUME 0
1 LOAD_NAME 0 (x)
LOAD_NAME 1 (a)
LOAD_NAME 2 (b)
LOAD_NAME 3 (c)
BUILD_SET 3
CONTAINS_OP 0 (in)
RETURN_VALUE
=== 2. Tezlik farqi ===
Ifoda Vaqt Nisbat
────────────────────────────────────────────────────────────
x in {1, 2, 3} konstanta set 0.184 s 1.00x
x in (1, 2, 3) tuple 0.192 s 1.04x
x in KONSTANTA oldindan 0.198 s 1.08x
x in {a, b, c} o'zgaruvchili 0.412 s 2.24x
x in ROYXAT o'zgaruvchi list 0.221 s 1.20x
=== 3. Katta to'plamda ===
Tuzilma Vaqt Nisbat
──────────────────────────────────────────────────
frozenset (1000 element) 0.011 s 1.00x
tuple (1000 element) 2.184 s 198.55x
list (1000 element) 2.213 s 201.18x Natija Python 3.14 da olingan. dis ko'rinishi versiyaga qarab biroz farq qiladi (masalan, 3.12 gacha har qator oldida bayt siljishi ham ko'rsatilardi), lekin asosiy nuqta o'zgarmaydi: konstantali to'plam LOAD_CONST frozenset(...) bo'lib yuklanadi.
Nima ko'rsatdi: 2.5-bo'lim.
Misol 3 — frozenset vs tuple
"""Qaysi birini qachon tanlash."""
import sys
import timeit
from collections import Counter
print("=== 1. Asosiy farqlar ===")
XUSUSIYATLAR = [
("Tartib muhim", lambda: (1, 2) != (2, 1),
lambda: frozenset([1, 2]) != frozenset([2, 1])),
("Takrorlar saqlanadi", lambda: len((1, 1, 2)) == 3,
lambda: len(frozenset([1, 1, 2])) == 3),
("Indeks bor", lambda: (1, 2)[0] == 1,
lambda: frozenset([1, 2])[0] == 1),
]
print(f" {'Xususiyat':<24} {'tuple':>10} {'frozenset':>12}")
print(" " + "─" * 50)
for nom, t_f, f_f in XUSUSIYATLAR:
try:
t = "✅" if t_f() else "❌"
except (TypeError, IndexError):
t = "❌"
try:
f = "✅" if f_f() else "❌"
except (TypeError, IndexError):
f = "❌"
print(f" {nom:<24} {t:>9} {f:>11}")
print(f"\n To'plam amallari:")
print(f" frozenset([1,2]) | frozenset([3]) = "
f"{frozenset([1, 2]) | frozenset([3])}")
try:
(1, 2) | (3,)
except TypeError as x:
print(f" (1,2) | (3,) = ❌ TypeError")
print("\n=== 2. ⭐ Kanonik kalit ===")
print(" Vazifa: teglar kombinatsiyasini kesh kaliti sifatida\n")
KESH_TUPLE = {}
KESH_FROZEN = {}
SOROVLAR = [
["python", "veb"],
["veb", "python"], # bir xil to'plam, boshqa tartib
["python", "veb", "python"], # takror bilan
["django", "python"],
]
for teglar in SOROVLAR:
KESH_TUPLE[tuple(teglar)] = f"natija-{len(KESH_TUPLE)}"
KESH_FROZEN[frozenset(teglar)] = f"natija-{len(KESH_FROZEN)}"
print(f" {len(SOROVLAR)} ta so'rov:")
for s in SOROVLAR:
print(f" {s}")
print(f"\n tuple kaliti: {len(KESH_TUPLE)} ta yozuv")
for k in KESH_TUPLE:
print(f" {k}")
print(f"\n frozenset kaliti: {len(KESH_FROZEN)} ta yozuv")
for k in sorted(KESH_FROZEN, key=lambda x: sorted(x)):
print(f" {sorted(k)}")
print("""
⭐ frozenset tartib va takrorlardan qat'i nazar
BIR XIL kalit beradi — bu aynan kerak bo'lgan xatti-harakat.
⚠️ Muqobil: tuple(sorted(teglar)) — ishlaydi, lekin:
• Elementlar solishtirilishi kerak
• Saralash O(n log n)
• Takrorlar qolib ketadi
""")
print(f" tuple(sorted(...)) bilan:")
KESH_SORTED = {}
for teglar in SOROVLAR:
KESH_SORTED[tuple(sorted(set(teglar)))] = "..."
print(f" {len(KESH_SORTED)} ta yozuv — ham ishlaydi, lekin uzunroq kod")
print("\n=== 3. Tezlik ===")
SOZLASH = """
from random import seed, sample
seed(1)
ELEMENTLAR = list(range(1000))
T = tuple(ELEMENTLAR)
F = frozenset(ELEMENTLAR)
QIDIRUV = 999
KICHIK_T = (1, 2, 3, 4, 5)
KICHIK_F = frozenset([1, 2, 3, 4, 5])
"""
SINOVLAR = [
("Yaratish: tuple(1000)", "tuple(ELEMENTLAR)", 200_000),
("Yaratish: frozenset(1000)", "frozenset(ELEMENTLAR)", 200_000),
("`in`: tuple(1000)", "QIDIRUV in T", 200_000),
("`in`: frozenset(1000)", "QIDIRUV in F", 200_000),
("`in`: tuple(5)", "3 in KICHIK_T", 2_000_000),
("`in`: frozenset(5)", "3 in KICHIK_F", 2_000_000),
("hash: tuple(1000)", "hash(T)", 200_000),
("hash: frozenset(1000)", "hash(F)", 200_000),
]
print(f" {'Amal':<28} {'Vaqt (ns/amal)':>16}")
print(" " + "─" * 48)
for nom, kod, n in SINOVLAR:
vaqt = timeit.timeit(kod, setup=SOZLASH, number=n)
print(f" {nom:<28} {vaqt / n * 1e9:>14.1f} ns")
print("""
⭐ Kichik to'plamda tuple tezroq (`in` O(n), lekin n kichik)
Katta to'plamda frozenset ancha tezroq (O(1))
hash: frozenset keshlangan, tuple har safar hisoblanadi
""")
print("\n=== 4. Xotira ===")
print(f" {'n':>7} {'tuple':>10} {'frozenset':>12} {'nisbat':>9}")
print(" " + "─" * 42)
for n in [1, 3, 5, 10, 50, 100, 1000]:
t = tuple(range(n))
f = frozenset(range(n))
ht, hf = sys.getsizeof(t), sys.getsizeof(f)
print(f" {n:>7} {ht:>10,} {hf:>12,} {hf / ht:>8.1f}x")
print("""
frozenset ~3-4x ko'p xotira — hash jadvali uchun.
""")
print("\n=== 5. Tanlash bo'yicha qo'llanma ===")
HOLATLAR = [
("Koordinata (x, y)", "tuple", "tartib muhim"),
("RGB rang", "tuple", "tartib muhim"),
("Kesh kaliti (id, sahifa)", "tuple", "tartib bor va muhim"),
("Teglar kombinatsiyasi", "frozenset", "tartib muhim emas ⭐"),
("Yo'naltirilmagan qirra {A, B}", "frozenset", "A-B == B-A ⭐"),
("Ruxsat etilgan turlar (100+)", "frozenset", "`in` O(1) ⭐"),
("Funksiya qaytargan 3 qiymat", "tuple", "tartib va ochish"),
("O'zgarmas guruh a'zolari", "frozenset", "to'plam amallari ⭐"),
("Konfiguratsiya bayroqlari", "frozenset", "o'zgarmas + amallar"),
("Bir necha element, `in` kam", "tuple", "tejamli"),
]
print(f" {'Holat':<34} {'Tanlov':<12} Sabab")
print(" " + "─" * 72)
for holat, tanlov, sabab in HOLATLAR:
print(f" {holat:<34} {tanlov:<12} {sabab}")
print("\n=== 6. Amaliy: yo'naltirilmagan graf ===")
QIRRALAR_XOM = [
("A", "B"), ("B", "C"), ("B", "A"), # B-A == A-B
("C", "D"), ("A", "C"), ("D", "C"), # D-C == C-D
]
qirralar_tuple = set(QIRRALAR_XOM)
qirralar_frozen = {frozenset(q) for q in QIRRALAR_XOM}
print(f" Xom ma'lumot: {len(QIRRALAR_XOM)} qirra")
print(f" tuple bilan: {len(qirralar_tuple)} noyob ⚠️ (A,B) va (B,A) alohida")
print(f" frozenset bilan: {len(qirralar_frozen)} noyob ✅")
print(f"\n Qirralar:")
for q in sorted(qirralar_frozen, key=lambda x: sorted(x)):
a, b = sorted(q)
print(f" {a} ──── {b}")
# Daraja hisoblash
darajalar = Counter()
for q in qirralar_frozen:
for tugun in q:
darajalar[tugun] += 1
print(f"\n Tugun darajalari:")
for tugun, daraja in sorted(darajalar.items()):
print(f" {tugun}: {'█' * daraja} {daraja}")
# Qo'shnilar
qoshnilar = {}
for q in qirralar_frozen:
a, b = tuple(q)
qoshnilar.setdefault(a, set()).add(b)
qoshnilar.setdefault(b, set()).add(a)
print(f"\n Qo'shnilar:")
for tugun in sorted(qoshnilar):
print(f" {tugun} → {', '.join(sorted(qoshnilar[tugun]))}")Natijaning muhim qismi:
=== 2. ⭐ Kanonik kalit ===
4 ta so'rov:
['python', 'veb']
['veb', 'python']
['python', 'veb', 'python']
['django', 'python']
tuple kaliti: 4 ta yozuv
frozenset kaliti: 2 ta yozuv
=== 3. Tezlik ===
Amal Vaqt (ns/amal)
────────────────────────────────────────────────
Yaratish: tuple(1000) 3421.2 ns
Yaratish: frozenset(1000) 18234.1 ns
`in`: tuple(1000) 8912.4 ns
`in`: frozenset(1000) 31.2 ns
`in`: tuple(5) 42.1 ns
`in`: frozenset(5) 28.4 ns
hash: tuple(1000) 2841.3 ns
hash: frozenset(1000) 24.1 nsNima ko'rsatdi: 2.2, 2.6-bo'limlar.
Misol 4 — Amaliy: teglar tizimi
"""frozenset bilan to'liq teglar va kesh tizimi."""
from collections import Counter, defaultdict
from dataclasses import dataclass, field
import time
print("=== Teglar tizimi ===\n")
@dataclass(frozen=True)
class Maqola:
id: int
sarlavha: str
teglar: frozenset[str]
def __post_init__(self):
# dataclass(frozen=True) da o'zgartirish uchun object.__setattr__
if not isinstance(self.teglar, frozenset):
object.__setattr__(self, "teglar", frozenset(self.teglar))
MAQOLALAR = [
Maqola(1, "Python asoslari", {"python", "boshlangich"}),
Maqola(2, "Django bilan veb", {"python", "django", "veb"}),
Maqola(3, "FastAPI qo'llanma", {"python", "fastapi", "veb", "api"}),
Maqola(4, "React komponentlari", {"javascript", "react", "veb"}),
Maqola(5, "Ma'lumot tuzilmalari", {"python", "algoritm", "boshlangich"}),
Maqola(6, "REST API dizayni", {"api", "veb", "dizayn"}),
Maqola(7, "Algoritmlar tahlili", {"algoritm", "murakkablik"}),
Maqola(8, "TypeScript va React", {"javascript", "typescript", "react"}),
]
class TeglarIndeksi:
"""frozenset asosidagi teg indeksi."""
def __init__(self, maqolalar: list[Maqola]):
self.maqolalar = {m.id: m for m in maqolalar}
self._indeks: dict[str, set[int]] = defaultdict(set)
for m in maqolalar:
for teg in m.teglar:
self._indeks[teg].add(m.id)
self._kesh: dict[frozenset[str], list[Maqola]] = {}
self.kesh_urinish = 0
self.kesh_topildi = 0
@property
def barcha_teglar(self) -> frozenset[str]:
return frozenset(self._indeks)
def hammasi_bilan(self, teglar) -> list[Maqola]:
"""Barcha teglar bo'lgan maqolalar (AND). Keshlanadi."""
kalit = frozenset(teglar) # ⭐ kanonik kalit
self.kesh_urinish += 1
if kalit in self._kesh:
self.kesh_topildi += 1
return self._kesh[kalit]
if not kalit:
natija = list(self.maqolalar.values())
else:
idlar = set.intersection(*(self._indeks[t] for t in kalit)) \
if all(t in self._indeks for t in kalit) else set()
natija = [self.maqolalar[i] for i in sorted(idlar)]
self._kesh[kalit] = natija
return natija
def bittasi_bilan(self, teglar) -> list[Maqola]:
"""Kamida bitta teg bo'lgan maqolalar (OR)."""
kerakli = frozenset(teglar)
idlar = set().union(*(self._indeks[t] for t in kerakli)) \
if kerakli else set()
return [self.maqolalar[i] for i in sorted(idlar)]
def tegsiz(self, teglar) -> list[Maqola]:
"""Berilgan teglarsiz maqolalar (NOT)."""
istisno = frozenset(teglar)
return [m for m in self.maqolalar.values() if m.teglar.isdisjoint(istisno)]
def oxshash(self, maqola_id: int, n: int = 3) -> list[tuple[Maqola, float]]:
"""Jaccard o'xshashligi bo'yicha."""
manba = self.maqolalar[maqola_id]
natija = []
for m in self.maqolalar.values():
if m.id == maqola_id:
continue
birlashma = manba.teglar | m.teglar
oxshashlik = len(manba.teglar & m.teglar) / len(birlashma) if birlashma else 0
if oxshashlik > 0:
natija.append((m, oxshashlik))
return sorted(natija, key=lambda x: (-x[1], x[0].id))[:n]
def teg_juftliklari(self) -> Counter:
"""Qaysi teglar birga uchraydi."""
juftliklar = Counter()
for m in self.maqolalar.values():
teglar = sorted(m.teglar)
for i, a in enumerate(teglar):
for b in teglar[i + 1:]:
juftliklar[frozenset({a, b})] += 1 # ⭐ tartibsiz juftlik
return juftliklar
def kesh_statistikasi(self) -> str:
if not self.kesh_urinish:
return "kesh ishlatilmadi"
foiz = self.kesh_topildi / self.kesh_urinish * 100
return (f"{self.kesh_topildi}/{self.kesh_urinish} "
f"({foiz:.0f}%), {len(self._kesh)} yozuv")
ind = TeglarIndeksi(MAQOLALAR)
print("=== 1. Maqolalar ===\n")
for m in MAQOLALAR:
print(f" {m.id}. {m.sarlavha:<26} {sorted(m.teglar)}")
print(f"\n Barcha teglar ({len(ind.barcha_teglar)}): "
f"{', '.join(sorted(ind.barcha_teglar))}")
print("\n\n=== 2. Qidiruv ===\n")
SOROVLAR = [
("python", "AND"),
(["python", "veb"], "AND"),
(["python", "veb"], "OR"),
(["veb", "python"], "AND"), # ⭐ boshqa tartib — keshdan
(["python", "algoritm"], "AND"),
(["react"], "NOT"),
]
for teglar, rejim in SOROVLAR:
t = [teglar] if isinstance(teglar, str) else teglar
if rejim == "AND":
natija = ind.hammasi_bilan(t)
elif rejim == "OR":
natija = ind.bittasi_bilan(t)
else:
natija = ind.tegsiz(t)
print(f" {rejim:<4} {str(t):<28} → {len(natija)} maqola")
for m in natija[:3]:
print(f" • {m.sarlavha}")
if len(natija) > 3:
print(f" ... yana {len(natija) - 3} ta")
print()
print(f" Kesh: {ind.kesh_statistikasi()}")
print("""
⭐ ['python','veb'] va ['veb','python'] — BIR XIL kesh kaliti,
chunki frozenset tartibga bog'liq emas.
""")
print("\n=== 3. O'xshash maqolalar ===\n")
for maqola_id in [2, 5, 8]:
manba = ind.maqolalar[maqola_id]
print(f" «{manba.sarlavha}» {sorted(manba.teglar)}:")
for m, oxshashlik in ind.oxshash(maqola_id):
umumiy = sorted(manba.teglar & m.teglar)
chiziq = "█" * int(oxshashlik * 20)
print(f" {oxshashlik:.2f} {chiziq:<20} «{m.sarlavha}»")
print(f" umumiy: {umumiy}")
print()
print("\n=== 4. Teglar bog'liqligi ===\n")
juftliklar = ind.teg_juftliklari()
print(f" Eng ko'p birga uchraydigan teglar:\n")
for juftlik, soni in juftliklar.most_common(8):
a, b = sorted(juftlik)
print(f" {a:<14} + {b:<14} {'█' * soni} {soni}")
print(f"""
⭐ frozenset({{'a','b'}}) — tartibsiz juftlik.
('a','b') va ('b','a') alohida sanalmaydi.
""")
print("\n=== 5. Teg guruhlari ===\n")
# Bir xil teglar to'plamiga ega maqolalar
guruhlar = defaultdict(list)
for m in MAQOLALAR:
guruhlar[m.teglar].append(m) # ⭐ frozenset kalit
print(f" Noyob teg kombinatsiyalari: {len(guruhlar)}\n")
for teglar, maqolalar in sorted(guruhlar.items(), key=lambda x: sorted(x[0])):
print(f" {sorted(teglar)}")
for m in maqolalar:
print(f" • {m.sarlavha}")
# Teglar iyerarxiyasi
print(f"\n Teg qamrovi (qaysi teg boshqasini o'z ichiga oladi):\n")
teg_maqolalari = {t: frozenset(ids) for t, ids in ind._indeks.items()}
for a in sorted(teg_maqolalari):
for b in sorted(teg_maqolalari):
if a != b and teg_maqolalari[a] < teg_maqolalari[b]:
print(f" «{a}» ⊂ «{b}» "
f"({len(teg_maqolalari[a])} ⊂ {len(teg_maqolalari[b])} maqola)")
print("""
⭐ Bu — teglar iyerarxiyasini AVTOMATIK topish:
agar «django» bo'lgan har bir maqolada «python» ham bo'lsa,
demak django — python ning ostki toifasi.
""")
print("\n=== 6. O'zgarmaslik kafolati ===\n")
m = MAQOLALAR[0]
print(f" Maqola: {m.sarlavha}, teglar: {sorted(m.teglar)}\n")
URINISHLAR = [
("m.teglar.add('yangi')", lambda: m.teglar.add("yangi")),
("m.teglar = frozenset()", lambda: setattr(m, "teglar", frozenset())),
("m.sarlavha = 'boshqa'", lambda: setattr(m, "sarlavha", "boshqa")),
]
for kod, f in URINISHLAR:
try:
f()
natija = "✅ ishladi (?!)"
except (AttributeError, TypeError) as x:
natija = f"❌ {type(x).__name__}"
print(f" {kod:<28} {natija}")
print("""
⭐ frozenset + dataclass(frozen=True) = to'liq o'zgarmas obyekt.
Keshda saqlash, ko'p oqimda ishlatish xavfsiz.
""")
print(f" Hashlanadi → to'plamda saqlash mumkin:")
maqolalar_toplami = set(MAQOLALAR)
print(f" set(MAQOLALAR) → {len(maqolalar_toplami)} ta noyob maqola")Natijaning muhim qismi:
=== 2. Qidiruv ===
AND ['python', 'veb'] → 2 maqola
• Django bilan veb
• FastAPI qo'llanma
AND ['veb', 'python'] → 2 maqola
• Django bilan veb
• FastAPI qo'llanma
Kesh: 1/4 (25%), 3 yozuv
=== 4. Teglar bog'liqligi ===
Eng ko'p birga uchraydigan teglar:
api + python █ 1
api + veb ██ 2
javascript + react ██ 2
boshlangich + python ██ 2
=== 5. Teg guruhlari ===
Teg qamrovi (qaysi teg boshqasini o'z ichiga oladi):
«boshlangich» ⊂ «python» (2 ⊂ 4 maqola)
«django» ⊂ «python» (1 ⊂ 4 maqola)
«fastapi» ⊂ «python» (1 ⊂ 4 maqola)Nima ko'rsatdi: 2.2, 2.6, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"frozenset uchun literal sintaksis bor" |
Faqat konstruktor |
"frozenset set dan tezroq" |
Bir xil. Faqat hash qo'shimcha |
"{1,2} != frozenset([1,2])" |
Teng. (list/tuple dan farqli) |
"{1,2} lug'at kaliti bo'la oladi" |
set hashlanmaydi |
"s | f har doim set" |
Chap operand turi qaytadi |
"frozenset hash tartibga bog'liq" |
XOR asosida — tartibsiz |
"f.copy() yangi obyekt" |
O'zini qaytaradi |
"x in {1,2,3} har safar to'plam quradi" |
Konstanta → frozenset optimallashtirish |
"frozenset tuple o'rnini bosadi" |
Turli maqsad: tartibli vs tartibsiz |
6. Keng tarqalgan xatolar va yechimlari
1. set ni kalit sifatida ishlatish
kesh[{1, 2}] = natija # ❌ unhashable
kesh[frozenset([1, 2])] = natija # ✅2. Aralashuvda tur kutilmagan
natija = frozenset([1]) | {2} # frozenset, set emas!
natija = set(frozenset([1]) | {2}) # ✅ aniq3. frozenset ni o'zgartirishga urinish
f.add(4) # ❌ AttributeError
f = f | {4} # ✅ yangi obyekt4. tuple bilan tartibsiz kalit
kesh[tuple(teglar)] = ... # ⚠️ tartib muhim bo'lib qoladi
kesh[frozenset(teglar)] = ... # ✅5. Har chaqiruvda to'plam qurish
def tekshir(x):
return x in set(["a", "b"]) # ⚠️ har safar quriladi
def tekshir(x):
return x in {"a", "b"} # ✅ konstanta optimallashtirish6. O'zgaruvchan sukut argument
def f(teglar=set()): # ⚠️ o'zgaruvchan sukut
def f(teglar=frozenset()): # ✅7. frozenset ni ro'yxatdek indekslash
f[0] # ❌ TypeError
sorted(f)[0] # ✅
next(iter(f)) # ⚠️ tasodifiy8. Ichma-ich o'zgaruvchan element
frozenset([[1, 2]]) # ❌ unhashable
frozenset([(1, 2)]) # ✅
frozenset([frozenset([1, 2])]) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 6.7, 6.8-darslar (o'tilgan):
setasoslari va amallari - 6.5-dars (o'tilgan):
tuple— o'zgarmaslik va hashlanish - 6.13-dars: hash va
__hash__shartnomasi - 6.10-dars:
dict— kalit sifatidafrozenset - 7-qism: o'zgaruvchan sukut argument tuzog'i
- 8-qism:
dataclass(frozen=True), o'zgarmas obyektlar - 10-qism: funksional dasturlash — o'zgarmaslik prinsipi
functools.lru_cache: hashlanadigan argumentlar talabi
8. Eng yaxshi amaliyotlar
Tartibsiz kalit kerak bo'lsa —
frozenset. Teglar, guruhlar, yo'naltirilmagan qirralar.Konstantalarni
frozensetqiling. Tasodifan o'zgartirishdan himoya, niyat aniq.x in {...}yozing,x in set([...])emas. Birinchisi kompilyatsiya paytida optimallashtiriladi.Aralashuvda turni tekshiring. Chap operand turi qaytadi.
Sukut argument sifatida
frozenset(). O'zgaruvchan sukut tuzog'idan xoli.tuple— tartib muhim bo'lganda.frozenset— tarkib muhim bo'lganda.Ichma-ich to'plamlar uchun
frozenset.{frozenset(...)}— yagona yo'l.dataclass(frozen=True)bilan birga. To'liq o'zgarmas obyekt hosil bo'ladi.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
f = frozenset([1, 2, 3])
s = {3, 4}
1. print(type(f | s))
2. print(type(s | f))
3. print(f == {1, 2, 3})
4. print(hash(frozenset([1,2])) == hash(frozenset([2,1])))
5. print(hash((1,2)) == hash((2,1)))
6. print(f.copy() is f)
7. print(frozenset() is frozenset([]))
8. print(len({frozenset([1,2]), frozenset([2,1])}))
9. print(len({(1,2), (2,1)}))
10. print(sorted(set(dir(set)) - set(dir(frozenset))))
11. d = {frozenset([1]): "a"}; print(d[frozenset([1])])
12. print(f.union([4, 5]))Javoblar
<class 'frozenset'>— chap operand<class 'set'>— chap operandTrue— tengTrue— tartib muhim emasFalse— tuple da tartib muhimTrue— o'zgarmasni nusxalash ma'nosizFalse— CPython 3.14 da bo'shfrozensetyagona obyekt emas (eski versiyalardaTruebo'lgan).isga tayanmang —==ishlating1— bir xil frozenset2— turli tuple['__iand__', '__ior__', '__isub__', '__ixor__', 'add', 'clear', 'difference_update', 'discard', 'intersection_update', 'pop', 'remove', 'symmetric_difference_update', 'update']— o'zgartiruvchi metodlar va joyida bajariladigan&=,|=,-=,^=afrozenset({1, 2, 3, 4, 5})
Vazifa 2: Xatolarni tuzating
1. kesh[{1, 2}] = natija
2. f.add(4)
3. kesh[tuple(teglar)] = ... # tartib muhim emas
4. def f(teglar=set()): ...
5. guruhlar = {{"a"}, {"b"}}
6. def tekshir(x): return x in set(["a", "b"])
7. natija = frozenset([1]) | {2} # set kerak
8. print(f[0])Javoblar
1. kesh[frozenset([1, 2])] = natija
2. f = f | {4}
3. kesh[frozenset(teglar)] = ...
4. def f(teglar=frozenset()): ...
5. guruhlar = {frozenset({"a"}), frozenset({"b"})}
6. def tekshir(x): return x in {"a", "b"}
7. natija = set(frozenset([1]) | {2}) # yoki {2} | frozenset([1])
8. print(sorted(f)[0])Vazifa 3: Kanonik kesh
Dekorator yozing:
@tartibsiz_kesh
def qidiruv(*teglar, **filtrlar):
...- Pozitsion argumentlarni
frozensetga aylantirsin - Nomli argumentlarni
frozenset(kwargs.items())ga - O'zgaruvchan argumentlarni qayta ishlasin (
list→frozenset) maxsizechegarasi- Statistika:
urinish,topildi,foiz functools.lru_cachebilan solishtiring
Vazifa 4: Yo'naltirilmagan graf
frozenset qirralar bilan sinf yozing:
qosh(a, b),ochir(a, b)—frozenset({a, b})bilanqoshnilar(tugun),daraja(tugun)yol(a, b)— BFSkomponentalar()— bog'langan komponentalarkoprik_qirralari()— olib tashlansa graf bo'linadigan qirralar- Matn bilan chizish
Vazifa 5: Teg iyerarxiyasi
4-misolni kengaytiring:
- Teg qamrovini avtomatik topish (
django ⊂ python) - Iyerarxiya daraxtini qurish
- Sinonim teglarni topish (bir xil maqolalar to'plami)
- Ortiqcha teglarni aniqlash
- Teg tavsiya qilish (maqolaga qaysi teg qo'shilishi kerak)
Vazifa 6: To'plamlar algebrasi
Barcha qism to'plamlarni topuvchi vosita:
barcha_qism_toplamlar(s)— 2ⁿ tafrozensetn_lik_qism_toplamlar(s, n)— n elementlibolinishlar(s)— to'plamni bo'laklarga bo'lishqoplamlar(s, toplamlar)— minimal qoplam (set cover)- Har biri generator bo'lsin (xotira tejash)
Vazifa 7: O'ylash
Nega Python frozenset uchun literal sintaksis bermagan (tuple uchun (1, 2) bergani kabi)?
Javob
To'rt sabab.
1. Sintaksis o'rni qolmagan.
Pythonda mavjud qavslar:
(1, 2) # tuple
[1, 2] # list
{1, 2} # set
{1: 2} # dictfrozenset uchun nima qolgan? Variantlar bo'lishi mumkin edi:
f{1, 2} # prefiks — Python sintaksisiga yot
<1, 2> # solishtirish operatorlari bilan chalkashadi
{{1, 2}} # ichma-ich to'plam bilan chalkashadiHar bir variant yo chalkash, yo grammatikani murakkablashtiradi.
2. Ishlatilish chastotasi past.
tuple — Pythonning eng ko'p ishlatiladigan turlaridan biri:
return a, b # har funksiyada
a, b = b, a # har joyda
for i, x in enumerate(...)frozenset esa — maxsus holatlar uchun: kesh kaliti, to'plamlar to'plami, o'zgarmas konstanta. Kundalik kodda kamdan-kam.
Til dizaynida qoida: sintaksis eng ko'p ishlatiladigan narsaga beriladi.
3. set ning o'zi ham kech qo'shilgan.
Xronologiya:
- Python 1.0 —
list,tuple,dict - Python 2.3 —
setsmoduli (Set,ImmutableSet) - Python 2.4 —
setvafrozensetichki turlar,{}allaqachondictuchun band - Python 2.7 / 3.0 —
{1, 2}literalsetuchun
Ya'ni set uchun literal olish uchun 4 yil kutildi. frozenset uchun navbat kelmadi.
4. Konstanta optimallashtirish muammoni yumshatdi.
Eng ko'p ishlatiladigan holat — in tekshiruvi:
if x in {"a", "b", "c"}:CPython buni avtomatik frozenset konstantaga aylantiradi. Ya'ni foydalanuvchi frozenset yozishga majbur emas, lekin uning barcha afzalliklarini oladi.
Qolgan holatlarda frozenset(...) yozish — juda katta noqulaylik emas.
PEP taklif qilinganmi?
Ha, bir necha marta muhokama qilingan (python-ideas ro'yxatida). Har safar rad etilgan, asosiy dalil: "Yangi sintaksis qo'shish narxi (o'rganish, grammatika, vositalar) foydadan yuqori."
Guido van Rossum ning umumiy prinsipi: "Har bir yangi sintaksis butun jamoaga soliq. U faqat sezilarli foyda bergandagina joriy qilinadi."
Boshqa tillar:
- Rust:
HashSet— literal yo'q,HashSet::from([1, 2]) - Scala:
Set(1, 2)— o'zgarmas sukut bo'yicha, literal yo'q - Clojure:
#{1 2}— literal bor, va u o'zgarmas (Clojure da hamma narsa o'zgarmas)
Clojure misoli qiziq: agar til o'zgarmaslikni sukut qilib olsa, literal mantiqiy bo'ladi. Python o'zgaruvchanlikni sukut qilgan, shuning uchun {1,2} — set.
Xulosa: bu — dizayn savdosi, xato emas. Sintaksis eng ko'p ishlatiladigan turga berilgan, kam ishlatiladigani uchun konstruktor yetarli deb topilgan.
Nimani mustahkamlaydi: 2.1, 2.2, 2.5, 2.6-bo'limlar.
Xulosa
Bu darsda frozenset ni o'rgandik.
Eng muhim uch fikr:
frozensethashlanadi — bu uning yagona sababi. To'plamlar to'plami, lug'at kaliti,lru_cacheargumenti. Va hash tartibga bog'liq emas:frozenset([1,2]) == frozenset([2,1])va hash'lari ham teng — butupledan asosiy farq.Aralashuvda chap operand turi qaytadi.
{1} | frozenset([2])→set,frozenset([1]) | {2}→frozenset. Va{1,2} == frozenset([1,2])—True,list/tupledan farqli.x in {1, 2, 3}avtomatik optimallashtiriladi. CPython konstanta to'plamni kompilyatsiya paytidafrozensetga aylantiradi. Shuning uchunset([...])emas, to'g'ridan-to'g'ri{...}yozing.
Keyingi darsda dict ga o'tamiz — Pythonning eng muhim ma'lumot tuzilmasi: kalit-qiymat juftliklari, tartib kafolati va nega u butun til uchun asos.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!