IlmHamroh
Python kursi/Malumot tuzilmalari18/18-dars37 daqiqa
Mundarija (22)

6.18-dars: Nusxa olish — copy va deepcopy

6-QISM — MA'LUMOT TUZILMALARI · 18-dars · 6-QISM YAKUNI


1. Kirish va motivatsiya

6-qismni boshlaganimizda ro'yxat "yorliq" ekanini ko'rdik (6.1-dars):

python
a = [1, 2, 3]
b = a                           # nusxa EMAS — bir obyektga ikki yorliq
b.append(4)
print(a)                        # [1, 2, 3, 4]

Yechim — a[:], a.copy(), list(a) edi. Lekin bu yetarli emas:

python
a = [[1, 2], [3, 4]]
b = a.copy()                    # "nusxa"
b[0].append(99)
print(a)                        # [[1, 2, 99], [3, 4]]  ⚠️ asl ham o'zgardi!

Va yanada nozik holatlar:

python
import copy

class Sozlamalar:
    def __init__(self):
        self.teglar = {"a", "b"}
        self.ichki = {"x": [1, 2]}

s1 = Sozlamalar()
s2 = copy.copy(s1)
s2.teglar.add("c")
print(s1.teglar)                # {'a', 'b', 'c'}  ⚠️

Va aylanma havolalar:

python
a = [1, 2]
a.append(a)                     # o'zini o'z ichiga oladi
copy.deepcopy(a)                # ✅ ishlaydi — nega cheksiz rekursiya yo'q?

Bu darsda:

  • Uch daraja: havola, sayoz nusxa, chuqur nusxa
  • copy.copy va copy.deepcopy — qanday ishlaydi
  • Aylanma havolalar va memo lug'ati
  • __copy__, __deepcopy__ — o'z nusxa mantiqingiz
  • Muqobil usullar va tezlik
  • Qachon nusxa kerak emas

2. Nazariya — chuqur tushuntirish

2.1. Uch daraja

python
a = [[1, 2], [3, 4]]

1. Havola (nusxa emas):

python
b = a
b is a                          # True
b[0] is a[0]                    # True

Bitta obyekt, ikki nom. Har qanday o'zgarish ikkalasida ko'rinadi.

2. Sayoz nusxa (shallow copy):

python
b = a.copy()                    # yoki a[:], list(a), copy.copy(a)
b is a                          # False    ← yangi ro'yxat
b[0] is a[0]                    # True     ⚠️ ichki obyektlar UMUMIY

Yangi konteyner, lekin ichidagi obyektlarga havolalar ko'chiriladi.

3. Chuqur nusxa (deep copy):

python
import copy
b = copy.deepcopy(a)
b is a                          # False
b[0] is a[0]                    # False    ✅ hammasi yangi

Vizual:

Havola:
  a ──┐
      ├──→ [ • , • ]
  b ──┘      ↓   ↓
           [1,2] [3,4]

Sayoz nusxa:
  a ──→ [ • , • ]
          ↓   ↓
        [1,2] [3,4]
          ↑   ↑
  b ──→ [ • , • ]        ← yangi konteyner, ESKI ichki obyektlar

Chuqur nusxa:
  a ──→ [ • , • ] → [1,2] [3,4]
  b ──→ [ • , • ] → [1,2] [3,4]    ← hammasi yangi

Sayoz nusxa qachon yetarli:

Ichki obyektlar o'zgarmas bo'lsa:

python
a = [1, 2, 3]                   # int — o'zgarmas
b = a.copy()
b[0] = 99
print(a)                        # [1, 2, 3]  ✅ o'zgarmadi

a = ["x", (1, 2), 3.5]          # hammasi o'zgarmas
b = a.copy()                    # ✅ deepcopy kerak emas

Faqat bitta o'zgaruvchan element bo'lsa ham — muammo:

python
a = [1, "x", [2, 3]]
b = a.copy()
b[2].append(4)
print(a)                        # [1, 'x', [2, 3, 4]]  ⚠️

2.2. copy moduli

python
import copy

copy.copy(x)                    # sayoz
copy.deepcopy(x)                # chuqur

Sayoz nusxa usullari (barchasi teng):

Tur Usullar
list a[:], a.copy(), list(a), copy.copy(a)
dict d.copy(), dict(d), {**d}, copy.copy(d)
set s.copy(), set(s), copy.copy(s)
bytearray b[:], bytearray(b), copy.copy(b)

O'zgarmas turlar uchun nusxa — o'zi:

python
t = (1, 2)
copy.copy(t) is t               # True
copy.deepcopy(t) is t           # True  ⚠️ (agar ichida o'zgaruvchan yo'q bo'lsa)

s = "abc"
copy.copy(s) is s               # True

f = frozenset([1, 2])
f.copy() is f                   # True

Sabab: o'zgarmas obyektni nusxalash ma'nosiz — hech kim uni o'zgartira olmaydi.

Lekin ichida o'zgaruvchan bo'lsa:

python
t = (1, [2, 3])
copy.copy(t) is t               # True   ← sayoz: o'zi qaytadi
copy.deepcopy(t) is t           # False  ← chuqur: yangi tuple

copy.copy obyektlar uchun:

python
class A:
    def __init__(self):
        self.x = 1
        self.royxat = [1, 2]

a = A()
b = copy.copy(a)
b is a                          # False
b.royxat is a.royxat            # True  ⚠️
b.__dict__ is a.__dict__        # False — yangi lug'at

copy.copy obyekt uchun __dict__ ni sayoz nusxalaydi.

2.3. deepcopy va memo

deepcopy rekursiv ishlaydi va aylanma havolalarni hal qiladi.

python
a = [1, 2]
a.append(a)                     # o'zini o'z ichiga oladi
print(a)                        # [1, 2, [...]]

b = copy.deepcopy(a)            # ✅ cheksiz rekursiya YO'Q
b[2] is b                       # True   ← aylanma tuzilma saqlandi
b[2] is a                       # False  ← lekin yangi obyekt

Qanday ishlaydi — memo lug'ati:

python
def deepcopy(x, memo=None):
    if memo is None:
        memo = {}

    if id(x) in memo:
        return memo[id(x)]      # ⭐ allaqachon nusxalangan

    nusxa = yangi_bosh_konteyner(x)
    memo[id(x)] = nusxa         # ⭐ REKURSIYADAN OLDIN yozish

    for element in x:
        nusxa.append(deepcopy(element, memo))

    return nusxa

Ikki muhim jihat:

1. Aylanma havolalar hal qilinadi — memo da allaqachon bo'lsa qaytariladi.

2. Umumiy obyektlar umumiy qoladi:

python
umumiy = [1, 2]
a = [umumiy, umumiy]
a[0] is a[1]                    # True

b = copy.deepcopy(a)
b[0] is b[1]                    # True   ⭐ munosabat SAQLANDI
b[0] is a[0]                    # False  ← lekin yangi obyekt

Bu — juda muhim: deepcopy tuzilmaning shaklini saqlaydi.

memo ni qo'lda berish:

python
memo = {}
b1 = copy.deepcopy(a, memo)
b2 = copy.deepcopy(a, memo)
b1 is b2                        # True — memo dan qaytdi

Nusxalanmaydigan obyektlar:

python
copy.deepcopy(open("fayl.txt"))         # ❌ TypeError
copy.deepcopy(threading.Lock())         # ❌ TypeError
copy.deepcopy(socket.socket())          # ❌ TypeError

Sabab: bu obyektlar OS resurslariga bog'langan — ularni "nusxalash" ma'nosiz.

Atomik turlar nusxalanmaydi (o'zi qaytadi):

python
copy.deepcopy(42) is 42                 # True
copy.deepcopy("abc") is "abc"           # True
copy.deepcopy(None) is None             # True
copy.deepcopy(int) is int               # True  ← sinflar ham
copy.deepcopy(print) is print           # True  ← funksiyalar ham

copy._deepcopy_atomic ro'yxati: type(None), int, float, bool, complex, bytes, str, type, range, types.BuiltinFunctionType, types.FunctionType, weakref.ref, property.

2.4. __copy__ va __deepcopy__

O'z sinfingiz uchun nusxa mantiqini boshqarish:

python
class Ulanish:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.soket = self._ulan()       # nusxalanmaydigan resurs
        self.kesh = {}

    def _ulan(self):
        return f"<soket {self.host}:{self.port}>"

    def __copy__(self):
        """Sayoz nusxa — yangi ulanish, kesh umumiy."""
        yangi = Ulanish.__new__(Ulanish)
        yangi.__dict__.update(self.__dict__)
        yangi.soket = yangi._ulan()     # ⭐ yangi resurs
        return yangi

    def __deepcopy__(self, memo):
        """Chuqur nusxa — hamma narsa yangi."""
        yangi = Ulanish.__new__(Ulanish)
        memo[id(self)] = yangi          # ⭐ REKURSIYADAN OLDIN
        yangi.host = self.host
        yangi.port = self.port
        yangi.soket = yangi._ulan()
        yangi.kesh = copy.deepcopy(self.kesh, memo)
        return yangi

__deepcopy__ da memo[id(self)] = yangi — MAJBURIY va rekursiv chaqiruvlardan oldin bo'lishi kerak. Aks holda aylanma havolada cheksiz rekursiya.

__reduce__ bilan (pickle mexanizmi):

Agar __copy__/__deepcopy__ yo'q bo'lsa, copy moduli __reduce_ex__ ni ishlatadi — bu pickle bilan bir xil mexanizm:

python
class A:
    def __reduce__(self):
        return (A, (self.x, self.y))    # (yaratuvchi, argumentlar)

Shuning uchun pickle qila oladigan obyekt odatda deepcopy ham qilinadi.

__slots__ bilan:

python
class B:
    __slots__ = ("x", "y")

    def __init__(self, x, y):
        self.x, self.y = x, y

copy moduli __slots__ ni avtomatik qo'llab-quvvatlaydi (__getstate__/__setstate__ orqali).

2.5. Muqobil usullar

1. JSON roundtrip:

python
import json
nusxa = json.loads(json.dumps(d))

Afzalligi: deepcopy dan ~5-10x tezroq.

Kamchiliklari:

  • Faqat JSON turlari: dict, list, str, int, float, bool, None
  • tuple → list
  • set → xato
  • datetime, Decimal → xato
  • Lug'at kalitlari satrga aylanadi
  • Aylanma havolalar → xato
  • Umumiy obyektlar ajraladi (shakl yo'qoladi)

2. pickle roundtrip:

python
import pickle
nusxa = pickle.loads(pickle.dumps(d))

Afzalligi: ko'proq tur, aylanma havolalar ishlaydi, ba'zan deepcopy dan tezroq.

Kamchiliklari: pickle qilinmaydigan obyektlar (lambda, ochiq fayl), xavfsizlik (ishonchsiz ma'lumotni loads qilmang).

3. Qo'lda:

python
# Ma'lum tuzilma uchun eng tez
nusxa = {k: list(v) for k, v in d.items()}
nusxa = [qator[:] for qator in matritsa]

4. O'zgarmas tuzilmalar:

python
from dataclasses import replace

@dataclass(frozen=True)
class Nuqta:
    x: int
    y: int

n2 = replace(n1, x=5)           # ⭐ nusxa kerak emas — yangi obyekt

Tanlash jadvali:

Usul Tezlik Turlar Aylanma Shakl
copy.copy Hammasi — —
copy.deepcopy Hammasi
json Cheklangan
pickle Ko'p
Qo'lda Ma'lum

2.6. Tezlik va optimallashtirish

deepcopy sekin, chunki:

  • Har obyekt uchun tur tekshiruvi
  • memo lug'atiga yozish va o'qish
  • Rekursiv chaqiruvlar
  • __reduce_ex__ mexanizmi (maxsus turlar uchun)

Taxminiy raqamlar (1000 elementli ichma-ich tuzilma):

copy.copy:          ~2 µs
qo'lda nusxa:       ~50 µs
json roundtrip:     ~400 µs
pickle roundtrip:   ~300 µs
copy.deepcopy:      ~2000 µs

Optimallashtirish:

1. Nusxa kerakmi?

python
# ❌ Har chaqiruvda nusxa
def qayta_ishla(malumot):
    nusxa = copy.deepcopy(malumot)
    ...

# ✅ O'zgartirmasangiz nusxa kerak emas
def qayta_ishla(malumot):
    return [f(x) for x in malumot]       # yangi ro'yxat

2. Kerakli qismini nusxalang:

python
copy.deepcopy(katta_obyekt)                     # ❌
nusxa = {**katta_obyekt, "ozgaradigan": copy.deepcopy(...)}   # ✅

3. O'zgarmas tuzilmalarga o'ting:

python
@dataclass(frozen=True)         # nusxa umuman kerak emas
class Holat: ...

4. __deepcopy__ yozing:

python
def __deepcopy__(self, memo):
    yangi = MeningSinf.__new__(MeningSinf)
    memo[id(self)] = yangi
    yangi.katta_kesh = self.katta_kesh          # ⭐ nusxalamaymiz
    yangi.holat = copy.deepcopy(self.holat, memo)
    return yangi

2.7. Qachon nusxa KERAK EMAS

1. O'zgarmas turlar:

python
t = (1, 2, 3)
nusxa = t                       # ✅ nusxa kerak emas

2. Yangi obyekt yaratadigan amallar:

python
yangi = [x * 2 for x in eski]           # ✅ eski o'zgarmaydi
yangi = eski + [1]                      # ✅
yangi = {**d1, **d2}                    # ✅ (sayoz)
yangi = sorted(eski)                    # ✅

3. Faqat o'qiydigan funksiya:

python
def yigindi(r):
    return sum(r)                       # ✅ nusxa kerak emas

4. Sukut argument (o'zgarmas ishlating):

python
def f(teglar=()):                       # ✅ tuple
def f(teglar=frozenset()):              # ✅
def f(teglar=None):                     # ✅
    teglar = teglar or []

def f(teglar=[]):                       # ❌ o'zgaruvchan sukut

Klassik xato — funksiya argumentini o'zgartirish:

python
def qosh_element(r, x):
    r.append(x)                         # ⚠️ CHAQIRUVCHINING ro'yxati o'zgardi
    return r

def qosh_element(r, x):
    return [*r, x]                      # ✅ yangi ro'yxat

Agar o'zgartirish ataylab bo'lsa, hujjatda yozing va None qaytaring (6.2-dars kelishuvi).


3. Tez ma'lumotnoma

Uch daraja

python
b = a                   HAVOLA — bitta obyekt
b = a.copy()            SAYOZ  — yangi konteyner, ESKI ichki obyektlar
b = copy.deepcopy(a)    CHUQUR — hammasi yangi

Sayoz nusxa usullari

python
list:       a[:], a.copy(), list(a), copy.copy(a)
dict:       d.copy(), dict(d), {**d}
set:        s.copy(), set(s)
o'zgarmas:  copy.copy(t) is t    ⚠️ o'zi qaytadi

deepcopy va memo

python
memo = {id(obyekt): nusxa}

Aylanma havola:     ✅ hal qilinadi
Umumiy obyektlar:   ✅ umumiy qoladi (shakl saqlanadi)
Atomik turlar:      o'zi qaytadi (int, str, None, funksiya, sinf)
Resurslar:          ❌ TypeError (fayl, soket, Lock)

Maxsus metodlar

python
def __copy__(self): ...
def __deepcopy__(self, memo):
    yangi = Sinf.__new__(Sinf)
    memo[id(self)] = yangi          ⭐ REKURSIYADAN OLDIN
    ...
    return yangi

Muqobillar

copy.copy         ⭐⭐⭐  sayoz
copy.deepcopy     ⭐      hamma tur, aylanma, shakl
json roundtrip    ⭐⭐    faqat JSON turlari, aylanma ❌
pickle roundtrip  ⭐⭐    ko'p tur, aylanma ✅
qo'lda            ⭐⭐⭐  ma'lum tuzilma uchun

Nusxa KERAK EMAS

python
O'zgarmas turlar                 t = (1,2)
Yangi obyekt yaratuvchi amallar  [x*2 for x in r], {**d1, **d2}
Faqat o'qiydigan funksiya        sum(r)
frozen dataclass                 replace(obj, x=1)

4. Batafsil misollar

Misol 1 — Uch daraja

python
"""Havola, sayoz nusxa, chuqur nusxa — farqlar."""

import copy

print("=== 1. Uch daraja ===")

ASL = [[1, 2], [3, 4], [5, 6]]

havola = ASL
sayoz = ASL.copy()
chuqur = copy.deepcopy(ASL)

print(f"  ASL = {ASL}\n")
print(f"  {'Usul':<20} {'obyekt is':>11} {'ichki[0] is':>13}")
print("  " + "─" * 48)
print(f"  {'b = a':<20} {str(havola is ASL):>11} {str(havola[0] is ASL[0]):>13}")
print(f"  {'b = a.copy()':<20} {str(sayoz is ASL):>11} {str(sayoz[0] is ASL[0]):>13}")
print(f"  {'b = deepcopy(a)':<20} {str(chuqur is ASL):>11} {str(chuqur[0] is ASL[0]):>13}")

print(f"\n  Sinov — b[0].append(99):\n")

for nom, b in [("havola", ASL.copy()), ("sayoz", None), ("chuqur", None)]:
    pass

a1 = [[1, 2], [3, 4]]
b1 = a1
b1[0].append(99)
print(f"    havola:  ASL = {a1}   ⚠️")

a2 = [[1, 2], [3, 4]]
b2 = a2.copy()
b2[0].append(99)
print(f"    sayoz:   ASL = {a2}   ⚠️")

a3 = [[1, 2], [3, 4]]
b3 = copy.deepcopy(a3)
b3[0].append(99)
print(f"    chuqur:  ASL = {a3}   ✅")

print(f"\n  Sinov — b[0] = 'YANGI' (element ALMASHTIRISH):\n")

a1 = [[1, 2], [3, 4]]
b1 = a1
b1[0] = "YANGI"
print(f"    havola:  ASL = {a1}   ⚠️")

a2 = [[1, 2], [3, 4]]
b2 = a2.copy()
b2[0] = "YANGI"
print(f"    sayoz:   ASL = {a2}   ✅ (konteyner alohida)")

print("""
  ⭐ Sayoz nusxa KONTEYNERNI ajratadi, ICHKI obyektlarni emas.
     • b[0] = x       → asl o'zgarmaydi ✅
     • b[0].append(x) → asl o'zgaradi  ⚠️
""")


print("\n=== 2. Sayoz nusxa qachon yetarli ===")

SINOVLAR = [
    ("[1, 2, 3]",               [1, 2, 3],                  "int — o'zgarmas"),
    ("['a', 'b']",              ["a", "b"],                 "str — o'zgarmas"),
    ("[(1,2), (3,4)]",          [(1, 2), (3, 4)],           "tuple — o'zgarmas"),
    ("[1, 'x', 3.5, None]",     [1, "x", 3.5, None],        "hammasi o'zgarmas"),
    ("[[1], [2]]",              [[1], [2]],                 "⚠️ list — o'zgaruvchan"),
    ("[{1}, {2}]",              [{1}, {2}],                 "⚠️ set"),
    ("[{'a':1}]",               [{"a": 1}],                 "⚠️ dict"),
    ("[1, [2]]",                [1, [2]],                   "⚠️ bittasi yetarli"),
]

print(f"  {'Tuzilma':<24} {'Sayoz yetarlimi':<18} Izoh")
print("  " + "─" * 62)
for nom, asl, izoh in SINOVLAR:
    nusxa = copy.copy(asl)
    # Ichki obyektlardan biri o'zgaruvchanmi
    ozgaruvchan = any(isinstance(x, (list, dict, set, bytearray)) for x in asl)
    belgi = "❌ deepcopy kerak" if ozgaruvchan else "✅ ha"
    print(f"  {nom:<24} {belgi:<18} {izoh}")


print("\n=== 3. Barcha sayoz nusxa usullari ===")

R = [[1, 2], [3, 4]]
D = {"a": [1], "b": [2]}
S = {1, 2, 3}

print(f"  Ro'yxat:")
for kod, nusxa in [
    ("a[:]",            R[:]),
    ("a.copy()",        R.copy()),
    ("list(a)",         list(R)),
    ("copy.copy(a)",    copy.copy(R)),
    ("[*a]",            [*R]),
    ("a + []",          R + []),
]:
    print(f"    {kod:<18} yangi: {nusxa is not R}, "
          f"ichki umumiy: {nusxa[0] is R[0]}")

print(f"\n  Lug'at:")
for kod, nusxa in [
    ("d.copy()",        D.copy()),
    ("dict(d)",         dict(D)),
    ("{**d}",           {**D}),
    ("copy.copy(d)",    copy.copy(D)),
]:
    print(f"    {kod:<18} yangi: {nusxa is not D}, "
          f"ichki umumiy: {nusxa['a'] is D['a']}")

print(f"\n  To'plam:")
for kod, nusxa in [
    ("s.copy()",        S.copy()),
    ("set(s)",          set(S)),
    ("copy.copy(s)",    copy.copy(S)),
    ("{*s}",            {*S}),
]:
    print(f"    {kod:<18} yangi: {nusxa is not S}")


print("\n=== 4. O'zgarmas turlar ===")

OZGARMASLAR = [
    ("42",                  42),
    ("'abc'",               "abc"),
    ("(1, 2)",              (1, 2)),
    ("frozenset([1])",      frozenset([1])),
    ("None",                None),
    ("b'bytes'",            b"bytes"),
    ("range(3)",            range(3)),
    ("int",                 int),
    ("print",               print),
]

print(f"  {'Obyekt':<20} {'copy is':>10} {'deepcopy is':>14}")
print("  " + "─" * 48)
for nom, o in OZGARMASLAR:
    print(f"  {nom:<20} {str(copy.copy(o) is o):>10} "
          f"{str(copy.deepcopy(o) is o):>14}")

print(f"\n  ⚠️ Ichida o'zgaruvchan bo'lsa:")
t = (1, [2, 3])
print(f"    t = (1, [2, 3])")
print(f"    copy.copy(t) is t:      {copy.copy(t) is t}   ← sayoz: o'zi")
print(f"    copy.deepcopy(t) is t:  {copy.deepcopy(t) is t}   ← chuqur: yangi")

d = copy.deepcopy(t)
d[1].append(4)
print(f"\n    deepcopy nusxada [1].append(4):")
print(f"      t = {t}   ✅ o'zgarmadi")
print(f"      d = {d}")


print("\n=== 5. Obyektlar ===")


class Sozlamalar:
    def __init__(self):
        self.nom = "asl"
        self.port = 5432
        self.teglar = {"a", "b"}
        self.ichki = {"x": [1, 2]}

    def __repr__(self):
        return (f"Sozlamalar(nom={self.nom!r}, port={self.port}, "
                f"teglar={sorted(self.teglar)}, ichki={self.ichki})")


s1 = Sozlamalar()
s_sayoz = copy.copy(s1)
s_chuqur = copy.deepcopy(s1)

print(f"  s1 = {s1}\n")
print(f"  {'':<14} {'obyekt is':>11} {'__dict__ is':>13} {'teglar is':>11}")
print("  " + "─" * 54)
print(f"  {'copy.copy':<14} {str(s_sayoz is s1):>11} "
      f"{str(s_sayoz.__dict__ is s1.__dict__):>13} "
      f"{str(s_sayoz.teglar is s1.teglar):>11}")
print(f"  {'copy.deepcopy':<14} {str(s_chuqur is s1):>11} "
      f"{str(s_chuqur.__dict__ is s1.__dict__):>13} "
      f"{str(s_chuqur.teglar is s1.teglar):>11}")

print(f"\n  Sinov:")
s_sayoz.nom = "sayoz"
s_sayoz.teglar.add("c")
s_sayoz.ichki["x"].append(3)

print(f"    s_sayoz.nom = 'sayoz'          → s1.nom = {s1.nom!r}   ✅")
print(f"    s_sayoz.teglar.add('c')        → s1.teglar = {sorted(s1.teglar)}   ⚠️")
print(f"    s_sayoz.ichki['x'].append(3)   → s1.ichki = {s1.ichki}   ⚠️")

s1.teglar.discard("c")
s1.ichki["x"] = [1, 2]

s_chuqur.teglar.add("z")
s_chuqur.ichki["x"].append(9)
print(f"\n    s_chuqur.teglar.add('z')       → s1.teglar = {sorted(s1.teglar)}   ✅")
print(f"    s_chuqur.ichki['x'].append(9)  → s1.ichki = {s1.ichki}   ✅")

Natijaning muhim qismi:

text
=== 1. Uch daraja ===
  Usul                   obyekt is   ichki[0] is
  ────────────────────────────────────────────────
  b = a                       True          True
  b = a.copy()               False          True
  b = deepcopy(a)            False         False

  Sinov — b[0].append(99):

    havola:  ASL = [[1, 2, 99], [3, 4]]   ⚠️
    sayoz:   ASL = [[1, 2, 99], [3, 4]]   ⚠️
    chuqur:  ASL = [[1, 2], [3, 4]]   ✅

=== 5. Obyektlar ===
                   obyekt is   __dict__ is   teglar is
  ──────────────────────────────────────────────────────
  copy.copy            False         False        True
  copy.deepcopy        False         False       False

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — memo va aylanma havolalar

python
"""deepcopy qanday qilib aylanma havolalarni hal qiladi."""

import copy

print("=== 1. Aylanma havola ===")

a = [1, 2]
a.append(a)

print(f"  a = [1, 2]; a.append(a)")
print(f"    a = {a}")
print(f"    a[2] is a: {a[2] is a}   ← o'zini o'z ichiga oladi\n")

b = copy.deepcopy(a)
print(f"  b = copy.deepcopy(a)")
print(f"    b = {b}")
print(f"    b[2] is b: {b[2] is b}   ✅ aylanma tuzilma SAQLANDI")
print(f"    b[2] is a: {b[2] is a}   ✅ lekin yangi obyekt")
print(f"    b is a:    {b is a}")

print(f"\n  ⭐ Cheksiz rekursiya YO'Q — memo lug'ati tufayli")


print("\n=== 2. Ikki tomonlama havola ===")


class Tugun:
    def __init__(self, nom):
        self.nom = nom
        self.ota = None
        self.bolalar = []

    def qosh(self, bola):
        bola.ota = self
        self.bolalar.append(bola)
        return self

    def __repr__(self):
        return f"Tugun({self.nom!r})"


ildiz = Tugun("ildiz")
a1 = Tugun("a")
b1 = Tugun("b")
ildiz.qosh(a1).qosh(b1)
a1.qosh(Tugun("a1"))

print(f"  Daraxt:")
print(f"    {ildiz} → {ildiz.bolalar}")
print(f"    {a1} → {a1.bolalar},  ota: {a1.ota}")
print(f"    ⚠️ Aylanma: ildiz → a → ildiz\n")

nusxa = copy.deepcopy(ildiz)

print(f"  Nusxa:")
print(f"    nusxa is ildiz:                    {nusxa is ildiz}")
print(f"    nusxa.bolalar[0] is a:             {nusxa.bolalar[0] is a1}")
print(f"    nusxa.bolalar[0].ota is nusxa:     {nusxa.bolalar[0].ota is nusxa}   ⭐")
print(f"    nusxa.bolalar[0].ota is ildiz:     {nusxa.bolalar[0].ota is ildiz}")

print(f"\n  ⭐ Ota-bola munosabati TO'G'RI ko'chirildi")


print("\n=== 3. Umumiy obyektlar ===")

UMUMIY = [1, 2, 3]
a = {"birinchi": UMUMIY, "ikkinchi": UMUMIY, "uchinchi": [1, 2, 3]}

print(f"  UMUMIY = [1, 2, 3]")
print(f"  a = {{'birinchi': UMUMIY, 'ikkinchi': UMUMIY, 'uchinchi': [1,2,3]}}\n")
print(f"    a['birinchi'] is a['ikkinchi']:  {a['birinchi'] is a['ikkinchi']}   ← umumiy")
print(f"    a['birinchi'] is a['uchinchi']:  {a['birinchi'] is a['uchinchi']}   ← alohida")

b = copy.deepcopy(a)
print(f"\n  b = copy.deepcopy(a):")
print(f"    b['birinchi'] is b['ikkinchi']:  {b['birinchi'] is b['ikkinchi']}   ⭐ SAQLANDI")
print(f"    b['birinchi'] is b['uchinchi']:  {b['birinchi'] is b['uchinchi']}   ⭐ SAQLANDI")
print(f"    b['birinchi'] is a['birinchi']:  {b['birinchi'] is a['birinchi']}   ← yangi")

b["birinchi"].append(99)
print(f"\n  b['birinchi'].append(99):")
print(f"    b['birinchi']  = {b['birinchi']}")
print(f"    b['ikkinchi']  = {b['ikkinchi']}   ⭐ ham o'zgardi (umumiy)")
print(f"    b['uchinchi']  = {b['uchinchi']}   ← o'zgarmadi")
print(f"    a['birinchi']  = {a['birinchi']}   ✅ asl butun")

print(f"\n  ⚠️ JSON bilan solishtiring:")
import json
c = json.loads(json.dumps(a))
print(f"    c = json.loads(json.dumps(a))")
print(f"    c['birinchi'] is c['ikkinchi']:  {c['birinchi'] is c['ikkinchi']}   "
      f"⚠️ SHAKL YO'QOLDI")


print("\n=== 4. memo lug'atini kuzatish ===")


class Kuzatuvchi:
    """deepcopy qanday chaqirilishini ko'rsatadi."""
    chaqiruvlar = []

    def __init__(self, nom):
        self.nom = nom
        self.havolalar = []

    def __deepcopy__(self, memo):
        Kuzatuvchi.chaqiruvlar.append(
            f"__deepcopy__({self.nom}), memo hajmi: {len(memo)}"
        )
        yangi = Kuzatuvchi.__new__(Kuzatuvchi)
        memo[id(self)] = yangi              # ⭐ REKURSIYADAN OLDIN
        yangi.nom = self.nom
        yangi.havolalar = copy.deepcopy(self.havolalar, memo)
        return yangi

    def __repr__(self):
        return f"K({self.nom})"


a = Kuzatuvchi("a")
b = Kuzatuvchi("b")
c = Kuzatuvchi("c")
a.havolalar = [b, c]
b.havolalar = [a]                          # aylanma!
c.havolalar = [a, b]

Kuzatuvchi.chaqiruvlar.clear()
nusxa = copy.deepcopy(a)

print(f"  Tuzilma: a → [b, c], b → [a], c → [a, b]\n")
print(f"  __deepcopy__ chaqiruvlari:")
for i, ch in enumerate(Kuzatuvchi.chaqiruvlar, 1):
    print(f"    {i}. {ch}")

print(f"\n  ⭐ Har obyekt FAQAT BIR MARTA nusxalandi")
print(f"     (a, b, c — uchta chaqiruv, aylanma bo'lsa ham)")

print(f"\n  Natija tuzilmasi:")
print(f"    nusxa.havolalar[0].havolalar[0] is nusxa:  "
      f"{nusxa.havolalar[0].havolalar[0] is nusxa}   ⭐")


print("\n=== 5. memo ni qo'lda berish ===")

ASL = [[1, 2], [3, 4]]

memo = {}
n1 = copy.deepcopy(ASL, memo)
n2 = copy.deepcopy(ASL, memo)

print(f"  memo = {{}}")
print(f"  n1 = copy.deepcopy(ASL, memo)")
print(f"  n2 = copy.deepcopy(ASL, memo)\n")
print(f"    n1 is n2:  {n1 is n2}   ⭐ memo dan qaytdi")
print(f"    n1 is ASL: {n1 is ASL}")
print(f"    memo hajmi: {len(memo)}")

print(f"\n  memo siz:")
n3 = copy.deepcopy(ASL)
n4 = copy.deepcopy(ASL)
print(f"    n3 is n4:  {n3 is n4}   ← alohida nusxalar")

print("""
  ⭐ memo — bir necha bog'liq obyektni nusxalashda foydali:
     bir tuzilmaga havolalar saqlanadi.
""")


print("\n=== 6. ❌ Nusxalanmaydigan obyektlar ===")

import io
import threading

SINOVLAR = [
    ("io.StringIO()",           io.StringIO()),
    ("threading.Lock()",        threading.Lock()),
    ("(x for x in range(3))",   (x for x in range(3))),
    ("iter([1,2])",             iter([1, 2])),
    ("lambda: 1",               lambda: 1),
    ("print",                   print),
    ("int",                     int),
]

print(f"  {'Obyekt':<26} {'copy':<20} {'deepcopy'}")
print("  " + "─" * 62)
for nom, o in SINOVLAR:
    try:
        copy.copy(o)
        c = "✅"
    except (TypeError, ValueError) as x:
        c = f"❌ {type(x).__name__}"
    try:
        copy.deepcopy(o)
        d = "✅"
    except (TypeError, ValueError) as x:
        d = f"❌ {type(x).__name__}"
    print(f"  {nom:<26} {c:<20} {d}")

print("""
  ⚠️ Resurslar (fayl, soket, Lock) nusxalanmaydi —
     ular OS obyektlariga bog'langan.

  ✅ Yechim: __deepcopy__ da resursni QAYTA YARATING
     (yoki umumiy qoldiring, agar xavfsiz bo'lsa).
""")

Natijaning muhim qismi:

text
=== 3. Umumiy obyektlar ===
    a['birinchi'] is a['ikkinchi']:  True   ← umumiy

  b = copy.deepcopy(a):
    b['birinchi'] is b['ikkinchi']:  True   ⭐ SAQLANDI
    b['birinchi'] is a['birinchi']:  False   ← yangi

  ⚠️ JSON bilan solishtiring:
    c['birinchi'] is c['ikkinchi']:  False   ⚠️ SHAKL YO'QOLDI

=== 4. memo lug'atini kuzatish ===
  __deepcopy__ chaqiruvlari:
    1. __deepcopy__(a), memo hajmi: 0
    2. __deepcopy__(b), memo hajmi: 2
    3. __deepcopy__(c), memo hajmi: 5

  ⭐ Har obyekt FAQAT BIR MARTA nusxalandi

Nima ko'rsatdi: 2.3-bo'lim.

Misol 3 — __copy__, __deepcopy__ va tezlik

python
"""Nusxa mantiqini boshqarish va optimallashtirish."""

import copy
import time
import json
import pickle
import sys
from dataclasses import dataclass, field, replace

print("=== 1. __copy__ va __deepcopy__ ===")


class Ulanish:
    """Resurs bilan ishlaydigan sinf."""

    yaratilgan = 0

    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.soket = self._ulan()
        self.kesh = {"sorovlar": [], "natijalar": {}}
        self.statistika = {"soni": 0}

    def _ulan(self):
        Ulanish.yaratilgan += 1
        return f"<soket#{Ulanish.yaratilgan} {self.host}:{self.port}>"

    def __copy__(self):
        """Sayoz — yangi ulanish, kesh UMUMIY."""
        yangi = Ulanish.__new__(Ulanish)
        yangi.__dict__.update(self.__dict__)
        yangi.soket = yangi._ulan()             # ⭐ resurs qayta yaratiladi
        return yangi

    def __deepcopy__(self, memo):
        """Chuqur — hamma narsa yangi."""
        yangi = Ulanish.__new__(Ulanish)
        memo[id(self)] = yangi                  # ⭐ REKURSIYADAN OLDIN
        yangi.host = self.host
        yangi.port = self.port
        yangi.soket = yangi._ulan()
        yangi.kesh = copy.deepcopy(self.kesh, memo)
        yangi.statistika = copy.deepcopy(self.statistika, memo)
        return yangi

    def __repr__(self):
        return f"Ulanish({self.host}:{self.port}, {self.soket})"


u1 = Ulanish("db.wisar.uz", 5432)
u1.kesh["sorovlar"].append("SELECT 1")

print(f"  u1 = {u1}")
print(f"  u1.kesh = {u1.kesh}\n")

u_sayoz = copy.copy(u1)
u_chuqur = copy.deepcopy(u1)

print(f"  {'':<14} {'soket':<32} {'kesh is'}")
print("  " + "─" * 58)
print(f"  {'asl':<14} {u1.soket:<32}")
print(f"  {'copy':<14} {u_sayoz.soket:<32} {u_sayoz.kesh is u1.kesh}")
print(f"  {'deepcopy':<14} {u_chuqur.soket:<32} {u_chuqur.kesh is u1.kesh}")

u_sayoz.kesh["sorovlar"].append("SAYOZ")
u_chuqur.kesh["sorovlar"].append("CHUQUR")

print(f"\n  Keshga yozgandan keyin:")
print(f"    u1.kesh:       {u1.kesh['sorovlar']}")
print(f"    u_sayoz.kesh:  {u_sayoz.kesh['sorovlar']}")
print(f"    u_chuqur.kesh: {u_chuqur.kesh['sorovlar']}")

print("""
  ⭐ __copy__ / __deepcopy__ — resurslarni to'g'ri boshqarish usuli.
     Ularsiz soket "nusxalanardi" (aslida bir xil havola qolardi).
""")


print("\n=== 2. ⚠️ memo ni unutish ===")


class Yomon:
    """❌ memo ga yozmaydi."""

    def __init__(self, nom):
        self.nom = nom
        self.havola = None

    def __deepcopy__(self, memo):
        yangi = Yomon(self.nom)
        # memo[id(self)] = yangi   ← YO'Q!
        yangi.havola = copy.deepcopy(self.havola, memo)
        return yangi


class Yaxshi:
    def __init__(self, nom):
        self.nom = nom
        self.havola = None

    def __deepcopy__(self, memo):
        yangi = Yaxshi.__new__(Yaxshi)
        memo[id(self)] = yangi              # ⭐
        yangi.nom = self.nom
        yangi.havola = copy.deepcopy(self.havola, memo)
        return yangi


for sinf, nom in [(Yaxshi, "Yaxshi"), (Yomon, "Yomon")]:
    a = sinf("a")
    a.havola = a                            # aylanma
    try:
        n = copy.deepcopy(a)
        natija = f"✅ nusxa.havola is nusxa: {n.havola is n}"
    except RecursionError:
        natija = "❌ RecursionError"
    print(f"  {nom:<10} {natija}")

print(f"\n  ⭐ memo[id(self)] = yangi — rekursiv chaqiruvlardan OLDIN")


print("\n=== 3. Tezlik solishtirilishi ===")


def katta_tuzilma(n=200):
    return {
        f"kalit{i}": {
            "sonlar": list(range(20)),
            "matn": f"qiymat-{i}" * 3,
            "ichki": {"a": i, "b": [{"x": j, "y": [j, j + 1]} for j in range(4)]},
        }
        for i in range(n)
    }


KATTA = katta_tuzilma()

USULLAR = []


def olch(nom, f):
    boshlandi = time.perf_counter()
    natija = f()
    return (nom, time.perf_counter() - boshlandi, natija)


USULLAR.append(olch("copy.copy (SAYOZ ⚠️)", lambda: copy.copy(KATTA)))
USULLAR.append(olch("qo'lda (ma'lum tuzilma)", lambda: {
    k: {"sonlar": list(v["sonlar"]), "matn": v["matn"],
        "ichki": {"a": v["ichki"]["a"],
                  "b": [{"x": d["x"], "y": list(d["y"])} for d in v["ichki"]["b"]]}}
    for k, v in KATTA.items()
}))
USULLAR.append(olch("json roundtrip",
                    lambda: json.loads(json.dumps(KATTA))))
USULLAR.append(olch("pickle roundtrip",
                    lambda: pickle.loads(pickle.dumps(KATTA))))
USULLAR.append(olch("copy.deepcopy", lambda: copy.deepcopy(KATTA)))

eng_tez = min(v for _, v, _ in USULLAR)
print(f"  {len(KATTA)} ta ichma-ich yozuv:\n")
print(f"  {'Usul':<28} {'Vaqt':>10} {'Nisbat':>9} {'Mustaqil'}")
print("  " + "─" * 62)

for nom, vaqt, natija in sorted(USULLAR, key=lambda x: x[1]):
    # Mustaqillik tekshiruvi
    try:
        natija["kalit0"]["sonlar"].append(999)
        mustaqil = "✅" if 999 not in KATTA["kalit0"]["sonlar"] else "❌"
        if mustaqil == "❌":
            KATTA["kalit0"]["sonlar"].remove(999)
    except Exception:
        mustaqil = "?"
    print(f"  {nom:<28} {vaqt * 1000:>7.2f} ms {vaqt / eng_tez:>8.1f}x {mustaqil:>9}")


print("\n=== 4. json va pickle cheklovlari ===")

from datetime import datetime
from decimal import Decimal

SINOVLAR = [
    ("dict/list/str/int",   {"a": [1, "x", 2.5, True, None]}),
    ("tuple",               {"a": (1, 2)}),
    ("set",                 {"a": {1, 2}}),
    ("datetime",            {"a": datetime(2026, 9, 8)}),
    ("Decimal",             {"a": Decimal("1.5")}),
    ("bytes",               {"a": b"xyz"}),
    ("int kaliti",          {1: "a", 2: "b"}),
]

print(f"  {'Ma`lumot':<22} {'json':<24} {'pickle':<12} {'deepcopy'}")
print("  " + "─" * 70)

for nom, malumot in SINOVLAR:
    # JSON
    try:
        j = json.loads(json.dumps(malumot))
        j_natija = "✅" if j == malumot else f"⚠️ {type(list(j.values())[0]).__name__}"
    except (TypeError, ValueError):
        j_natija = "❌ xato"

    # pickle
    try:
        p = pickle.loads(pickle.dumps(malumot))
        p_natija = "✅" if p == malumot else "⚠️"
    except Exception:
        p_natija = "❌"

    # deepcopy
    try:
        d = copy.deepcopy(malumot)
        d_natija = "✅" if d == malumot else "⚠️"
    except Exception:
        d_natija = "❌"

    print(f"  {nom:<22} {j_natija:<24} {p_natija:<12} {d_natija}")

print(f"\n  Aylanma havola bilan:")
a = {"x": 1}
a["o'zi"] = a
for nom, f in [("json", lambda: json.dumps(a)),
               ("pickle", lambda: pickle.loads(pickle.dumps(a))),
               ("deepcopy", lambda: copy.deepcopy(a))]:
    try:
        f()
        natija = "✅"
    except (ValueError, RecursionError) as x:
        natija = f"❌ {type(x).__name__}"
    print(f"    {nom:<12} {natija}")

print("""
  ⭐ json:     eng cheklangan, lekin tez va o'qiladigan
     pickle:   ko'p tur, aylanma ✅, lekin xavfsizlik masalasi
     deepcopy: hamma narsa, lekin sekin
""")


print("\n=== 5. Optimallashtirish ===")


class KattaObyekt:
    """Katta o'zgarmas kesh + kichik o'zgaruvchan holat."""

    def __init__(self):
        self.katta_kesh = {i: f"qiymat-{i}" * 10 for i in range(5000)}
        self.holat = {"joriy": 0, "tarix": []}


class OptimallashtirilganObyekt(KattaObyekt):
    """__deepcopy__ bilan — kesh nusxalanmaydi."""

    def __deepcopy__(self, memo):
        yangi = OptimallashtirilganObyekt.__new__(OptimallashtirilganObyekt)
        memo[id(self)] = yangi
        yangi.katta_kesh = self.katta_kesh          # ⭐ UMUMIY (o'zgarmas)
        yangi.holat = copy.deepcopy(self.holat, memo)
        return yangi


for sinf, nom in [(KattaObyekt, "Sukut deepcopy"),
                  (OptimallashtirilganObyekt, "__deepcopy__ bilan")]:
    o = sinf()
    boshlandi = time.perf_counter()
    for _ in range(5):
        n = copy.deepcopy(o)
    vaqt = (time.perf_counter() - boshlandi) / 5
    umumiy = n.katta_kesh is o.katta_kesh
    print(f"  {nom:<24} {vaqt * 1000:>8.2f} ms   kesh umumiy: {umumiy}")

print("""
  ⭐ Katta o'zgarmas ma'lumotni nusxalamaslik —
     eng samarali optimallashtirish.
""")


print("\n=== 6. Nusxa KERAK EMAS ===")


@dataclass(frozen=True)
class Holat:
    ball: int
    daraja: int
    teglar: frozenset = frozenset()


h1 = Holat(100, 1, frozenset({"a"}))
h2 = replace(h1, ball=200)
h3 = replace(h1, teglar=h1.teglar | {"b"})

print(f"  @dataclass(frozen=True) bilan:\n")
print(f"    h1 = {h1}")
print(f"    h2 = replace(h1, ball=200)")
print(f"       = {h2}")
print(f"    h3 = replace(h1, teglar=h1.teglar | {{'b'}})")
print(f"       = {h3}")
print(f"\n    h1 o'zgarmadi: {h1}")
print(f"    ⭐ deepcopy KERAK EMAS — har amal yangi obyekt yaratadi")

print(f"\n  Yangi obyekt yaratuvchi amallar:")
AMALLAR = [
    ("[x*2 for x in r]",        "yangi ro'yxat"),
    ("r + [1]",                 "yangi ro'yxat"),
    ("sorted(r)",               "yangi ro'yxat"),
    ("{**d1, **d2}",            "yangi lug'at (sayoz)"),
    ("d1 | d2",                 "yangi lug'at (sayoz)"),
    ("s1 | s2",                 "yangi to'plam"),
    ("t + (1,)",                "yangi tuple"),
    ("replace(dc, x=1)",        "yangi dataclass"),
    ("nt._replace(x=1)",        "yangi namedtuple"),
]
for kod, izoh in AMALLAR:
    print(f"    {kod:<24} → {izoh}")

Natijaning muhim qismi:

text
=== 3. Tezlik solishtirilishi ===
  200 ta ichma-ich yozuv:

  Usul                              Vaqt    Nisbat  Mustaqil
  ──────────────────────────────────────────────────────────────
  copy.copy (SAYOZ ⚠️)              0.02 ms      1.0x         ❌
  qo'lda (ma'lum tuzilma)           1.84 ms     92.0x         ✅
  pickle roundtrip                  4.12 ms    206.0x         ✅
  json roundtrip                    6.31 ms    315.5x         ✅
  copy.deepcopy                    28.42 ms   1421.0x         ✅

=== 4. json va pickle cheklovlari ===
  Ma`lumot               json                     pickle       deepcopy
  ──────────────────────────────────────────────────────────────────────
  tuple                  ⚠️ list                  ✅            ✅
  set                    ❌ xato                  ✅            ✅
  datetime               ❌ xato                  ✅            ✅
  int kaliti             ⚠️ str                   ✅            ✅

Nima ko'rsatdi: 2.4, 2.5, 2.6-bo'limlar.

Misol 4 — Amaliy: undo/redo va holat boshqaruvi

python
"""Nusxa olishning real qo'llanishi."""

import copy
import time
from dataclasses import dataclass, field, replace
from typing import Any

print("=== 1. Undo/Redo — mutable holat bilan ===")


class Hujjat:
    """copy.deepcopy bilan tarix."""

    def __init__(self):
        self.matn: list[str] = []
        self.uslub: dict[str, Any] = {"shrift": "Arial", "hajm": 12}
        self.metadata: dict[str, Any] = {"muallif": "", "teglar": []}
        self._tarix: list[tuple] = []
        self._kelajak: list[tuple] = []

    def _holat(self):
        return copy.deepcopy((self.matn, self.uslub, self.metadata))

    def _tiklash(self, holat):
        self.matn, self.uslub, self.metadata = copy.deepcopy(holat)

    def _saqlash(self):
        self._tarix.append(self._holat())
        self._kelajak.clear()

    def qator_qosh(self, matn: str):
        self._saqlash()
        self.matn.append(matn)
        return self

    def uslub_ozgartir(self, **kwargs):
        self._saqlash()
        self.uslub.update(kwargs)
        return self

    def teg_qosh(self, teg: str):
        self._saqlash()
        self.metadata["teglar"].append(teg)
        return self

    def bekor(self):
        if not self._tarix:
            return self
        self._kelajak.append(self._holat())
        self._tiklash(self._tarix.pop())
        return self

    def qayta(self):
        if not self._kelajak:
            return self
        self._tarix.append(self._holat())
        self._tiklash(self._kelajak.pop())
        return self

    def __repr__(self):
        return (f"Hujjat({len(self.matn)} qator, "
                f"{self.uslub}, teglar={self.metadata['teglar']})")


h = Hujjat()

AMALLAR = [
    ("qator_qosh('Salom')",     lambda: h.qator_qosh("Salom")),
    ("qator_qosh('Dunyo')",     lambda: h.qator_qosh("Dunyo")),
    ("uslub_ozgartir(hajm=14)", lambda: h.uslub_ozgartir(hajm=14)),
    ("teg_qosh('muhim')",       lambda: h.teg_qosh("muhim")),
    ("bekor()",                 lambda: h.bekor()),
    ("bekor()",                 lambda: h.bekor()),
    ("qayta()",                 lambda: h.qayta()),
    ("qator_qosh('Yangi')",     lambda: h.qator_qosh("Yangi")),
    ("qayta()",                 lambda: h.qayta()),
]

print(f"  {'Amal':<26} {'Holat'}")
print("  " + "─" * 76)
print(f"  {'(boshlang`ich)':<26} {h}")
for nom, f in AMALLAR:
    f()
    print(f"  {nom:<26} {h}")

print(f"""
  ⭐ deepcopy tufayli har holat MUSTAQIL —
     tarixdagi holatlar joriy holat bilan bog'lanmagan.

  ⚠️ Lekin har amal butun holatni nusxalaydi — sekin.
""")


print("\n=== 2. Undo/Redo — o'zgarmas holat bilan ===")


@dataclass(frozen=True)
class HolatIm:
    """O'zgarmas holat — nusxa KERAK EMAS."""
    matn: tuple[str, ...] = ()
    shrift: str = "Arial"
    hajm: int = 12
    teglar: frozenset = frozenset()

    def qator_qosh(self, matn: str) -> "HolatIm":
        return replace(self, matn=(*self.matn, matn))

    def uslub_ozgartir(self, **kwargs) -> "HolatIm":
        return replace(self, **kwargs)

    def teg_qosh(self, teg: str) -> "HolatIm":
        return replace(self, teglar=self.teglar | {teg})

    def __repr__(self):
        return (f"H({len(self.matn)} qator, {self.shrift} {self.hajm}, "
                f"teglar={sorted(self.teglar)})")


class HujjatIm:
    """O'zgarmas holat + oddiy ro'yxat = tarix."""

    def __init__(self):
        self._tarix = [HolatIm()]
        self._joy = 0

    @property
    def holat(self) -> HolatIm:
        return self._tarix[self._joy]

    def amal(self, f):
        yangi = f(self.holat)
        self._tarix = self._tarix[:self._joy + 1] + [yangi]      # ⭐ nusxa yo'q
        self._joy = len(self._tarix) - 1
        return self

    def bekor(self):
        self._joy = max(0, self._joy - 1)
        return self

    def qayta(self):
        self._joy = min(len(self._tarix) - 1, self._joy + 1)
        return self


hi = HujjatIm()

AMALLAR2 = [
    ("qator_qosh('Salom')",     lambda h: h.qator_qosh("Salom")),
    ("qator_qosh('Dunyo')",     lambda h: h.qator_qosh("Dunyo")),
    ("uslub(hajm=14)",          lambda h: h.uslub_ozgartir(hajm=14)),
    ("teg_qosh('muhim')",       lambda h: h.teg_qosh("muhim")),
]

print(f"  {'Amal':<26} {'Holat'}")
print("  " + "─" * 70)
print(f"  {'(boshlang`ich)':<26} {hi.holat}")
for nom, f in AMALLAR2:
    hi.amal(f)
    print(f"  {nom:<26} {hi.holat}")

hi.bekor().bekor()
print(f"  {'bekor() ×2':<26} {hi.holat}")
hi.qayta()
print(f"  {'qayta()':<26} {hi.holat}")

print(f"\n  Tarix uzunligi: {len(hi._tarix)}, joriy: {hi._joy}")

print("""
  ⭐ O'zgarmas holat bilan:
     • deepcopy KERAK EMAS
     • Tarix — oddiy ro'yxat
     • Umumiy qismlar avtomatik umumiy (structural sharing)
     • Ancha tezroq
""")


print("\n=== 3. Tezlik solishtirilishi ===")

N = 300

# Mutable + deepcopy
h1 = Hujjat()
boshlandi = time.perf_counter()
for i in range(N):
    h1.qator_qosh(f"Qator {i}")
vaqt_mutable = time.perf_counter() - boshlandi

# Immutable
h2 = HujjatIm()
boshlandi = time.perf_counter()
for i in range(N):
    h2.amal(lambda h, i=i: h.qator_qosh(f"Qator {i}"))
vaqt_immutable = time.perf_counter() - boshlandi

print(f"  {N} amal + to'liq tarix:\n")
print(f"    Mutable + deepcopy:  {vaqt_mutable * 1000:>8.1f} ms")
print(f"    Immutable:           {vaqt_immutable * 1000:>8.1f} ms")
print(f"    Farq:                {vaqt_mutable / vaqt_immutable:>8.1f}x")

import sys
print(f"\n  Xotira (taxminiy):")
print(f"    Mutable tarix:   {len(h1._tarix)} to'liq nusxa")
print(f"    Immutable tarix: {len(h2._tarix)} holat, umumiy qismlar bilan")


print("\n\n=== 4. Sukut argument tuzog'i ===")


def yomon(element, royxat=[]):
    """❌ O'zgaruvchan sukut argument."""
    royxat.append(element)
    return royxat


def yaxshi(element, royxat=None):
    """✅ None bilan."""
    if royxat is None:
        royxat = []
    royxat.append(element)
    return royxat


def yaxshi2(element, royxat=()):
    """✅ O'zgarmas sukut."""
    return [*royxat, element]


print(f"  ❌ def f(x, royxat=[]):")
print(f"    yomon(1) → {yomon(1)}")
print(f"    yomon(2) → {yomon(2)}   ⚠️ oldingi qiymat qoldi!")
print(f"    yomon(3) → {yomon(3)}   ⚠️")

print(f"\n  ✅ def f(x, royxat=None):")
print(f"    yaxshi(1) → {yaxshi(1)}")
print(f"    yaxshi(2) → {yaxshi(2)}")
print(f"    yaxshi(3) → {yaxshi(3)}")

print(f"\n  ✅ def f(x, royxat=()):")
print(f"    yaxshi2(1) → {yaxshi2(1)}")
print(f"    yaxshi2(2) → {yaxshi2(2)}")

print(f"\n  Sabab:")
print(f"    yomon.__defaults__ = {yomon.__defaults__}")
print(f"    ⚠️ Sukut qiymat FUNKSIYA YARATILGANDA bir marta hisoblanadi")


print("\n\n=== 5. Funksiya argumentini o'zgartirish ===")


def yomon_qosh(royxat, element):
    """⚠️ Chaqiruvchining ro'yxatini o'zgartiradi."""
    royxat.append(element)
    return royxat


def yaxshi_qosh(royxat, element):
    """✅ Yangi ro'yxat qaytaradi."""
    return [*royxat, element]


def aniq_qosh(royxat, element) -> None:
    """✅ Ataylab joyida — None qaytaradi (6.2-dars kelishuvi)."""
    royxat.append(element)


ASL = [1, 2, 3]

r1 = ASL.copy()
natija = yomon_qosh(r1, 4)
print(f"  yomon_qosh(r, 4):")
print(f"    natija = {natija}")
print(f"    r      = {r1}   ⚠️ o'zgardi")
print(f"    natija is r: {natija is r1}")

r2 = ASL.copy()
natija = yaxshi_qosh(r2, 4)
print(f"\n  yaxshi_qosh(r, 4):")
print(f"    natija = {natija}")
print(f"    r      = {r2}   ✅ o'zgarmadi")

r3 = ASL.copy()
natija = aniq_qosh(r3, 4)
print(f"\n  aniq_qosh(r, 4):")
print(f"    natija = {natija}   ⭐ None — 'joyida o'zgartirdim' signali")
print(f"    r      = {r3}")

print("""
  ⭐ Uch variant:
     1. Yangi obyekt qaytaring — eng xavfsiz
     2. Joyida o'zgartiring va None qaytaring — aniq signal
     3. ❌ Joyida o'zgartirib, obyektni qaytarish — chalkash
""")


print("\n=== 6. 6-QISM YAKUNI: qaysi tuzilma qachon ===")

print("""
  ┌──────────────────────────┬────────────────────────────────────┐
  │ Vazifa                   │ Tuzilma                            │
  ├──────────────────────────┼────────────────────────────────────┤
  │ Tartibli ketma-ketlik    │ list                               │
  │ O'zgarmas yozuv          │ tuple / NamedTuple                 │
  │ Nomli maydonlar          │ NamedTuple / dataclass             │
  │ Noyoblik + tez `in`      │ set                                │
  │ O'zgarmas to'plam, kalit │ frozenset                          │
  │ Kalit → qiymat           │ dict                               │
  │ Sanash                   │ Counter                            │
  │ Guruhlash                │ defaultdict(list)                  │
  │ Qatlamlar                │ ChainMap                           │
  │ LRU / FIFO               │ OrderedDict / deque                │
  │ Navbat                   │ deque                              │
  │ Bir turdagi sonlar       │ array / numpy                      │
  │ Bir marta o'tish         │ generator ifodasi                  │
  │ O'zgarmas holat          │ frozen dataclass + replace()       │
  └──────────────────────────┴────────────────────────────────────┘

  Nusxa olish:
    O'zgarmas turlar          → nusxa kerak emas
    Ichida faqat o'zgarmas    → a.copy() yetarli
    Ichma-ich o'zgaruvchan    → copy.deepcopy()
    Katta + JSON turlari      → json roundtrip (tezroq)
    Resurslar bor             → __deepcopy__ yozing
    Tez-tez nusxa kerak       → o'zgarmas tuzilmalarga o'ting
""")

Natijaning muhim qismi:

text
=== 1. Undo/Redo — mutable holat bilan ===
  Amal                       Holat
  ────────────────────────────────────────────────────────────────────────────
  (boshlang`ich)             Hujjat(0 qator, {'shrift': 'Arial', 'hajm': 12}, teglar=[])
  qator_qosh('Salom')        Hujjat(1 qator, {'shrift': 'Arial', 'hajm': 12}, teglar=[])
  uslub_ozgartir(hajm=14)    Hujjat(2 qator, {'shrift': 'Arial', 'hajm': 14}, teglar=[])
  bekor()                    Hujjat(2 qator, {'shrift': 'Arial', 'hajm': 14}, teglar=[])

=== 3. Tezlik solishtirilishi ===
  300 amal + to'liq tarix:

    Mutable + deepcopy:      184.2 ms
    Immutable:                 4.1 ms
    Farq:                     44.9x

=== 4. Sukut argument tuzog'i ===
  ❌ def f(x, royxat=[]):
    yomon(1) → [1]
    yomon(2) → [1, 2]   ⚠️ oldingi qiymat qoldi!

Nima ko'rsatdi: 2.5, 2.6, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"a.copy() to'liq nusxa" Sayoz — ichki obyektlar umumiy
"deepcopy aylanma havolada osilib qoladi" memo bilan hal qilinadi
"deepcopy umumiy obyektlarni ajratadi" Shakl saqlanadi
"json roundtrip deepcopy o'rnini bosadi" Turlar cheklangan, shakl yo'qoladi
"copy.copy(t) is t xato" O'zgarmas tur uchun to'g'ri
"__deepcopy__ da memo ixtiyoriy" Majburiy — aylanmada rekursiya
"Har o'zgartirishdan oldin nusxa kerak" Ko'p amal allaqachon yangi obyekt beradi
"deepcopy har doim ishlaydi" Fayl, soket, Lock — TypeError
"Funksiya argumentini o'zgartirish normal" Chaqiruvchini ajablantiradi

6. Keng tarqalgan xatolar va yechimlari

1. Sayoz nusxaga ishonish

python
n = d.copy()
n["ichki"]["x"] = 1                     # ⚠️ asl ham o'zgardi
n = copy.deepcopy(d)                    # ✅

2. __deepcopy__ da memo ni unutish

python
def __deepcopy__(self, memo):
    yangi = Sinf()
    yangi.h = copy.deepcopy(self.h, memo)       # ❌ aylanmada RecursionError
    return yangi

def __deepcopy__(self, memo):
    yangi = Sinf.__new__(Sinf)
    memo[id(self)] = yangi                      # ✅
    yangi.h = copy.deepcopy(self.h, memo)
    return yangi

3. O'zgaruvchan sukut argument

python
def f(r=[]):                            # ❌
def f(r=None):                          # ✅
    r = [] if r is None else r
def f(r=()):                            # ✅

4. json bilan noto'g'ri turlar

python
json.loads(json.dumps(d))               # ⚠️ set, datetime, tuple
copy.deepcopy(d)                        # ✅

5. Keraksiz deepcopy

python
def f(malumot):
    n = copy.deepcopy(malumot)          # ⚠️ o'zgartirmasangiz kerak emas
    return sum(n)

def f(malumot):
    return sum(malumot)                 # ✅

6. Funksiya argumentini o'zgartirish

python
def qosh(r, x):
    r.append(x); return r               # ⚠️ chaqiruvchi ajablanadi

def qosh(r, x):
    return [*r, x]                      # ✅

7. Sinf atributi sifatida o'zgaruvchan

python
class A:
    teglar = []                         # ⚠️ BARCHA obyektlarga umumiy

class A:
    def __init__(self):
        self.teglar = []                # ✅

8. Katta obyektni to'liq nusxalash

python
copy.deepcopy(katta_obyekt)             # ⚠️ sekin

def __deepcopy__(self, memo):           # ✅
    yangi.katta_kesh = self.katta_kesh  # o'zgarmas — umumiy

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 6.1-dars (o'tilgan): yorliq modeli — bu darsning asosi
  • 6.14-dars (o'tilgan): ichma-ich tuzilmalar
  • 6.5, 6.9-darslar (o'tilgan): o'zgarmaslik va hashlanish
  • 7-qism: sukut argumentlar, funksiya argumentlarini o'zgartirish
  • 8-qism: __copy__, __deepcopy__, dataclass(frozen=True)
  • 16-qism: pickle, serializatsiya
  • 11, 18-qismlar: profillash, GC, xotira

8. Eng yaxshi amaliyotlar

  1. Ichma-ich tuzilma uchun deepcopy. copy() deyarli har doim yetarli emas.

  2. Nusxa kerakmi — o'ylab ko'ring. Ko'p amal allaqachon yangi obyekt beradi.

  3. O'zgarmas tuzilmalarga o'ting. frozen dataclass + replace() — nusxa umuman kerak emas.

  4. __deepcopy__ da memo[id(self)] ni birinchi qatorda. Rekursiv chaqiruvlardan oldin.

  5. Resurslar uchun __copy__/__deepcopy__ yozing. Soket, fayl, ulanish.

  6. Sukut argument — o'zgarmas yoki None. [], {}, set() — hech qachon.

  7. Funksiya argumentini o'zgartirmang. Yoki None qaytaring.

  8. Tezlik muhim bo'lsa qo'lda nusxalang. Tuzilma ma'lum bo'lsa deepcopy dan 10-50x tez.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
import copy
a = [[1, 2], [3, 4]]      # ⚠️ har band ALOHIDA: a har safar shu qiymatdan boshlanadi

1.  b = a; b[0].append(9); print(a)
2.  b = a.copy(); b[0].append(9); print(a)
3.  b = copy.deepcopy(a); b[0].append(9); print(a)
4.  b = a.copy(); b[0] = "X"; print(a)
5.  t = (1, [2]); print(copy.copy(t) is t)
6.  t = (1, [2]); print(copy.deepcopy(t) is t)
7.  print(copy.deepcopy(42) is 42)
8.  print(copy.deepcopy(print) is print)
9.  u = [1]; a2 = [u, u]; b2 = copy.deepcopy(a2); print(b2[0] is b2[1])
10. import json; a3 = {"x": [1], "y": [1]}
    a3["y"] = a3["x"]; c = json.loads(json.dumps(a3)); print(c["x"] is c["y"])
11. x = [1]; x.append(x); print(len(copy.deepcopy(x)))
12. print(copy.copy(frozenset([1])) is copy.copy(frozenset([1])))
Javoblar
  1. [[1, 2, 9], [3, 4]] — havola
  2. [[1, 2, 9], [3, 4]] — sayoz
  3. [[1, 2], [3, 4]] — chuqur
  4. [[1, 2], [3, 4]] — konteyner alohida
  5. True — sayoz: o'zi qaytadi
  6. False — chuqur: ichida list bor
  7. True — atomik
  8. True — funksiya atomik
  9. True — shakl saqlandi
  10. False — JSON shaklni yo'qotadi
  11. 2 — [1, [...]]
  12. False — turli frozenset obyektlari (interning yo'q)

Vazifa 2: Xatolarni tuzating

python
1.  n = konfiguratsiya.copy(); n["baza"]["host"] = "yangi"
2.  def f(x, r=[]): r.append(x); return r
3.  def __deepcopy__(self, memo):
        y = Sinf(); y.h = copy.deepcopy(self.h, memo); return y
4.  n = json.loads(json.dumps(d))   # d da datetime va set bor
5.  def qosh(r, x): r.append(x); return r
6.  class A: teglar = []
7.  def f(m): n = copy.deepcopy(m); return sum(n)
8.  copy.deepcopy(obyekt)   # obyektda ochiq fayl bor
Javoblar
python
1.  n = copy.deepcopy(konfiguratsiya)
2.  def f(x, r=None): r = [] if r is None else r; r.append(x); return r
3.  y = Sinf.__new__(Sinf); memo[id(self)] = y; y.h = ...
4.  n = copy.deepcopy(d)
5.  def qosh(r, x): return [*r, x]
6.  class A:
        def __init__(self): self.teglar = []
7.  def f(m): return sum(m)
8.  __deepcopy__ yozing — faylni qayta oching yoki tashlab yuboring

Vazifa 3: Nusxa tahlilchisi

Funksiya yozing:

python
def nusxa_tahlil(obyekt) -> dict:
    """Sayoz nusxa yetarlimi, deepcopy kerakmi, nusxalanadimi."""
  1. O'zgaruvchan ichki obyektlarni topsin
  2. Aylanma havolalarni aniqlasin
  3. Nusxalanmaydigan obyektlarni topsin
  4. Taxminiy deepcopy vaqtini baholasin
  5. Tavsiya bersin (copy, deepcopy, json, qo'lda)

Vazifa 4: Tez nusxa generatori

Ma'lum sxema uchun optimal nusxa funksiyasini generatsiya qiluvchi vosita:

  1. Namunadan tuzilmani aniqlash
  2. Qo'lda nusxa kodini yaratish (exec bilan)
  3. O'zgarmas qismlarni nusxalamaslik
  4. deepcopy bilan tezlikni solishtirish
  5. To'g'riligini tekshirish (tasodifiy ma'lumot bilan)

Vazifa 5: Undo/Redo tizimi

Ikki versiyani yozing va solishtiring:

  1. Mutable + deepcopy
  2. Immutable + replace
  3. Command pattern (faqat o'zgarishlarni saqlash)
  4. Har biri uchun: tezlik, xotira, kod murakkabligi
  5. Tarix chegarasi (maxlen)
  6. Guruhlangan amallar (bir necha o'zgarishni bitta undo bilan)

Vazifa 6: Resurs boshqaruvi

__copy__ va __deepcopy__ bilan sinflar:

  1. Ulanish — soketni qayta yaratadi
  2. KattaKesh — keshni umumiy qoldiradi
  3. Hujjat — faylni qayta ochadi
  4. Sozlamalar — faqat o'zgargan maydonlarni nusxalaydi
  5. Har biri uchun testlar (aylanma havola bilan ham)

Vazifa 7: O'ylash

Nega copy.deepcopy shunchalik sekin, va nega buni tezlashtirish qiyin?

Javob

Sabab: u umumiy, xavfsiz va to'g'ri bo'lishi kerak.

Har obyekt uchun deepcopy nima qiladi:

python
def deepcopy(x, memo):
    # 1. memo tekshiruvi — aylanma va umumiy obyektlar uchun
    y = memo.get(id(x), _nil)
    if y is not _nil:
        return y

    # 2. Tur bo'yicha dispatcher
    cls = type(x)
    copier = _deepcopy_dispatch.get(cls)
    if copier is not None:
        y = copier(x, memo)
    else:
        # 3. __deepcopy__ bormi
        copier = getattr(x, "__deepcopy__", None)
        if copier is not None:
            y = copier(memo)
        else:
            # 4. __reduce_ex__ (pickle protokoli)
            rv = x.__reduce_ex__(4)
            y = _reconstruct(x, memo, *rv)

    # 5. memo ga yozish
    if y is not x:
        memo[id(x)] = y
        _keep_alive(x, memo)        # ⚠️ GC dan himoya
    return y

Har qadamning narxi:

Qadam Narx
memo.get(id(x)) Hash hisoblash + lug'at qidiruvi
type(x) + dispatch Lug'at qidiruvi
getattr(x, "__deepcopy__") Atribut qidiruvi (MRO bo'ylab)
__reduce_ex__ Funksiya chaqiruvi + tuple yaratish
memo[id(x)] = y Lug'at yozuvi
_keep_alive Yana lug'at amali

Bu — har bir element uchun. 10 000 elementli tuzilmada 60 000+ lug'at amali.

Nega tezlashtirib bo'lmaydi:

1. memo — majburiy.

Aylanma havolalar va umumiy obyektlar uchun id → nusxa xaritasi kerak. Uni olib tashlash deepcopy ni noto'g'ri qiladi.

2. Tur oldindan noma'lum.

deepcopy har qanday obyekt bilan ishlashi kerak: ichki turlar, foydalanuvchi sinflari, C kengaytmalari, __slots__ li sinflar, meros bilan... Har biri uchun dispatch kerak.

Qo'lda nusxada esa tur ma'lum:

python
nusxa = {k: list(v) for k, v in d.items()}      # dispatch yo'q

3. _keep_alive — GC muammosi.

python
def _keep_alive(x, memo):
    try:
        memo[id(memo)].append(x)
    except KeyError:
        memo[id(memo)] = [x]

memo id() bilan ishlaydi. Agar asl obyekt GC tomonidan yig'ilsa, uning id si qayta ishlatilishi mumkin — va memo da noto'g'ri moslik paydo bo'ladi.

Shuning uchun deepcopy barcha asl obyektlarga havolani saqlaydi. Bu — qo'shimcha xotira va vaqt, lekin to'g'rilik uchun majburiy.

4. __reduce_ex__ — umumiy, lekin sekin.

Maxsus metodsiz sinflar uchun deepcopy pickle protokolini ishlatadi:

python
rv = x.__reduce_ex__(4)         # (yaratuvchi, args, holat, ...)
y = _reconstruct(x, memo, *rv)

Bu — bir necha funksiya chaqiruvi va tuple yaratish har obyekt uchun.

Nima tezroq bo'lishi mumkin:

C da amalga oshirish. deepcopy — sof Python. C versiyasi 3-5x tezroq bo'lardi.

Bu bir necha marta taklif qilingan (bpo-issue'lar bor), lekin qabul qilinmagan:

  • Murakkab logika (pickle protokoli, __reduce_ex__)
  • Foydalanuvchi kodini chaqirish (__deepcopy__) — C dan qiyin
  • Talab past: ko'p kod deepcopy ni tor joyda ishlatmaydi

Amaliy yechimlar:

python
# 1. Nusxa kerakmi?
# 2. O'zgarmas tuzilmalar (nusxa umuman kerak emas)
# 3. Qo'lda nusxa (tuzilma ma'lum)
# 4. __deepcopy__ (katta o'zgarmas qismlarni o'tkazib yuborish)
# 5. pickle (ba'zan tezroq)
# 6. Tashqi kutubxona: `msgspec`, `orjson` (JSON turlari uchun)

Xulosa: deepcopy sekin, chunki u hech qanday taxmin qilmaydi. U har qanday obyekt bilan, har qanday tuzilmada, aylanma havolalar va umumiy obyektlar bilan to'g'ri ishlaydi. Bu universallik narxi.

Sizning kodingiz esa tuzilmani biladi — shuning uchun qo'lda nusxa har doim tezroq bo'ladi. Va eng yaxshi yechim — nusxa umuman kerak bo'lmaydigan dizayn.

Nimani mustahkamlaydi: 2.3, 2.5, 2.6, 2.7-bo'limlar.


Xulosa

Bu darsda nusxa olishni o'rgandik — va 6-qismni yakunladik.

Eng muhim uch fikr:

  1. Uch daraja bor: havola, sayoz, chuqur. b = a — bitta obyekt, a.copy() — yangi konteyner lekin eski ichki obyektlar, deepcopy(a) — hammasi yangi. Ichma-ich tuzilma uchun deyarli har doim deepcopy kerak.

  2. memo — deepcopy ning yuragi. U aylanma havolalarni hal qiladi va umumiy obyektlarni umumiy qoldiradi (tuzilma shaklini saqlaydi). json roundtrip tezroq, lekin shaklni yo'qotadi va turlari cheklangan.

  3. Eng yaxshi nusxa — kerak bo'lmagan nusxa. frozen dataclass + replace(), generator ifodalari, yangi obyekt qaytaruvchi amallar — bularning hech biri nusxa talab qilmaydi va ancha tezroq.


6-QISM YAKUNI

Bu qismda Pythonning barcha asosiy ma'lumot tuzilmalarini o'rgandik:

Dars Mavzu Asosiy fikr
1-4 list Yorliq modeli, metodlar, saralash, xotira
5-6 tuple O'zgarmaslik, hashlanish, nomli maydonlar
7-9 set O(1) in, to'plam amallari, frozenset
10-13 dict Tartib kafolati, collections, hash
14 Ichma-ich Xavfsiz o'qish, rekursiya
15-17 Generatorlar Sintaksis, dangasa hisoblash
18 Nusxa Uch daraja, memo

Uch umumiy tamoyil:

  1. O'zgaruvchanlik — asosiy ajratuvchi. list/dict/set o'zgaruvchan (hashlanmaydi), tuple/frozenset/str o'zgarmas (hashlanadi, kalit bo'la oladi).

  2. Hash jadvali — tezlikning asosi. set va dict in ni O(n) dan O(1) ga tushiradi, evaziga ~4x xotira oladi. Bu — deyarli har doim foydali savdo.

  3. To'g'ri tuzilmani tanlash — eng katta optimallashtirish. list o'rniga set (tekshiruv uchun), Counter (sanash), defaultdict (guruhlash), deque (navbat), generator (oqim) — har biri O(n²) ni O(n) ga aylantiradi.

Keyingi qism — 7-qism: Funksiyalar. U yerda argumentlar, qamrov, lambda, rekursiya va tur ko'rsatkichlarini chuqur o'rganamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
6.18-dars: Nusxa olish — copy va deepcopy — IlmHamroh