Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Terminologiya
- 2.2. Uzatish mexanizmi
- 2.3. Xavfsiz naqshlar
- 2.4. Argumentlar soni va tartibi
- 2.5. Ko'p parametrli funksiyalar
- 2.6. Argumentlarni tekshirish
- 2.7. Argumentlarni ochish
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uzatish mexanizmi
- Misol 2 — Argumentlar tartibi va ochish
- Misol 3 — Ko'p parametr va validatsiya
- Misol 4 — Amaliy: ma'lumot qayta ishlash quvuri
- 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
7.2-dars: Argument va parametr
7-QISM — FUNKSIYALAR · 2-dars
1. Kirish va motivatsiya
Ikki so'z tez-tez chalkashtiriladi:
def salomlash(ism): # ism — PARAMETR
print(f"Salom, {ism}!")
salomlash("Aziz") # "Aziz" — ARGUMENTParametr — funksiya ta'rifidagi nom. Argument — chaqiruvda uzatilgan qiymat.
Lekin asosiy savol boshqa: argument qanday uzatiladi?
def ozgartir(x):
x = 99
a = 1
ozgartir(a)
print(a) # 1 ← o'zgarmadidef ozgartir(r):
r.append(99)
a = [1, 2]
ozgartir(a)
print(a) # [1, 2, 99] ← o'zgardi!Bir xil kod, turli natija. Nega?
Va yanada chalkash:
def ozgartir(r):
r = [99] # ⚠️ almashtirish
a = [1, 2]
ozgartir(a)
print(a) # [1, 2] ← o'zgarmadiBu darsda:
- Parametr vs argument — aniq farq
- Uzatish mexanizmi — "obyektga havola bo'yicha uzatish"
- O'zgaruvchan va o'zgarmas argumentlar
- Xavfsiz naqshlar — argumentni buzmaslik
- Argumentlar soni va tartibi
- Ko'p parametrli funksiyalar muammosi
2. Nazariya — chuqur tushuntirish
2.1. Terminologiya
def f(a, b, c=3): # a, b, c — PARAMETRLAR
...
f(1, 2) # 1, 2 — ARGUMENTLAR
f(1, b=2) # 1 — pozitsion argument, b=2 — nomli argument| Termin | Ma'nosi |
|---|---|
| Parametr | Funksiya ta'rifidagi nom |
| Argument | Chaqiruvda uzatilgan qiymat |
| Pozitsion argument | Tartib bo'yicha (f(1, 2)) |
| Nomli argument | Nom bilan (f(a=1)) |
| Sukut qiymat | Parametr uchun standart (c=3) |
Ingliz tilida: parameter / argument. Ba'zan "formal parameter" va "actual parameter" deyiladi.
Amalda ko'pincha ikkalasi "argument" deyiladi — bu odatda muammo emas, lekin xato xabarlarida farq muhim:
def f(a, b): ...
f(1)
# TypeError: f() missing 1 required positional argument: 'b'
# ↑ parametr nomi2.2. Uzatish mexanizmi
Klassik savol: Python "qiymat bo'yicha" (by value) yoki "havola bo'yicha" (by reference) uzatadimi?
Javob: ikkalasi ham emas. Python "obyektga havolani qiymat bo'yicha" uzatadi (call by object reference / call by sharing).
Nima sodir bo'ladi:
def f(x):
...
a = [1, 2]
f(a)a— obyektga yorliq (6.1-dars)f(a)chaqirilganda,xshu obyektga yangi yorliq bo'ladi- Endi
avax— bitta obyektga ikki yorliq
a ──┐
├──→ [1, 2]
x ──┘Ikki holat:
1. Obyektni O'ZGARTIRISH — ikkala yorliqda ko'rinadi:
def f(x):
x.append(99) # OBYEKTNI o'zgartiradi
a = [1, 2]
f(a)
print(a) # [1, 2, 99] ✅ o'zgardi2. Yorliqni QAYTA BOG'LASH — faqat lokal:
def f(x):
x = [99] # YORLIQNI boshqa obyektga bog'ladi
a = [1, 2]
f(a)
print(a) # [1, 2] ← o'zgarmadiBoshida: f ichida x = [99] dan keyin:
a ──┐ a ──→ [1, 2]
├──→ [1, 2] x ──→ [99]
x ──┘Bu — Pythondagi eng muhim tushunchalardan biri.
O'zgarmas obyektlar bilan:
def f(x):
x = 99 # yagona imkoniyat — qayta bog'lash
a = 1
f(a)
print(a) # 1int o'zgarmas, shuning uchun x += 1 ham qayta bog'lash:
def f(x):
x += 1 # x = x + 1 → yangi obyekt
a = 1
f(a)
print(a) # 1 Lekin ro'yxat bilan += — joyida:
def f(x):
x += [99] # list.__iadd__ → JOYIDA
a = [1, 2]
f(a)
print(a) # [1, 2, 99] ⚠️ o'zgardi!Bu — += ning ikki xil xatti-harakati (6.2-dars).
Jadval:
| Amal | O'zgarmas (int, str, tuple) |
O'zgaruvchan (list, dict, set) |
|---|---|---|
x = yangi |
Lokal | Lokal |
x += y |
Lokal (yangi obyekt) | Tashqarida ham (joyida) |
x.metod() |
— (o'zgartiruvchi metod yo'q) | Tashqarida ham |
x[0] = y |
Xato | Tashqarida ham |
2.3. Xavfsiz naqshlar
1. Argumentni o'zgartirmang (afzal):
# ❌ Chaqiruvchini ajablantiradi
def qosh(r, x):
r.append(x)
return r
# ✅ Yangi obyekt
def qosh(r, x):
return [*r, x]2. Ataylab o'zgartirsangiz — None qaytaring:
def sarala_joyida(r) -> None:
"""Ro'yxatni JOYIDA saraladi."""
r.sort()Bu — Python kelishuvi (6.2-dars): list.sort(), list.append() — hammasi None qaytaradi.
3. Ichkarida nusxa oling:
def qayta_ishla(r):
r = list(r) # ⭐ lokal nusxa
r.sort()
return rSayoz nusxa — ichma-ich uchun yetarli emas (6.18-dars):
def qayta_ishla(d):
d = copy.deepcopy(d) # ichma-ich bo'lsa
...4. O'zgarmas turlarni afzal ko'ring:
def f(teglar: frozenset): ... # ✅ o'zgartirib bo'lmaydi
def f(nuqta: tuple): ... # ✅5. Hujjatda yozing:
def tozala(qatorlar: list[str]) -> None:
"""Ro'yxatni JOYIDA tozalaydi.
⚠️ Argument o'zgaradi!
"""2.4. Argumentlar soni va tartibi
Pozitsion argumentlar — tartib muhim:
def bol(a, b):
return a / b
bol(10, 2) # 5.0
bol(2, 10) # 0.2 ← boshqa natijaSoni mos kelishi kerak:
def f(a, b): ...
f(1) # ❌ TypeError: missing 1 required positional argument: 'b'
f(1, 2, 3) # ❌ TypeError: takes 2 positional arguments but 3 were givenNomli argumentlar — tartib erkin:
bol(a=10, b=2) # 5.0
bol(b=2, a=10) # 5.0 ← bir xilNomli argumentlar pozitsiondan KEYIN:
f(1, b=2) # ✅
f(a=1, 2) # ❌ SyntaxError: positional argument follows keyword argumentBir parametr ikki marta:
f(1, a=2) # ❌ TypeError: got multiple values for argument 'a'Bu — 4-darsda batafsil.
2.5. Ko'p parametrli funksiyalar
def yarat_hisobot(malumot, sarlavha, kenglik, balandlik, rang,
shrift, hajm, chegara, fon, ramka, ...):Muammolar:
- Tartibni eslash qiyin
- Chaqiruv o'qib bo'lmaydi:
f(x, 1, True, None, 3, "a") - Yangi parametr qo'shish — barcha chaqiruvni buzadi
- Test qilish qiyin
Yechimlar:
1. Nomli argumentlarni majburiy qilish (6-dars):
def yarat_hisobot(malumot, *, sarlavha, kenglik=80, rang="qora"):
...
yarat_hisobot(d, sarlavha="Hisobot", kenglik=100) # ✅ o'qiladi
yarat_hisobot(d, "Hisobot", 100) # ❌ TypeError2. Konfiguratsiya obyekti:
@dataclass
class HisobotSozlamalari:
sarlavha: str
kenglik: int = 80
balandlik: int = 24
rang: str = "qora"
def yarat_hisobot(malumot, sozlamalar: HisobotSozlamalari):
...3. Guruhlash:
def yarat_hisobot(malumot, matn: MatnSozlamalari, uslub: UslubSozlamalari):
...4. Funksiyani bo'lish:
Ko'p parametr — ko'pincha funksiya ko'p vazifa bajarayotganining belgisi.
Amaliy chegara: 3-4 pozitsion parametr. Undan ko'p bo'lsa — nomli argumentlar yoki obyekt.
2.6. Argumentlarni tekshirish
Turlarni tekshirish kerakmi?
def bol(a, b):
if not isinstance(a, (int, float)): # ⚠️ kerakmi?
raise TypeError(...)
return a / bPython falsafasi — EAFP (3.8-dars):
def bol(a, b):
return a / b # ✅ noto'g'ri tur bo'lsa TypeError o'zi chiqadiPython o'zi aniq xato beradi:
bol("a", 2) # TypeError: unsupported operand type(s)Qachon tekshirish kerak:
1. Xato xabari tushunarsiz bo'lsa:
def yosh_toifasi(yosh):
if yosh < 0:
raise ValueError(f"Yosh manfiy bo'lolmaydi: {yosh}")
...2. Xato kech chiqsa:
def qayta_ishla(malumot):
# 1000 qator kod...
natija = malumot["kalit"] # ❌ KeyError bu yerda
def qayta_ishla(malumot):
if "kalit" not in malumot: # ✅ darhol
raise ValueError("'kalit' maydoni majburiy")3. Tashqi kirish (API, foydalanuvchi):
def api_handler(sorov: dict):
yosh = sorov.get("yosh")
if not isinstance(yosh, int) or not 0 <= yosh <= 150:
raise ValueError("yosh 0-150 oralig'ida butun son bo'lishi kerak")Tur ko'rsatkichlari — hujjat, tekshiruv emas:
def f(x: int) -> str: ...
f("satr") # ✅ ishlaydi — Python tekshirmaydiTekshirish uchun mypy (statik) yoki pydantic (ish vaqti) kerak. 14-darsda.
2.7. Argumentlarni ochish
* — ketma-ketlikni pozitsion argumentlarga:
def f(a, b, c): ...
args = (1, 2, 3)
f(*args) # f(1, 2, 3)
r = [1, 2, 3]
f(*r) # ✅ ro'yxat ham
f(*range(3)) # ✅ har qanday iterable ** — lug'atni nomli argumentlarga:
kwargs = {"a": 1, "b": 2, "c": 3}
f(**kwargs) # f(a=1, b=2, c=3)Birga:
f(*[1, 2], **{"c": 3}) # f(1, 2, c=3)Kalitlar parametr nomlariga mos kelishi kerak:
f(**{"x": 1}) # ❌ TypeError: got an unexpected keyword argument 'x'Kalitlar satr bo'lishi kerak:
f(**{1: "a"}) # ❌ TypeError: keywords must be stringsAmaliy naqshlar:
# Konfiguratsiyani uzatish
sozlamalar = {"host": "x", "port": 5432}
ulan(**sozlamalar)
# Argumentlarni yo'naltirish
def orash(*args, **kwargs):
return asl_funksiya(*args, **kwargs)
# Qisman qo'llash
from functools import partial
bol_10ga = partial(bol, b=10)Bu — 5-darsda batafsil.
3. Tez ma'lumotnoma
Terminologiya
def f(a, b, c=3): a, b, c — PARAMETRLAR
f(1, 2) 1, 2 — ARGUMENTLAR
f(1, b=2) 1 — pozitsion, b=2 — nomliUzatish: obyektga havolani qiymat bo'yicha
def f(x):
x.append(1) ✅ TASHQARIDA ham ko'rinadi (obyekt o'zgardi)
x = [1] ❌ faqat lokal (yorliq qayta bog'landi)
x += [1] ⚠️ list — joyida, int/str/tuple — lokal
x[0] = 1 ✅ tashqarida (o'zgaruvchan bo'lsa)Xavfsiz naqshlar
def f(r): return [*r, x] ✅ yangi obyekt
def f(r) -> None: r.append(x) ✅ ataylab + None qaytaradi
def f(r): r = list(r); ... ✅ ichkarida nusxa
def f(t: tuple): ... ✅ o'zgarmas turArgumentlar tartibi
f(1, b=2) ✅ pozitsion → nomli
f(a=1, 2) ❌ SyntaxError
f(1, a=2) ❌ TypeError: multiple values
f(1) ❌ missing required positional argumentOchish
f(*args) ketma-ketlik → pozitsion
f(**kwargs) lug'at → nomli (kalitlar SATR va parametr nomiga mos)
f(*a, **k) birgaKo'p parametr
3-4 dan ko'p → nomli argumentlar (*), dataclass, yoki funksiyani bo'ling4. Batafsil misollar
Misol 1 — Uzatish mexanizmi
"""Argument qanday uzatiladi — to'liq namoyish."""
print("=== 1. ⭐ Asosiy farq ===")
def ozgartir(x):
"""Obyektni O'ZGARTIRADI."""
x.append(99)
def qayta_boglash(x):
"""Yorliqni QAYTA BOG'LAYDI."""
x = [99]
def ikkalasi(x):
"""Avval o'zgartiradi, keyin qayta bog'laydi."""
x.append(99)
x = [0]
x.append(1)
for f, izoh in [(ozgartir, "x.append(99)"),
(qayta_boglash, "x = [99]"),
(ikkalasi, "x.append(99); x = [0]; x.append(1)")]:
a = [1, 2]
f(a)
print(f" def f(x): {izoh:<38} → a = {a}")
print("""
⭐ x.append(99) — OBYEKTNI o'zgartiradi → tashqarida ko'rinadi
x = [99] — YORLIQNI qayta bog'laydi → faqat lokal
""")
print("\n=== 2. id() bilan kuzatish ===")
def kuzat(x, nom="x"):
print(f" {nom} kirishda: id={id(x)}, qiymat={x}")
x.append(99)
print(f" {nom} append'dan: id={id(x)}, qiymat={x}")
x = [0]
print(f" {nom} = [0] dan: id={id(x)}, qiymat={x} ⚠️ YANGI id")
a = [1, 2]
print(f" a tashqarida: id={id(a)}, qiymat={a}\n")
kuzat(a)
print(f"\n a chaqiruvdan keyin: id={id(a)}, qiymat={a}")
print("""
⭐ id o'zgargani — yorliq boshqa obyektga bog'langanini bildiradi.
Asl obyekt (a) o'z joyida qoldi.
""")
print("\n=== 3. O'zgarmas vs o'zgaruvchan ===")
SINOVLAR = [
("int", 1, lambda x: x + 1, "x = x + 1"),
("str", "abc", lambda x: x + "d", "x = x + 'd'"),
("tuple", (1, 2), lambda x: x + (3,), "x = x + (3,)"),
("list", [1, 2], None, "x.append(3)"),
("dict", {"a": 1}, None, "x['b'] = 2"),
("set", {1, 2}, None, "x.add(3)"),
]
def sinov_ozgarmas(x, amal):
x = amal(x)
def sinov_list(x):
x.append(3)
def sinov_dict(x):
x["b"] = 2
def sinov_set(x):
x.add(3)
print(f" {'Tur':<8} {'Amal':<18} {'Kirish':<14} {'Chiqish':<18} {'O`zgardimi'}")
print(" " + "─" * 74)
for tur, qiymat, amal, kod in SINOVLAR:
asl = str(qiymat)
if amal:
sinov_ozgarmas(qiymat, amal)
elif tur == "list":
sinov_list(qiymat)
elif tur == "dict":
sinov_dict(qiymat)
else:
sinov_set(qiymat)
ozgardi = "⚠️ HA" if str(qiymat) != asl else "✅ yo'q"
print(f" {tur:<8} {kod:<18} {asl:<14} {str(qiymat):<18} {ozgardi}")
print("\n=== 4. ⚠️ += tuzog'i ===")
def plus_teng(x):
x += [99]
def plus_teng_son(x):
x += 1
a = [1, 2]
plus_teng(a)
print(f" def f(x): x += [99]")
print(f" a = [1, 2] → {a} ⚠️ O'ZGARDI (list.__iadd__ joyida)")
b = 1
plus_teng_son(b)
print(f"\n def f(x): x += 1")
print(f" b = 1 → {b} ✅ o'zgarmadi (int yangi obyekt)")
print(f"\n Sabab — bytecode:")
import dis
print(f" Ro'yxat uchun:")
dis.dis("x += [1]")
print("""
⭐ x += y → x = x.__iadd__(y) (agar __iadd__ bor bo'lsa)
list.__iadd__ — JOYIDA o'zgartiradi va o'zini qaytaradi
int da __iadd__ yo'q → x = x.__add__(y) → yangi obyekt
""")
print("\n=== 5. Ichma-ich tuzilmalar ===")
def sayoz_nusxa_bilan(d):
"""⚠️ Sayoz nusxa — ichki obyektlar umumiy."""
d = dict(d)
d["yangi"] = 1
d["ichki"]["x"] = 99 # ⚠️ ASL o'zgaradi!
return d
def chuqur_nusxa_bilan(d):
"""✅ Chuqur nusxa."""
import copy
d = copy.deepcopy(d)
d["yangi"] = 1
d["ichki"]["x"] = 99
return d
for f, nom in [(sayoz_nusxa_bilan, "Sayoz"), (chuqur_nusxa_bilan, "Chuqur")]:
asl = {"a": 1, "ichki": {"x": 0}}
natija = f(asl)
belgi = "⚠️" if asl["ichki"]["x"] == 99 else "✅"
print(f" {nom} nusxa: asl = {asl} {belgi}")
print("""
⚠️ dict(d) va d.copy() — SAYOZ.
Ichma-ich bo'lsa copy.deepcopy() kerak (6.18-dars).
""")
print("\n=== 6. Xavfsiz naqshlar ===")
ASL = [3, 1, 2]
print(f" Asl ro'yxat: {ASL}\n")
def yomon(r, x):
"""❌ Chaqiruvchini ajablantiradi."""
r.append(x)
return r
def yaxshi_1(r, x):
"""✅ Yangi ro'yxat."""
return [*r, x]
def yaxshi_2(r, x) -> None:
"""✅ Ataylab joyida — None qaytaradi."""
r.append(x)
def yaxshi_3(r):
"""✅ Ichkarida nusxa."""
r = list(r)
r.sort()
return r
NAQSHLAR = [
("yomon(r, 9)", yomon, (9,)),
("yaxshi_1(r, 9)", yaxshi_1, (9,)),
("yaxshi_2(r, 9)", yaxshi_2, (9,)),
("yaxshi_3(r)", yaxshi_3, ()),
]
print(f" {'Chaqiruv':<20} {'Qaytardi':<16} {'r keyin':<16} {'Xavfsizmi'}")
print(" " + "─" * 68)
for nom, f, qoshimcha in NAQSHLAR:
r = ASL.copy()
natija = f(r, *qoshimcha)
xavfsiz = "✅" if r == ASL else "⚠️ o'zgardi"
print(f" {nom:<20} {str(natija):<16} {str(r):<16} {xavfsiz}")
print("""
⭐ Uch to'g'ri variant:
1. Yangi obyekt qaytarish — eng xavfsiz
2. Joyida + None qaytarish — aniq signal (6.2-dars kelishuvi)
3. Ichkarida nusxa olish — chaqiruvchi bilmaydi
""")Natijaning muhim qismi:
=== 1. ⭐ Asosiy farq ===
def f(x): x.append(99) → a = [1, 2, 99]
def f(x): x = [99] → a = [1, 2]
def f(x): x.append(99); x = [0]; x.append(1) → a = [1, 2, 99]
=== 3. O'zgarmas vs o'zgaruvchan ===
Tur Amal Kirish Chiqish O`zgardimi
──────────────────────────────────────────────────────────────────────────
int x = x + 1 1 1 ✅ yo'q
str x = x + 'd' abc abc ✅ yo'q
tuple x = x + (3,) (1, 2) (1, 2) ✅ yo'q
list x.append(3) [1, 2] [1, 2, 3] ⚠️ HA
dict x['b'] = 2 {'a': 1} {'a': 1, 'b': 2} ⚠️ HA
set x.add(3) {1, 2} {1, 2, 3} ⚠️ HANima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 2 — Argumentlar tartibi va ochish
"""Pozitsion, nomli argumentlar va ularni ochish."""
print("=== 1. Pozitsion vs nomli ===")
def bol(a, b):
"""a / b"""
return a / b
CHAQIRUVLAR = [
("bol(10, 2)", lambda: bol(10, 2)),
("bol(2, 10)", lambda: bol(2, 10)),
("bol(a=10, b=2)", lambda: bol(a=10, b=2)),
("bol(b=2, a=10)", lambda: bol(b=2, a=10)),
("bol(10, b=2)", lambda: bol(10, b=2)),
]
for kod, f in CHAQIRUVLAR:
print(f" {kod:<22} → {f()}")
print(f"\n ⭐ Pozitsion: TARTIB muhim")
print(f" Nomli: tartib ERKIN, lekin o'qilishi yaxshiroq")
print("\n=== 2. Xatolar ===")
XATOLAR = [
("bol(1)", "bol(1)"),
("bol(1, 2, 3)", "bol(1, 2, 3)"),
("bol(1, a=2)", "bol(1, a=2)"),
("bol(x=1, y=2)", "bol(x=1, y=2)"),
]
for nom, kod in XATOLAR:
try:
eval(kod)
natija = "✅"
except TypeError as x:
natija = f"❌ TypeError: {x}"
print(f" {nom:<20} {natija}")
print(f"\n bol(a=1, 2):")
try:
eval("bol(a=1, 2)")
except SyntaxError as x:
print(f" ❌ SyntaxError: {x.msg}")
print("""
⭐ Qoida: pozitsion argumentlar NOMLIDAN OLDIN
""")
print("\n=== 3. Nomli argumentlar o'qilishni yaxshilaydi ===")
def yarat_tugma(matn, kenglik, balandlik, faol, korinmas, ramka):
return (f"Tugma({matn!r}, {kenglik}×{balandlik}, "
f"faol={faol}, korinmas={korinmas}, ramka={ramka})")
print(f" ❌ Faqat pozitsion:")
print(f" yarat_tugma('OK', 100, 30, True, False, True)")
print(f" → nima True? nima False?\n")
print(f" ✅ Nomli argumentlar bilan:")
print(f" yarat_tugma('OK', kenglik=100, balandlik=30,")
print(f" faol=True, korinmas=False, ramka=True)")
print(f" → {yarat_tugma('OK', kenglik=100, balandlik=30, faol=True, korinmas=False, ramka=True)}")
print(f"\n ⚠️ Bool argumentlar ayniqsa muhim:")
print(f" f(x, True, False, True) ❌ o'qib bo'lmaydi")
print(f" f(x, faol=True, ...) ✅")
print("\n=== 4. ⭐ * bilan ochish ===")
def uchburchak(a, b, c):
return f"Uchburchak({a}, {b}, {c}), perimetr={a+b+c}"
MANBALAR = [
("tuple", (3, 4, 5)),
("list", [3, 4, 5]),
("range", range(3, 6)),
("set", {3, 4, 5}),
("str", "345"),
("generator", (x for x in [3, 4, 5])),
]
print(f" {'Manba':<14} {'f(*manba)'}")
print(" " + "─" * 56)
for nom, manba in MANBALAR:
try:
natija = uchburchak(*manba)
except TypeError as x:
natija = f"❌ {x}"
print(f" {nom:<14} {natija}")
print(f"\n ⚠️ Elementlar soni mos kelishi kerak:")
for manba in [(1, 2), (1, 2, 3, 4)]:
try:
uchburchak(*manba)
natija = "✅"
except TypeError as x:
natija = f"❌ {x}"
print(f" uchburchak(*{manba}) → {natija}")
print("\n=== 5. ⭐ ** bilan ochish ===")
def ulan(host, port, ssl=False, timeout=30):
return (f"Ulanish({host}:{port}, ssl={ssl}, timeout={timeout})")
SOZLAMALAR = [
("To'liq", {"host": "db.uz", "port": 5432, "ssl": True, "timeout": 60}),
("Qisman", {"host": "db.uz", "port": 5432}),
("Ortiqcha", {"host": "db.uz", "port": 5432, "yangi": 1}),
("Kam", {"host": "db.uz"}),
("Int kalit", {1: "x"}),
]
print(f" {'Sozlama':<12} {'Natija'}")
print(" " + "─" * 68)
for nom, s in SOZLAMALAR:
try:
natija = ulan(**s)
except TypeError as x:
natija = f"❌ TypeError: {x}"
print(f" {nom:<12} {natija}")
print("\n=== 6. Birgalikda ===")
print(f" ulan(*['db.uz', 5432], **{{'ssl': True}})")
print(f" → {ulan(*['db.uz', 5432], **{'ssl': True})}")
print(f"\n Konfiguratsiyani qatlamlash:")
STANDART = {"host": "localhost", "port": 5432, "timeout": 30}
FOYDALANUVCHI = {"host": "db.wisar.uz", "ssl": True}
print(f" STANDART = {STANDART}")
print(f" FOYDALANUVCHI = {FOYDALANUVCHI}")
print(f" ulan(**{{**STANDART, **FOYDALANUVCHI}})")
print(f" → {ulan(**{**STANDART, **FOYDALANUVCHI})}")
print("\n=== 7. Argumentlarni yo'naltirish ===")
def asl(a, b, c=3, *, d=4):
return f"asl(a={a}, b={b}, c={c}, d={d})"
def orash(*args, **kwargs):
"""Barcha argumentlarni o'tkazadi."""
print(f" args={args}, kwargs={kwargs}")
return asl(*args, **kwargs)
print(f" orash(1, 2):")
print(f" → {orash(1, 2)}")
print(f"\n orash(1, 2, c=30, d=40):")
print(f" → {orash(1, 2, c=30, d=40)}")
print(f"\n orash(1, b=2, d=40):")
print(f" → {orash(1, b=2, d=40)}")
print("""
⭐ *args, **kwargs — dekoratorlar va o'rash funksiyalarining asosi.
5-darsda batafsil.
""")
print("\n=== 8. Qisman qo'llash (partial) ===")
from functools import partial
def kuch(asos, daraja):
return asos ** daraja
kvadrat = partial(kuch, daraja=2)
kub = partial(kuch, daraja=3)
ikki_darajasi = partial(kuch, 2)
print(f" kuch(asos, daraja) dan:\n")
print(f" kvadrat = partial(kuch, daraja=2)")
print(f" kub = partial(kuch, daraja=3)")
print(f" ikki_darajasi = partial(kuch, 2)\n")
print(f" {'x':>4} {'kvadrat':>10} {'kub':>10} {'2^x':>10}")
print(" " + "─" * 38)
for x in [2, 3, 4, 5]:
print(f" {x:>4} {kvadrat(x):>10} {kub(x):>10} {ikki_darajasi(x):>10}")
print(f"\n partial ichida:")
print(f" kvadrat.func = {kvadrat.func.__name__}")
print(f" kvadrat.args = {kvadrat.args}")
print(f" kvadrat.keywords = {kvadrat.keywords}")Natijaning muhim qismi:
=== 2. Xatolar ===
bol(1) ❌ TypeError: bol() missing 1 required positional argument: 'b'
bol(1, 2, 3) ❌ TypeError: bol() takes 2 positional arguments but 3 were given
bol(1, a=2) ❌ TypeError: bol() got multiple values for argument 'a'
bol(x=1, y=2) ❌ TypeError: bol() got an unexpected keyword argument 'x'
bol(a=1, 2):
❌ SyntaxError: positional argument follows keyword argument
=== 4. ⭐ * bilan ochish ===
Manba f(*manba)
────────────────────────────────────────────────────────
tuple Uchburchak(3, 4, 5), perimetr=12
str Uchburchak(3, 4, 5), perimetr=345Nima ko'rsatdi: 2.4, 2.7-bo'limlar.
Misol 3 — Ko'p parametr va validatsiya
"""Ko'p parametrli funksiyalar muammosi va yechimlari."""
from dataclasses import dataclass, field
print("=== 1. ❌ Ko'p pozitsion parametr ===")
def hisobot_yomon(malumot, sarlavha, kenglik, balandlik,
ramka, sarlavha_korsatilsinmi, raqamlar,
ajratgich, tekislash, rang):
"""10 ta parametr — chaqiruv o'qib bo'lmaydi."""
return f"Hisobot({sarlavha!r}, {kenglik}×{balandlik}, ...)"
print(f" Chaqiruv:")
print(f" hisobot_yomon(d, 'Sotuvlar', 80, 24, True, True, False, '|', 'chap', 'qora')")
print(f" ↑ 80 nima? 24 nima? True lar nima?\n")
print(f" Muammolar:")
print(f" • Tartibni eslash kerak")
print(f" • Chaqiruv o'qib bo'lmaydi")
print(f" • Yangi parametr — barcha chaqiruvni buzadi")
print(f" • Bool argumentlar tushunarsiz")
print("\n=== 2. ✅ Yechim 1: nomli argumentlarni majburiy ===")
def hisobot_nomli(malumot, *, sarlavha, kenglik=80, balandlik=24,
ramka=True, raqamlar=False, ajratgich="|",
tekislash="chap", rang="qora"):
"""* dan keyingi hammasi FAQAT nomli (6-dars)."""
return (f"Hisobot({sarlavha!r}, {kenglik}×{balandlik}, "
f"ramka={ramka}, raqamlar={raqamlar})")
print(f" def f(malumot, *, sarlavha, kenglik=80, ...):\n")
print(f" ✅ Chaqiruv:")
natija = hisobot_nomli({}, sarlavha="Sotuvlar", kenglik=100, raqamlar=True)
print(f" hisobot_nomli(d, sarlavha='Sotuvlar', kenglik=100, raqamlar=True)")
print(f" → {natija}")
print(f"\n ❌ Pozitsion — endi mumkin emas:")
try:
hisobot_nomli({}, "Sotuvlar", 100)
except TypeError as x:
print(f" hisobot_nomli(d, 'Sotuvlar', 100) → TypeError: {x}")
print(f"\n ⭐ Afzalliklari:")
print(f" • Chaqiruv o'z-o'zini hujjatlaydi")
print(f" • Yangi parametr qo'shish xavfsiz")
print(f" • Tartib muhim emas")
print("\n=== 3. ✅ Yechim 2: konfiguratsiya obyekti ===")
@dataclass
class HisobotSozlamalari:
"""Barcha sozlamalar bitta obyektda."""
kenglik: int = 80
balandlik: int = 24
ramka: bool = True
raqamlar: bool = False
ajratgich: str = "|"
tekislash: str = "chap"
rang: str = "qora"
def __post_init__(self):
if self.tekislash not in {"chap", "markaz", "ong"}:
raise ValueError(f"Noto'g'ri tekislash: {self.tekislash}")
if not 20 <= self.kenglik <= 200:
raise ValueError(f"kenglik 20-200 oralig'ida: {self.kenglik}")
def hisobot_obyekt(malumot, sarlavha: str,
sozlamalar: HisobotSozlamalari | None = None):
s = sozlamalar or HisobotSozlamalari()
return f"Hisobot({sarlavha!r}, {s.kenglik}×{s.balandlik}, ramka={s.ramka})"
print(f" Sukut sozlamalar bilan:")
print(f" hisobot_obyekt(d, 'Sotuvlar')")
print(f" → {hisobot_obyekt({}, 'Sotuvlar')}")
print(f"\n Maxsus sozlamalar:")
s = HisobotSozlamalari(kenglik=120, raqamlar=True, tekislash="markaz")
print(f" s = HisobotSozlamalari(kenglik=120, raqamlar=True, tekislash='markaz')")
print(f" hisobot_obyekt(d, 'Sotuvlar', s)")
print(f" → {hisobot_obyekt({}, 'Sotuvlar', s)}")
print(f"\n ⭐ Validatsiya bepul keladi:")
for kwargs in [{"tekislash": "yuqori"}, {"kenglik": 5}]:
try:
HisobotSozlamalari(**kwargs)
natija = "✅"
except ValueError as x:
natija = f"❌ {x}"
print(f" HisobotSozlamalari(**{kwargs}) → {natija}")
print(f"\n ⭐ Sozlamalarni qayta ishlatish va o'zgartirish:")
from dataclasses import replace
s2 = replace(s, kenglik=200)
print(f" replace(s, kenglik=200) → kenglik={s2.kenglik}, "
f"tekislash={s2.tekislash}")
print("\n=== 4. Argumentlarni tekshirish ===")
print(f" ⭐ EAFP — Python o'zi aniq xato beradi:\n")
def bol_tekshiruvsiz(a, b):
return a / b
SINOVLAR = [(10, 2), (10, 0), ("a", 2), (10, "b"), (None, 2)]
for a, b in SINOVLAR:
try:
natija = f"✅ {bol_tekshiruvsiz(a, b)}"
except (TypeError, ZeroDivisionError) as x:
natija = f"❌ {type(x).__name__}: {x}"
print(f" bol({a!r}, {b!r}) → {natija}")
print(f"\n ✅ Qachon tekshirish KERAK:\n")
def yosh_toifasi(yosh: int) -> str:
"""Tekshiruvsiz xato tushunarsiz bo'lardi."""
if not isinstance(yosh, int) or isinstance(yosh, bool):
raise TypeError(f"yosh butun son bo'lishi kerak, {type(yosh).__name__} keldi")
if not 0 <= yosh <= 150:
raise ValueError(f"yosh 0-150 oralig'ida bo'lishi kerak, {yosh} keldi")
if yosh < 13:
return "bola"
if yosh < 20:
return "o'smir"
if yosh < 60:
return "kattalar"
return "keksa"
for yosh in [5, 15, 30, 70, -5, 200, "30", 30.5, True]:
try:
natija = f"✅ {yosh_toifasi(yosh)}"
except (TypeError, ValueError) as x:
natija = f"❌ {type(x).__name__}: {x}"
print(f" yosh_toifasi({yosh!r}) → {natija}")
print("""
⭐ Tekshirish kerak:
• Xato xabari tushunarsiz bo'lsa
• Xato ancha keyin chiqsa
• Tashqi kirish (API, foydalanuvchi, fayl)
• Mantiqiy cheklovlar (oraliq, format)
⚠️ Tekshirish KERAK EMAS:
• Python o'zi aniq xato beradigan holatlar
• Ichki yordamchi funksiyalar
""")
print("\n=== 5. Tur ko'rsatkichlari tekshirmaydi ===")
def kvadrat(x: int) -> int:
return x ** 2
SINOVLAR = [5, 2.5, "3", [1, 2], True]
print(f" def kvadrat(x: int) -> int:\n")
for x in SINOVLAR:
try:
natija = f"✅ {kvadrat(x)}"
except TypeError as e:
natija = f"❌ {e}"
print(f" kvadrat({x!r}) → {natija}")
print(f"""
⚠️ Python tur ko'rsatkichlarini TEKSHIRMAYDI.
'3' ** 2 xato beradi, lekin 2.5 va True ishlaydi.
⭐ Tekshirish uchun:
• mypy / pyright — statik (yozish paytida)
• pydantic — ish vaqtida
• beartype — dekorator bilan
14-darsda batafsil.
""")
print("\n=== 6. Parametrlar sonini kamaytirish ===")
print("""
Belgilar va yechimlar:
┌────────────────────────────┬───────────────────────────────────┐
│ Muammo │ Yechim │
├────────────────────────────┼───────────────────────────────────┤
│ 5+ parametr │ * bilan nomli qilish │
│ Bog'liq parametrlar guruhi │ dataclass │
│ Bool argumentlar ko'p │ Enum yoki alohida funksiyalar │
│ Ba'zi parametr kamdan-kam │ **kwargs + sukut lug'at │
│ Har xil ish rejimi │ Alohida funksiyalar │
│ Ko'p bog'liq holat │ Sinf │
└────────────────────────────┴───────────────────────────────────┘
""")
print(f" Bool argumentlar o'rniga Enum:\n")
from enum import Enum
class Tekislash(Enum):
CHAP = "chap"
MARKAZ = "markaz"
ONG = "ong"
def matn_chiqar(matn: str, kenglik: int, tekislash: Tekislash):
if tekislash is Tekislash.CHAP:
return matn.ljust(kenglik, ".")
if tekislash is Tekislash.ONG:
return matn.rjust(kenglik, ".")
return matn.center(kenglik, ".")
print(f" ❌ matn_chiqar('x', 20, True, False)")
print(f" ✅ matn_chiqar('x', 20, Tekislash.MARKAZ)\n")
for t in Tekislash:
print(f" {t.name:<8} {matn_chiqar('SALOM', 20, t)}")Natijaning muhim qismi:
=== 2. ✅ Yechim 1: nomli argumentlarni majburiy ===
❌ Pozitsion — endi mumkin emas:
hisobot_nomli(d, 'Sotuvlar', 100) → TypeError: hisobot_nomli() takes 1
positional argument but 3 were given
=== 4. Argumentlarni tekshirish ===
bol(10, 2) → ✅ 5.0
bol(10, 0) → ❌ ZeroDivisionError: division by zero
bol('a', 2) → ❌ TypeError: unsupported operand type(s) for /: 'str' and 'int'
yosh_toifasi(-5) → ❌ ValueError: yosh 0-150 oralig'ida bo'lishi kerak, -5 keldi
yosh_toifasi(True) → ❌ TypeError: yosh butun son bo'lishi kerak, bool keldi
=== 5. Tur ko'rsatkichlari tekshirmaydi ===
kvadrat(5) → ✅ 25
kvadrat(2.5) → ✅ 6.25
kvadrat('3') → ❌ unsupported operand type(s)
kvadrat(True) → ✅ 1Nima ko'rsatdi: 2.5, 2.6-bo'limlar.
Misol 4 — Amaliy: ma'lumot qayta ishlash quvuri
"""Argumentlarni to'g'ri boshqarish — real vazifa."""
import copy
from dataclasses import dataclass, field, replace
from typing import Callable
print("=== Yozuvlar qayta ishlash tizimi ===\n")
XOM_YOZUVLAR = [
{"id": 1, "ism": " Aziz ", "yosh": "30", "bolim": "IT", "maosh": 7_000_000},
{"id": 2, "ism": "bobur", "yosh": 25, "bolim": "hr", "maosh": "5000000"},
{"id": 3, "ism": "AZIZA", "yosh": "notogri", "bolim": "IT", "maosh": 8_000_000},
{"id": 4, "ism": "", "yosh": 28, "bolim": "Moliya", "maosh": 6_000_000},
{"id": 5, "ism": "Eldor", "yosh": 42, "bolim": "IT", "maosh": None},
]
print("=== 1. ❌ Argumentni buzuvchi funksiya ===")
def tozala_yomon(yozuvlar: list[dict]) -> list[dict]:
"""⚠️ Asl ro'yxatni VA ichidagi lug'atlarni o'zgartiradi."""
for y in yozuvlar:
if isinstance(y.get("ism"), str):
y["ism"] = y["ism"].strip().title()
return yozuvlar
asl_nusxa = copy.deepcopy(XOM_YOZUVLAR)
natija = tozala_yomon(XOM_YOZUVLAR)
print(f" Chaqiruvdan keyin:")
print(f" XOM_YOZUVLAR[0]['ism'] = {XOM_YOZUVLAR[0]['ism']!r} ⚠️ O'ZGARDI")
print(f" natija is XOM_YOZUVLAR = {natija is XOM_YOZUVLAR} ⚠️")
XOM_YOZUVLAR[:] = asl_nusxa # tiklash
print("\n=== 2. ✅ Xavfsiz funksiyalar ===")
def ismni_tozala(yozuv: dict) -> dict:
"""Yangi lug'at qaytaradi."""
ism = yozuv.get("ism", "")
if not isinstance(ism, str):
return {**yozuv, "ism": ""}
return {**yozuv, "ism": ism.strip().title()}
def songa_aylantir(yozuv: dict, maydon: str, sukut=None) -> dict:
"""Maydonni int ga aylantiradi."""
qiymat = yozuv.get(maydon)
if isinstance(qiymat, int) and not isinstance(qiymat, bool):
return dict(yozuv)
if isinstance(qiymat, str) and qiymat.lstrip("-").isdigit():
return {**yozuv, maydon: int(qiymat)}
return {**yozuv, maydon: sukut}
def bolimni_normalla(yozuv: dict) -> dict:
"""Bo'lim nomini standartlashtiradi."""
NORMAL = {"it": "IT", "hr": "HR", "moliya": "Moliya"}
bolim = str(yozuv.get("bolim", "")).lower()
return {**yozuv, "bolim": NORMAL.get(bolim, yozuv.get("bolim", ""))}
def togrimi(yozuv: dict) -> bool:
"""Yozuv to'liq va to'g'rimi."""
return bool(
yozuv.get("ism")
and isinstance(yozuv.get("yosh"), int)
and isinstance(yozuv.get("maosh"), int)
and yozuv.get("bolim")
)
print(f" Bosqichma-bosqich (birinchi yozuv):\n")
y = XOM_YOZUVLAR[0]
print(f" Asl: {y}")
y1 = ismni_tozala(y)
print(f" ismni_tozala: {y1}")
y2 = songa_aylantir(y1, "yosh")
print(f" songa_aylantir: {y2}")
y3 = bolimni_normalla(y2)
print(f" bolimni_normalla: {y3}")
print(f"\n XOM_YOZUVLAR[0] o'zgarmadi: {XOM_YOZUVLAR[0]['ism']!r} ✅")
print("\n=== 3. Quvur ===")
def quvur(yozuvlar: list[dict], *bosqichlar: Callable) -> list[dict]:
"""Har bosqichni ketma-ket qo'llaydi. Asl o'zgarmaydi."""
natija = yozuvlar
for bosqich in bosqichlar:
natija = [bosqich(y) for y in natija]
return natija
def yosh_songa(y):
return songa_aylantir(y, "yosh")
def maosh_songa(y):
return songa_aylantir(y, "maosh")
qayta_ishlangan = quvur(
XOM_YOZUVLAR,
ismni_tozala,
yosh_songa,
maosh_songa,
bolimni_normalla,
)
print(f" quvur(XOM_YOZUVLAR, ismni_tozala, yosh_songa, maosh_songa, bolimni_normalla)\n")
print(f" {'ID':>3} {'Ism':<10} {'Yosh':>6} {'Bo`lim':<8} {'Maosh':>12} {'To`g`ri'}")
print(" " + "─" * 56)
for y in qayta_ishlangan:
yosh = y["yosh"] if y["yosh"] is not None else "—"
maosh = f"{y['maosh']:,}" if y["maosh"] is not None else "—"
belgi = "✅" if togrimi(y) else "❌"
print(f" {y['id']:>3} {y['ism'] or '(bo`sh)':<10} {str(yosh):>6} "
f"{y['bolim']:<8} {maosh:>12} {belgi:>6}")
print(f"\n Asl ma'lumot o'zgarmadi:")
print(f" XOM_YOZUVLAR[0]['ism'] = {XOM_YOZUVLAR[0]['ism']!r} ✅")
print("\n=== 4. Ko'p parametrli funksiyani qayta loyihalash ===")
print(f" ❌ Asl:")
print(f"""
def hisobot(yozuvlar, sarlavha, guruh_maydoni, saralash_maydoni,
kamayish, chegara, jami_korsatilsinmi, foizlar,
kenglik, ajratgich):
""")
@dataclass(frozen=True)
class HisobotSozlamalari:
"""✅ Barcha sozlamalar bitta o'zgarmas obyektda."""
sarlavha: str = "HISOBOT"
guruh_maydoni: str = "bolim"
saralash_maydoni: str = "maosh"
kamayish: bool = True
chegara: int | None = None
jami: bool = True
foizlar: bool = False
kenglik: int = 56
def __post_init__(self):
if self.chegara is not None and self.chegara < 1:
raise ValueError(f"chegara musbat bo'lishi kerak: {self.chegara}")
if not 20 <= self.kenglik <= 200:
raise ValueError(f"kenglik 20-200: {self.kenglik}")
def hisobot(yozuvlar: list[dict],
sozlamalar: HisobotSozlamalari | None = None) -> str:
"""✅ Ikkita parametr, biri ixtiyoriy."""
s = sozlamalar or HisobotSozlamalari()
toza = [y for y in yozuvlar if togrimi(y)]
if not toza:
return "Ma'lumot yo'q"
guruhlar: dict[str, list[dict]] = {}
for y in toza:
guruhlar.setdefault(y[s.guruh_maydoni], []).append(y)
qatorlar = [f"┌─ {s.sarlavha}", "│"]
jami_hammasi = sum(y[s.saralash_maydoni] for y in toza)
tartib = sorted(
guruhlar.items(),
key=lambda kv: sum(y[s.saralash_maydoni] for y in kv[1]),
reverse=s.kamayish,
)
if s.chegara:
tartib = tartib[:s.chegara]
for guruh, xodimlar in tartib:
guruh_jami = sum(y[s.saralash_maydoni] for y in xodimlar)
qator = f"│ {guruh:<10} {len(xodimlar):>2} xodim {guruh_jami:>14,}"
if s.foizlar:
qator += f" ({guruh_jami / jami_hammasi:>5.1%})"
qatorlar.append(qator)
if s.jami:
qatorlar.append("│")
qatorlar.append(f"│ {'JAMI':<10} {len(toza):>2} xodim {jami_hammasi:>14,}")
qatorlar.append("└─")
return "\n".join(" " + q for q in qatorlar)
print(f" ✅ Yangi:")
print(f" def hisobot(yozuvlar, sozlamalar=None):\n")
print(f" Sukut sozlamalar bilan:")
print(hisobot(qayta_ishlangan))
print(f"\n Maxsus sozlamalar bilan:")
s = HisobotSozlamalari(sarlavha="BO'LIMLAR BO'YICHA", foizlar=True, chegara=2)
print(hisobot(qayta_ishlangan, s))
print(f"\n Sozlamalarni o'zgartirish (replace):")
s2 = replace(s, sarlavha="TO'LIQ", chegara=None, kamayish=False)
print(hisobot(qayta_ishlangan, s2))
print("\n\n=== 5. Validatsiya ===")
NOTOGRI = [
{"chegara": 0},
{"chegara": -5},
{"kenglik": 5},
{"kenglik": 500},
]
print(f" HisobotSozlamalari validatsiyasi:\n")
for kwargs in NOTOGRI:
try:
HisobotSozlamalari(**kwargs)
natija = "✅"
except ValueError as x:
natija = f"❌ {x}"
print(f" {str(kwargs):<24} {natija}")
print("\n=== 6. Xulosa: uchta qoida ===")
print("""
1️⃣ Argumentni o'zgartirmang
❌ def f(r): r.append(x); return r
✅ def f(r): return [*r, x]
✅ def f(r) -> None: r.append(x) (ataylab, None qaytaradi)
2️⃣ 4+ parametr bo'lsa — nomli yoki obyekt
❌ def f(a, b, c, d, e, f, g): ...
✅ def f(a, *, b=1, c=2, ...): ...
✅ def f(a, sozlamalar: Sozlamalar): ...
3️⃣ Tekshirish — faqat kerak bo'lganda
❌ Har argument uchun isinstance
✅ Tashqi kirish, tushunarsiz xato, kech chiqadigan xato
✅ Tur ko'rsatkichlari + mypy
""")Natijaning muhim qismi:
=== 3. Quvur ===
ID Ism Yosh Bo`lim Maosh To`g`ri
────────────────────────────────────────────────────────
1 Aziz 30 IT 7,000,000 ✅
2 Bobur 25 HR 5,000,000 ✅
3 Aziza — IT 8,000,000 ❌
4 (bo`sh) 28 Moliya 6,000,000 ❌
5 Eldor 42 IT — ❌
Asl ma'lumot o'zgarmadi:
XOM_YOZUVLAR[0]['ism'] = ' Aziz ' ✅
=== 4. Ko'p parametrli funksiyani qayta loyihalash ===
Maxsus sozlamalar bilan:
┌─ BO'LIMLAR BO'YICHA
│
│ IT 1 xodim 7,000,000 (58.3%)
│ HR 1 xodim 5,000,000 (41.7%)
│
│ JAMI 2 xodim 12,000,000
└─Nima ko'rsatdi: 2.3, 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Python qiymat bo'yicha uzatadi" | Obyektga havolani qiymat bo'yicha |
| "Python havola bo'yicha uzatadi" | x = yangi tashqarida ko'rinmaydi |
| "O'zgaruvchan argument har doim o'zgaradi" | Faqat obyekt o'zgartirilsa, qayta bog'lansa yo'q |
"x += y har doim bir xil" |
list — joyida, int — yangi obyekt |
"d.copy() argumentni himoyalaydi" |
Sayoz — ichma-ich uchun yetarli emas |
| "Tur ko'rsatkichlari tekshiradi" | Faqat hujjat. mypy kerak |
| "Har argumentni tekshirish kerak" | EAFP — Python o'zi aniq xato beradi |
| "Ko'p parametr — normal" | 4+ bo'lsa qayta loyihalang |
| "Nomli argument sekinroq" | Farq sezilmas darajada |
6. Keng tarqalgan xatolar va yechimlari
1. Argumentni jimgina o'zgartirish
def qosh(r, x):
r.append(x); return r # ⚠️ chaqiruvchi ajablanadi
def qosh(r, x):
return [*r, x] # ✅2. Sayoz nusxaga ishonish
def f(d):
d = dict(d) # ⚠️ ichma-ich bo'lsa yetarli emas
d["ichki"]["x"] = 1
def f(d):
d = copy.deepcopy(d) # ✅3. Nomli argument pozitsiondan oldin
f(a=1, 2) # ❌ SyntaxError
f(1, b=2) # ✅4. Bir parametrga ikki qiymat
f(1, a=2) # ❌ multiple values for argument 'a'5. Ko'p pozitsion parametr
def f(a, b, c, d, e, g): ... # ❌ chaqiruv o'qib bo'lmaydi
def f(a, *, b, c, d=1): ... # ✅6. Bool argumentlar
f(x, True, False, True) # ❌ nima nima?
f(x, faol=True, korinmas=False) # ✅7. Tur ko'rsatkichlariga ishonish
def f(x: int): return x * 2
f("a") # ⚠️ "aa" — xato yo'q!8. ** da noto'g'ri kalitlar
f(**{"noma'lum": 1}) # ❌ unexpected keyword argument
f(**{1: "a"}) # ❌ keywords must be strings7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 7.3-dars: sukut qiymatlar va o'zgaruvchan sukut tuzog'i
- 7.4-dars: nomli argumentlar batafsil
- 7.5-dars:
*args,**kwargs - 7.6-dars: faqat pozitsion va faqat nomli
- 6.1, 6.18-darslar (o'tilgan): yorliq modeli, nusxa olish
- 6.2-dars (o'tilgan):
Noneqaytaruvchi metodlar kelishuvi - 8-qism: metodlar va
self - 9-qism:
TypeError,ValueError
8. Eng yaxshi amaliyotlar
Argumentni o'zgartirmang. Yangi obyekt qaytaring yoki ichkarida nusxa oling.
Ataylab o'zgartirsangiz —
Noneqaytaring va hujjatda yozing.4+ parametr — nomli argumentlar yoki
dataclass.Bool argumentlarni doim nomli uzating.
f(x, faol=True).Tekshirishni faqat kerak bo'lganda. EAFP — Python o'zi xato beradi.
Tashqi kirishni doim tekshiring. API, foydalanuvchi, fayl.
Ichma-ich tuzilma uchun
deepcopy. Sayoz nusxa yetarli emas.Tur ko'rsatkichlari +
mypy. Hujjat va statik tekshiruv birga.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
def f1(x): x = 99
def f2(x): x.append(99)
def f3(x): x += [99]
def f4(x): x += 1
def f5(x): x[0] = 99
def f6(x): x = x + [99]
1. a = 1; f1(a); print(a)
2. a = [1]; f2(a); print(a)
3. a = [1]; f3(a); print(a)
4. a = 1; f4(a); print(a)
5. a = [1]; f5(a); print(a)
6. a = [1]; f6(a); print(a)
7. a = (1,); f3(a); print(a)
8. a = {"x": 1}; f5(a); print(a)
9. def g(a, b): return a - b
print(g(b=1, a=10))
10. def h(*args): return args
print(h(*[1,2], *(3,)))
11. def k(a, b=2): return a, b
print(k(**{"a": 1, "b": 3}))
12. def m(a): return a
print(m(*[1]))Javoblar
1— qayta bog'lash lokal[1, 99]— obyekt o'zgardi[1, 99]—list.__iadd__joyida1—intyangi obyekt[99]— element almashtirildi[1]—x + [99]yangi obyekt-
TypeError— tuple o'zgarmas {'x': 1, 0: 99}— lug'atdax[0] = 99yangi0kalitini yaratadi (ro'yxatdan farqli)9(1, 2, 3)(1, 3)1
Vazifa 2: Xatolarni tuzating
1. def qosh(r, x): r.append(x); return r
2. def f(d): d = dict(d); d["a"]["b"] = 1
3. f(a=1, 2)
4. def f(a, b, c, d, e, g, h): ...
5. yarat_tugma("OK", 100, 30, True, False)
6. def f(x: int) -> int: return x * 2
# foydalanuvchi kiritgan qiymat uzatiladi
7. def sarala(r): r.sort(); return r
8. f(**{"noma'lum": 1})Javoblar
1. def qosh(r, x): return [*r, x]
2. d = copy.deepcopy(d)
3. f(1, a=2) yoki f(a=1, b=2)
4. def f(a, *, b, c, d=1, e=2, g=3, h=4): ... yoki dataclass
5. yarat_tugma("OK", kenglik=100, balandlik=30, faol=True, korinmas=False)
6. Tekshiring: if not isinstance(x, int): raise TypeError(...)
7. def sarala(r): return sorted(r) # yoki -> None qiling
8. Parametr nomlarini tekshiringVazifa 3: Xavfsiz kutubxona
Funksiyalar yozing (hech biri argumentni o'zgartirmasin):
qosh(r, x),ochir(r, x),almashtir(r, i, x)birlashtir(*royxatlar),oraliq(r, a, b)guruhla(r, kalit_f)— lug'at qaytarsinyangila(d, **ozgarishlar)— chuqur birlashtirish- Har biri uchun test: asl o'zgarmaganini tekshiring
-> Noneversiyalarini ham yozing (joyida)
Vazifa 4: Uzatish tahlilchisi
Dastur yozing:
- Funksiya argumentni o'zgartiradimi — aniqlasin
id()vadeepcopybilan solishtirish orqali- Qaysi maydonlar o'zgarganini ko'rsatsin
- Dekorator sifatida:
@ozgartirmasligini_tekshir - Ogohlantirish yoki xato bersin
Vazifa 5: Konfiguratsiya tizimi
Ko'p parametrli funksiyani qayta loyihalang:
dataclass(frozen=True)sozlamalar__post_init__da validatsiyareplace()bilan o'zgartirish- Fayl/muhitdan yuklash
- Sukut qiymatlar bilan birlashtirish
to_dict()/from_dict()
Vazifa 6: Validatsiya dekoratori
Yozing:
@tekshir(yosh=(int, 0, 150), ism=(str, 1, 50))
def yarat_foydalanuvchi(ism, yosh): ...- Tur tekshiruvi
- Oraliq/uzunlik tekshiruvi
- Aniq xato xabarlari
- Tur ko'rsatkichlaridan avtomatik olish
pydanticbilan solishtirish
Vazifa 7: O'ylash
Nega Python "qiymat bo'yicha" yoki "havola bo'yicha" emas, balki uchinchi modelni tanladi?
Javob
Chunki Pythonda "o'zgaruvchi" — quti emas, yorliq.
Boshqa tillarda:
C — qiymat bo'yicha:
void f(int x) { x = 99; }
int a = 1;
f(a); // a == 1 — x NUSXAO'zgaruvchi — xotiradagi quti. Uzatishda quti nusxalanadi.
C++ — havola bo'yicha ham mumkin:
void f(int& x) { x = 99; }
int a = 1;
f(a); // a == 99 — x aslining ALIASIPythonda quti yo'q:
a = 1Bu — "a qutisiga 1 solindi" emas, balki "1 obyektiga a yorlig'i osildi" (6.1-dars).
a ──→ [1]Uzatishda nima bo'ladi:
def f(x): ...
f(a)x — shu obyektga yangi yorliq:
a ──┐
├──→ [1]
x ──┘Bu:
- "qiymat bo'yicha" emas — obyekt nusxalanmadi
- "havola bo'yicha" emas —
x = 99ani o'zgartirmaydi (xaning aliasi emas)
Bu model nima deyiladi:
- Call by object reference (Python hujjatlarida)
- Call by sharing (Barbara Liskov, 1974)
- Call by object (CLU tili)
Bir xil model: Java (obyektlar uchun), Ruby, JavaScript (obyektlar uchun), Smalltalk.
Nega bu tanlandi:
1. Model izchil.
Pythonda hamma narsa obyekt — int, str, funksiya, sinf, modul. Va o'zgaruvchi har doim yorliq. Funksiya chaqiruvi — shunchaki yangi yorliq bog'lash:
x = a # yorliq bog'lash
f(a) # parametr uchun yorliq bog'lash — BIR XIL narsaBir qoida — barcha holat uchun.
2. Nusxalash qimmat bo'lardi.
Agar Python "qiymat bo'yicha" uzatsa:
katta = list(range(10_000_000))
f(katta) # ⚠️ 400 MB nusxa!Har chaqiruvda nusxa — mumkin emas.
3. "Havola bo'yicha" xavfli bo'lardi.
def f(x):
x = [99] # agar havola bo'yicha bo'lsa:
a = [1]
f(a)
print(a) # [99]? ⚠️ juda chalkashFunksiya chaqiruvchining o'zgaruvchisini qayta bog'lay olardi. Bu — kodni kuzatishni juda qiyinlashtiradi.
4. Amalda kerakli ikkala xatti-harakat ham bor:
def f(x): x.append(1) # "havola bo'yicha" kabi
def f(x): x = [1] # "qiymat bo'yicha" kabiFarq — obyektning o'zgaruvchanligida, uzatish mexanizmida emas.
Chalkashlik manbai:
Ko'pchilik "o'zgaruvchan obyekt havola bo'yicha, o'zgarmas qiymat bo'yicha uzatiladi" deb o'ylaydi. Bu — noto'g'ri:
def f(x):
x = [99]
a = [1] # O'ZGARUVCHAN
f(a)
print(a) # [1] — "havola bo'yicha" bo'lsa [99] bo'lardiUzatish har doim bir xil. Farq — funksiya ichida nima qilinishida:
- Obyektni o'zgartirish (
x.append,x[0] =) → tashqarida ko'rinadi - Yorliqni qayta bog'lash (
x =) → lokal
Amaliy natija:
Bitta savol yetarli: "obyekt o'zgartirildimi yoki yorliq qayta bog'landimi?"
x.metod() obyekt → tashqarida ko'rinadi
x[i] = y obyekt → tashqarida
x += y list: obyekt, int: yorliq
x = y yorliq → lokalXulosa: Python "uchinchi model" ni ataylab tanlamagan — u yorliq modelining tabiiy oqibati. Agar o'zgaruvchi yorliq bo'lsa, funksiya parametri ham yorliq bo'lishi kerak. Boshqa variant izchil bo'lmasdi.
Nimani mustahkamlaydi: 2.2, 2.3-bo'limlar.
Xulosa
Bu darsda argument uzatish mexanizmini o'rgandik.
Eng muhim uch fikr:
Python obyektga havolani qiymat bo'yicha uzatadi. Parametr — asl obyektga yangi yorliq. Shuning uchun
x.append(1)tashqarida ko'rinadi,x = [1]esa yo'q. Farq — uzatish mexanizmida emas, funksiya ichida nima qilinishida.Argumentni o'zgartirmang. Yangi obyekt qaytaring (
return [*r, x]), yoki ataylab joyida o'zgartiribNoneqaytaring, yoki ichkarida nusxa oling. Ichma-ich tuzilma uchundeepcopykerak.4+ parametr — qayta loyihalang.
*bilan nomli argumentlarni majburiy qiling,dataclasssozlamalar obyekti yarating, yoki funksiyani bo'ling. Bool argumentlarni doim nom bilan uzating.
Keyingi darsda sukut qiymatlarni va Pythonning eng mashhur tuzog'ini — o'zgaruvchan sukut argumentni — ko'ramiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!