Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. *args — pozitsion argumentlarni yig'ish
- 2.2. **kwargs — nomli argumentlarni yig'ish
- 2.3. Yig'ish vs ochish
- 2.4. To'liq imzo shakli
- 2.5. Argumentlarni yo'naltirish (forwarding)
- 2.6. Amaliy naqshlar
- 2.7. Kamchiliklar va cheklovlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Asoslar
- Misol 2 — Yo'naltirish va dekoratorlar
- Misol 3 — Amaliy naqshlar
- Misol 4 — Amaliy: plagin tizimi
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
7.5-dars: *args va **kwargs
7-QISM — FUNKSIYALAR · 5-dars
1. Kirish va motivatsiya
Ba'zi funksiyalar oldindan noma'lum sondagi argument qabul qiladi:
print("a")
print("a", "b", "c")
print(*range(100))
max(1, 2)
max(1, 2, 3, 4, 5)
dict(a=1)
dict(a=1, b=2, c=3)Buni qanday yozish mumkin?
def yigindi(*sonlar):
return sum(sonlar)
yigindi() # 0
yigindi(1) # 1
yigindi(1, 2, 3, 4, 5) # 15def sozla(**sozlamalar):
return sozlamalar
sozla(host="x", port=5432) # {'host': 'x', 'port': 5432}Lekin bu ikki belgi chalkash — ular ikki xil kontekstda ishlatiladi:
def f(*args): ... # ta'rifda — YIG'ADI
f(*args) # chaqiruvda — OCHADIVa nozikliklar bor:
def f(*args, **kwargs): ...
f(1, 2, a=3) # args=(1,2), kwargs={'a':3}
def g(a, *args, b): ...
g(1, 2, 3) # ❌ b majburiy va faqat nomliBu darsda:
*args— cheksiz pozitsion argumentlar**kwargs— cheksiz nomli argumentlar- Yig'ish vs ochish — bir belgi, ikki ma'no
- Tartib qoidalari va to'liq imzo shakli
- Argumentlarni yo'naltirish (forwarding)
- Dekoratorlar va
functools.wraps
2. Nazariya — chuqur tushuntirish
2.1. *args — pozitsion argumentlarni yig'ish
def f(*args):
print(type(args), args)
f() # <class 'tuple'> ()
f(1) # <class 'tuple'> (1,)
f(1, 2, 3) # <class 'tuple'> (1, 2, 3) args — har doim tuple (hatto bo'sh bo'lsa ham).
Oddiy parametrlar bilan:
def f(a, b, *args):
return a, b, args
f(1, 2) # (1, 2, ())
f(1, 2, 3, 4) # (1, 2, (3, 4))
f(1) # ❌ TypeError — b majburiy *args dan keyin faqat nomli parametrlar:
def f(*args, b): # b — FAQAT nomli
return args, b
f(1, 2, b=3) # ((1, 2), 3)
f(1, 2, 3) # ❌ TypeError: missing 1 required keyword-only argument: 'b'Nom args — kelishuv, majburiyat emas:
def f(*sonlar): ... # ✅ aniqroq
def f(*qiymatlar): ... # ✅
def f(*args): ... # ✅ umumiy holat uchun Faqat * — argumentlarni yig'masdan chegara qo'yish (6-dars):
def f(a, *, b): # b faqat nomli, qolgan pozitsion QABUL QILINMAYDI
...
f(1, b=2) # ✅
f(1, 2) # ❌ TypeError2.2. **kwargs — nomli argumentlarni yig'ish
def f(**kwargs):
print(type(kwargs), kwargs)
f() # <class 'dict'> {}
f(a=1) # <class 'dict'> {'a': 1}
f(a=1, b=2) # <class 'dict'> {'a': 1, 'b': 2} kwargs — har doim dict, va tartib saqlanadi (PEP 468, Python 3.6+):
def f(**kwargs):
return list(kwargs)
f(z=1, a=2, m=3) # ['z', 'a', 'm'] ← yozilish tartibidaOddiy parametrlar bilan:
def f(a, **kwargs):
return a, kwargs
f(1, b=2, c=3) # (1, {'b': 2, 'c': 3})
f(a=1, b=2) # (1, {'b': 2}) **kwargs — doim OXIRIDA:
def f(**kwargs, a): ... # ❌ SyntaxError
def f(a, **kwargs): ... # ✅ Faqat bitta **:
def f(**a, **b): ... # ❌ SyntaxError2.3. Yig'ish vs ochish
Bir xil belgi, ikki qarama-qarshi ma'no:
| Kontekst | * |
** |
|---|---|---|
| Ta'rifda | Pozitsionlarni yig'adi → tuple |
Nomlilarni yig'adi → dict |
| Chaqiruvda | Iterable'ni ochadi → pozitsion | Lug'atni ochadi → nomli |
def f(*args): # YIG'ISH
print(args)
r = [1, 2, 3]
f(*r) # OCHISH → f(1, 2, 3) → (1, 2, 3)
f(r) # OCHISH YO'Q → ([1, 2, 3],)Chaqiruvda ochish (7.2-dars):
def g(a, b, c): ...
g(*[1, 2, 3]) # g(1, 2, 3)
g(**{"a": 1, "b": 2, "c": 3})
g(*[1, 2], **{"c": 3})Boshqa joylarda ochish (PEP 448, Python 3.5+):
[*a, *b] # ro'yxatlarni birlashtirish
(*a, *b) # tuple
{*a, *b} # to'plam
{**d1, **d2} # lug'at
[1, *r, 2] # o'rtaga qo'yish
{"a": 1, **d, "b": 2}Ochishda ochish:
def f(*args):
return args
f(*[1, 2], *[3, 4]) # (1, 2, 3, 4) — bir necha marta ochish
f(*range(3), *"ab") # (0, 1, 2, 'a', 'b')2.4. To'liq imzo shakli
def f(a, b, /, c, d, *args, e, f=1, **kwargs):
# ───── ──── ───── ────── ────────
# faqat ikka qolgan faqat qolgan
# pozits. lasi pozits. nomli nomli
...Tartib qat'iy:
- Faqat pozitsion (
/dan oldin) - Pozitsion yoki nomli
*argsyoki*- Faqat nomli
**kwargs
Buzilsa — SyntaxError:
def f(**kwargs, a): ... # ❌
def f(*args, a, *args2): ... # ❌
def f(a, /, b, /, c): ... # ❌ bitta /Namunalar:
def f(*args): ... # faqat pozitsion (cheksiz)
def f(**kwargs): ... # faqat nomli (cheksiz)
def f(*args, **kwargs): ... # ⭐ hamma narsa
def f(a, *args): ... # kamida bitta
def f(a, *, b): ... # b faqat nomli
def f(a, /, b): ... # a faqat pozitsion
def f(a, /, *, b): ... # ⭐ eng qat'iyinspect bilan:
import inspect
inspect.signature(f)
# (a, b, /, c, d, *args, e, f=1, **kwargs)2.5. Argumentlarni yo'naltirish (forwarding)
Eng muhim qo'llanish:
def orash(*args, **kwargs):
"""Barcha argumentlarni asl funksiyaga o'tkazadi."""
print(f"chaqirilmoqda: args={args}, kwargs={kwargs}")
return asl(*args, **kwargs)Dekorator asosi:
from functools import wraps
def jurnal(f):
@wraps(f)
def ichki(*args, **kwargs):
print(f"{f.__name__} chaqirildi")
return f(*args, **kwargs)
return ichki @wraps shart — aks holda metadata yo'qoladi:
def jurnal_yomon(f):
def ichki(*args, **kwargs):
return f(*args, **kwargs)
return ichki
@jurnal_yomon
def salom(): ...
salom.__name__ # 'ichki' ⚠️
salom.__doc__ # None ⚠️@wraps __name__, __doc__, __module__, __qualname__, __dict__, __wrapped__ ni ko'chiradi.
Meros bilan:
class Asos:
def __init__(self, a, b): ...
class Voris(Asos):
def __init__(self, c, *args, **kwargs):
super().__init__(*args, **kwargs) # ⭐ ota-onaga yo'naltirish
self.c = cQisman o'zgartirish:
def kengaytir(f):
@wraps(f)
def ichki(*args, **kwargs):
kwargs.setdefault("timeout", 30) # sukut qo'shish
return f(*args, **kwargs)
return ichkiYo'naltirish tur ko'rsatkichlarini yo'qotadi:
@jurnal
def qosh(a: int, b: int) -> int: ...
# IDE endi qosh(a, b) imzosini ko'rmaydi — (*args, **kwargs) ko'radiYechim — ParamSpec (Python 3.10+):
from typing import ParamSpec, TypeVar, Callable
P = ParamSpec("P")
R = TypeVar("R")
def jurnal(f: Callable[P, R]) -> Callable[P, R]:
@wraps(f)
def ichki(*args: P.args, **kwargs: P.kwargs) -> R:
return f(*args, **kwargs)
return ichki14-darsda batafsil.
2.6. Amaliy naqshlar
1. Cheksiz argumentli funksiya:
def eng_katta(*sonlar, sukut=None):
if not sonlar:
return sukut
return max(sonlar)2. Ikkala shakl (iterable yoki alohida):
def yigindi(*args):
"""yigindi(1,2,3) va yigindi([1,2,3]) — ikkalasi ham."""
if len(args) == 1 and hasattr(args[0], "__iter__"):
return sum(args[0])
return sum(args)Bu — max, min naqshi:
max(1, 2, 3)
max([1, 2, 3])3. Konfiguratsiyani yig'ish:
def ulan(host, port, **qolgan_sozlamalar):
asosiy = {"host": host, "port": port}
return {**asosiy, **qolgan_sozlamalar}4. Ma'lum kalitlarni ajratish:
def f(**kwargs):
debug = kwargs.pop("debug", False)
timeout = kwargs.pop("timeout", 30)
if kwargs:
raise TypeError(f"Noma'lum argumentlar: {sorted(kwargs)}")
...5. Ko'p funksiyaga tarqatish:
def yarat(**kwargs):
oyna_args = {k: v for k, v in kwargs.items() if k.startswith("oyna_")}
tugma_args = {k: v for k, v in kwargs.items() if k.startswith("tugma_")}
...6. Standart kutubxonadan:
print(*values, sep=" ", end="\n", file=None, flush=False)
dict(**kwargs)
str.format(*args, **kwargs)
functools.partial(f, *args, **kwargs)2.7. Kamchiliklar va cheklovlar
1. Imzo yo'qoladi:
def f(*args, **kwargs): ...- IDE avtoto'ldirish bermaydi
help(f)foydasiz- Tur ko'rsatkichlari yo'q
- Xato faqat ish vaqtida
2. Xatolar kech chiqadi:
def f(**kwargs):
return kwargs["hst"] # ⚠️ "host" xato yozilgan
f(host="x") # ❌ KeyError ancha keyinYechim — tekshirish:
def f(**kwargs):
RUXSAT = {"host", "port", "ssl"}
notogri = set(kwargs) - RUXSAT
if notogri:
raise TypeError(f"Noma'lum argumentlar: {sorted(notogri)}")3. Refaktoring qiyin:
f(*args, **kwargs) # qaysi argumentlar uzatilmoqda?4. Hujjatlash qiyin:
def f(*args, **kwargs):
"""
Argumentlar:
*args: ???
**kwargs: ???
"""Qachon ishlatish:
| Ishlating | Ishlatmang |
|---|---|
| Dekoratorlar | Oddiy funksiyalar |
| O'rash (wrapper) | Ma'lum parametrlar |
Meros (super()) |
Ko'p sukut qiymat |
print kabi cheksiz |
Ixtiyoriy parametrlar |
| Qayta yo'naltirish | API chegarasi |
Muqobil:
def f(*args): ... # ⚠️
def f(sonlar: list[int]): ... # ✅ aniqroq
def f(**kwargs): ... # ⚠️
def f(*, a=1, b=2, c=3): ... # ✅ aniq parametrlar
def f(sozlamalar: Sozlamalar): ... # ✅ dataclass3. Tez ma'lumotnoma
Yig'ish (ta'rifda)
def f(*args): args — TUPLE (bo'sh bo'lsa ham)
def f(**kwargs): kwargs — DICT (tartib saqlanadi)
def f(*args, **kwargs): hamma narsa
def f(a, *args, b): b — FAQAT nomli
def f(a, *, b): b — faqat nomli, qolgan pozitsion QABUL QILINMAYDIOchish (chaqiruvda)
f(*r) iterable → pozitsion
f(**d) lug'at → nomli
f(*a, *b) bir necha marta
[*a, *b], {**d1, **d2} PEP 448To'liq tartib
def f(a, b, /, c, d, *args, e, f=1, **kwargs)
───── ──── ───── ────── ────────
1 2 3 4 5
1. faqat pozitsion (/ dan oldin)
2. pozitsion yoki nomli
3. *args yoki *
4. faqat nomli
5. **kwargs (OXIRIDA)Yo'naltirish
from functools import wraps
def dekorator(f):
@wraps(f) ⭐ metadata ko'chiradi
def ichki(*args, **kwargs):
return f(*args, **kwargs)
return ichki
super().__init__(*args, **kwargs) meros
kwargs.setdefault("timeout", 30) sukut qo'shishKamchiliklar
Imzo yo'qoladi (IDE, help, tur ko'rsatkichlari)
Xatolar kech chiqadi (noma'lum kalit)
Refaktoring va hujjatlash qiyin
✅ Dekorator, o'rash, meros, print kabi
❌ Oddiy funksiya, ma'lum parametrlar4. Batafsil misollar
Misol 1 — Asoslar
"""*args va **kwargs — barcha shakllar."""
import inspect
print("=== 1. *args ===")
def f(*args):
return type(args).__name__, args
CHAQIRUVLAR = [
"f()",
"f(1)",
"f(1, 2, 3)",
"f(*[1, 2, 3])",
"f([1, 2, 3])",
"f(*range(3))",
"f(*'abc')",
"f(*[1, 2], *[3, 4])",
]
for kod in CHAQIRUVLAR:
print(f" {kod:<24} → {eval(kod)}")
print(f"\n ⭐ args — har doim TUPLE, hatto bo'sh bo'lsa ham")
print("\n=== 2. **kwargs ===")
def g(**kwargs):
return type(kwargs).__name__, kwargs
CHAQIRUVLAR = [
"g()",
"g(a=1)",
"g(a=1, b=2)",
"g(**{'a': 1, 'b': 2})",
"g(z=1, a=2, m=3)",
"g(**{'x': 1}, **{'y': 2})",
]
for kod in CHAQIRUVLAR:
print(f" {kod:<28} → {eval(kod)}")
print(f"\n ⭐ kwargs — DICT, tartib SAQLANADI (PEP 468)")
print("\n=== 3. Ikkalasi birga ===")
def h(*args, **kwargs):
return args, kwargs
CHAQIRUVLAR = [
"h()",
"h(1, 2)",
"h(a=1, b=2)",
"h(1, 2, a=3, b=4)",
"h(*[1, 2], **{'a': 3})",
]
for kod in CHAQIRUVLAR:
args, kwargs = eval(kod)
print(f" {kod:<28} → args={args}, kwargs={kwargs}")
print("\n=== 4. Oddiy parametrlar bilan ===")
def k(a, b=2, *args, c, d=4, **kwargs):
return {"a": a, "b": b, "args": args, "c": c, "d": d, "kwargs": kwargs}
print(f" def k(a, b=2, *args, c, d=4, **kwargs):\n")
CHAQIRUVLAR = [
("k(1, c=3)", lambda: k(1, c=3)),
("k(1, 20, c=3)", lambda: k(1, 20, c=3)),
("k(1, 20, 30, 40, c=3)", lambda: k(1, 20, 30, 40, c=3)),
("k(1, c=3, d=40, x=5)", lambda: k(1, c=3, d=40, x=5)),
("k(1, 2, 3)", lambda: k(1, 2, 3)),
]
for kod, fn in CHAQIRUVLAR:
try:
natija = fn()
print(f" {kod:<28}")
for kalit, qiymat in natija.items():
print(f" {kalit:<8} = {qiymat!r}")
except TypeError as x:
print(f" {kod:<28} ❌ TypeError: {x}")
print()
print("=== 5. ⭐ Yig'ish vs ochish ===")
def yigadi(*args):
return args
r = [1, 2, 3]
print(f" r = {r}\n")
print(f" Ta'rifda *args — YIG'ADI:")
print(f" def f(*args): return args\n")
print(f" Chaqiruvda * — OCHADI:")
print(f" f(r) → {yigadi(r)} ← ochish YO'Q, bitta argument")
print(f" f(*r) → {yigadi(*r)} ← ochildi, uchta argument")
print(f"\n Boshqa joylarda ochish (PEP 448):")
a, b = [1, 2], [3, 4]
d1, d2 = {"a": 1}, {"b": 2}
OCHISHLAR = [
("[*a, *b]", [*a, *b]),
("(*a, *b)", (*a, *b)),
("{*a, *b}", {*a, *b}),
("{**d1, **d2}", {**d1, **d2}),
("[0, *a, 9]", [0, *a, 9]),
("{'x': 0, **d1}", {"x": 0, **d1}),
("[*range(3), *'ab']", [*range(3), *"ab"]),
]
for kod, natija in OCHISHLAR:
print(f" {kod:<24} → {natija}")
print("\n=== 6. Tartib qoidalari ===")
TOGRI = [
"def f(*args): ...",
"def f(**kwargs): ...",
"def f(*args, **kwargs): ...",
"def f(a, *args): ...",
"def f(a, *args, b): ...",
"def f(a, *, b): ...",
"def f(a, /, b): ...",
"def f(a, /, b, *args, c, **kwargs): ...",
]
NOTOGRI = [
"def f(**kwargs, a): ...",
"def f(*args, *args2): ...",
"def f(**a, **b): ...",
"def f(a, /, b, /, c): ...",
"def f(*, ): ...",
]
print(f" ✅ To'g'ri:")
for kod in TOGRI:
try:
exec(kod)
print(f" {kod}")
except SyntaxError:
print(f" ❌ {kod}")
print(f"\n ❌ Noto'g'ri:")
for kod in NOTOGRI:
try:
exec(kod)
print(f" ✅ {kod}")
except SyntaxError as x:
print(f" {kod:<32} {x.msg}")
print("\n=== 7. To'liq imzo ===")
def toliq(a, b, /, c, d=4, *args, e, f=6, **kwargs):
...
sig = inspect.signature(toliq)
print(f" {sig}\n")
GURUHLAR = {
"POSITIONAL_ONLY": "faqat pozitsion (/ dan oldin)",
"POSITIONAL_OR_KEYWORD": "pozitsion yoki nomli",
"VAR_POSITIONAL": "*args — qolgan pozitsion",
"KEYWORD_ONLY": "faqat nomli (* dan keyin)",
"VAR_KEYWORD": "**kwargs — qolgan nomli",
}
for kind, izoh in GURUHLAR.items():
nomlar = [n for n, p in sig.parameters.items() if p.kind.name == kind]
print(f" {kind:<24} {str(nomlar):<16} {izoh}")Natijaning muhim qismi:
=== 1. *args ===
f() → ('tuple', ())
f(1) → ('tuple', (1,))
f(*[1, 2, 3]) → ('tuple', (1, 2, 3))
f([1, 2, 3]) → ('tuple', ([1, 2, 3],))
f(*[1, 2], *[3, 4]) → ('tuple', (1, 2, 3, 4))
=== 5. ⭐ Yig'ish vs ochish ===
f(r) → ([1, 2, 3],) ← ochish YO'Q, bitta argument
f(*r) → (1, 2, 3) ← ochildi, uchta argument
=== 6. Tartib qoidalari ===
❌ Noto'g'ri:
def f(**kwargs, a): ... arguments cannot follow var-keyword argument
def f(*args, *args2): ... * argument may appear only once
def f(a, /, b, /, c): ... / may appear only onceNima ko'rsatdi: 2.1, 2.2, 2.3, 2.4-bo'limlar.
Misol 2 — Yo'naltirish va dekoratorlar
"""*args, **kwargs ning asosiy qo'llanishi."""
import time
import inspect
from functools import wraps
print("=== 1. Oddiy yo'naltirish ===")
def asl(a, b, c=3):
return f"asl(a={a}, b={b}, c={c})"
def orash(*args, **kwargs):
print(f" → args={args}, kwargs={kwargs}")
natija = asl(*args, **kwargs)
print(f" ← {natija}")
return natija
CHAQIRUVLAR = [
("orash(1, 2)", (1, 2), {}),
("orash(1, 2, 30)", (1, 2, 30), {}),
("orash(1, b=2, c=30)", (1,), {"b": 2, "c": 30}),
("orash(**{'a':1,'b':2})", (), {"a": 1, "b": 2}),
]
for kod, args, kwargs in CHAQIRUVLAR:
print(f" {kod}")
orash(*args, **kwargs)
print()
print("=== 2. ⚠️ @wraps siz dekorator ===")
def jurnal_yomon(f):
def ichki(*args, **kwargs):
return f(*args, **kwargs)
return ichki
def jurnal_yaxshi(f):
@wraps(f)
def ichki(*args, **kwargs):
return f(*args, **kwargs)
return ichki
@jurnal_yomon
def salom_yomon(ism: str, salom: str = "Salom") -> str:
"""Foydalanuvchini salomlaydi."""
return f"{salom}, {ism}!"
@jurnal_yaxshi
def salom_yaxshi(ism: str, salom: str = "Salom") -> str:
"""Foydalanuvchini salomlaydi."""
return f"{salom}, {ism}!"
ATRIBUTLAR = ["__name__", "__doc__", "__module__", "__qualname__"]
print(f" {'Atribut':<14} {'@wraps siz':<26} {'@wraps bilan'}")
print(" " + "─" * 66)
for atr in ATRIBUTLAR:
a = str(getattr(salom_yomon, atr, None))[:24]
b = str(getattr(salom_yaxshi, atr, None))[:24]
print(f" {atr:<14} {a:<26} {b}")
print(f"\n Imzo:")
print(f" @wraps siz: {inspect.signature(salom_yomon)}")
print(f" @wraps bilan: {inspect.signature(salom_yaxshi)} ⭐")
print(f"\n Tur ko'rsatkichlari:")
print(f" @wraps siz: {getattr(salom_yomon, '__annotations__', {})}")
print(f" @wraps bilan: {salom_yaxshi.__annotations__}")
print(f"\n Asl funksiyaga kirish:")
print(f" salom_yaxshi.__wrapped__ = {salom_yaxshi.__wrapped__.__name__} ⭐")
print("""
⭐ @functools.wraps DOIM ishlating.
U __name__, __doc__, __module__, __qualname__,
__annotations__, __dict__ va __wrapped__ ni sozlaydi.
""")
print("\n=== 3. Foydali dekoratorlar ===")
def vaqt_olch(f):
"""Bajarilish vaqtini o'lchaydi."""
@wraps(f)
def ichki(*args, **kwargs):
boshlandi = time.perf_counter()
natija = f(*args, **kwargs)
vaqt = time.perf_counter() - boshlandi
print(f" ⏱ {f.__name__}: {vaqt * 1000:.3f} ms")
return natija
return ichki
def qayta_urin(urinishlar=3, kutish=0.01):
"""Xato bo'lsa qayta urinadi."""
def dekorator(f):
@wraps(f)
def ichki(*args, **kwargs):
oxirgi_xato = None
for i in range(1, urinishlar + 1):
try:
return f(*args, **kwargs)
except Exception as x:
oxirgi_xato = x
print(f" ⚠️ {i}-urinish muvaffaqiyatsiz: {x}")
if i < urinishlar:
time.sleep(kutish)
raise oxirgi_xato
return ichki
return dekorator
def sukutlar(**standart):
"""Yetishmayotgan nomli argumentlarga sukut qo'shadi."""
def dekorator(f):
@wraps(f)
def ichki(*args, **kwargs):
for k, v in standart.items():
kwargs.setdefault(k, v)
return f(*args, **kwargs)
return ichki
return dekorator
def tekshir(**qoidalar):
"""Argumentlarni tekshiradi."""
def dekorator(f):
sig = inspect.signature(f)
@wraps(f)
def ichki(*args, **kwargs):
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
for nom, qoida in qoidalar.items():
if nom not in bound.arguments:
continue
qiymat = bound.arguments[nom]
if not qoida(qiymat):
raise ValueError(
f"{f.__name__}: {nom}={qiymat!r} tekshiruvdan o'tmadi"
)
return f(*args, **kwargs)
return ichki
return dekorator
@vaqt_olch
def sekin_ish(n):
return sum(range(n))
print(f" @vaqt_olch:")
sekin_ish(1_000_000)
print(f"\n @qayta_urin(urinishlar=3):")
urinish_soni = [0]
@qayta_urin(urinishlar=3, kutish=0.001)
def beqaror():
urinish_soni[0] += 1
if urinish_soni[0] < 3:
raise ConnectionError(f"ulanish yo'q (#{urinish_soni[0]})")
return "muvaffaqiyat"
print(f" natija: {beqaror()}")
print(f"\n @sukutlar(timeout=30):")
@sukutlar(timeout=30, qayta_urin=True)
def sorov(url, timeout=None, qayta_urin=None):
return f"GET {url} (timeout={timeout}, qayta_urin={qayta_urin})"
print(f" sorov('http://x') → {sorov('http://x')}")
print(f" sorov('http://x', timeout=5) → {sorov('http://x', timeout=5)}")
print(f"\n @tekshir(yosh=lambda x: 0 <= x <= 150):")
@tekshir(yosh=lambda x: 0 <= x <= 150, ism=lambda x: len(x) > 0)
def yarat(ism, yosh):
return f"{ism} ({yosh})"
for args in [("Aziz", 30), ("Bobur", 200), ("", 25)]:
try:
print(f" yarat{args} → {yarat(*args)}")
except ValueError as x:
print(f" yarat{args} → ❌ {x}")
print("\n=== 4. Dekoratorlarni birlashtirish ===")
@vaqt_olch
@qayta_urin(urinishlar=2, kutish=0.001)
@sukutlar(rejim="tez")
def murakkab(x, rejim=None):
return f"murakkab({x}, rejim={rejim})"
print(f" @vaqt_olch")
print(f" @qayta_urin(urinishlar=2)")
print(f" @sukutlar(rejim='tez')")
print(f" def murakkab(x, rejim=None):\n")
print(f" murakkab(1) → {murakkab(1)}")
print(f"\n ⭐ Har bir dekorator *args, **kwargs orqali")
print(f" argumentlarni keyingisiga o'tkazadi.")
print(f"\n Imzo saqlandi: {inspect.signature(murakkab)}")
print(f" Nom saqlandi: {murakkab.__name__}")
print("\n=== 5. Meros bilan yo'naltirish ===")
class Asos:
def __init__(self, nom, yosh):
self.nom = nom
self.yosh = yosh
def __repr__(self):
return f"{type(self).__name__}({vars(self)})"
class Xodim(Asos):
def __init__(self, maosh, *args, **kwargs):
super().__init__(*args, **kwargs) # ⭐ yo'naltirish
self.maosh = maosh
class Menejer(Xodim):
def __init__(self, jamoa, *args, **kwargs):
super().__init__(*args, **kwargs)
self.jamoa = jamoa
m = Menejer(jamoa=["Aziz", "Bobur"], maosh=10_000_000,
nom="Aziza", yosh=35)
print(f" Menejer(jamoa=[...], maosh=..., nom=..., yosh=...)")
print(f" → {m}")
print(f"\n MRO: {' → '.join(c.__name__ for c in type(m).__mro__[:-1])}")
print("""
⭐ *args, **kwargs bilan har sinf faqat O'Z parametrlarini
biladi, qolganini ota-onaga o'tkazadi.
""")
print("\n=== 6. ⚠️ Yo'naltirish kamchiliklari ===")
@jurnal_yaxshi
def aniq(a: int, b: str = "x") -> str:
return f"{a}{b}"
print(f" @wraps bilan imzo ko'rinadi: {inspect.signature(aniq)}")
print(f" Lekin ichki funksiya haqiqatda: (*args, **kwargs)\n")
print(f" Xato ish vaqtida chiqadi:")
try:
aniq(1, 2, 3)
except TypeError as x:
print(f" aniq(1, 2, 3) → ❌ {x}")
print("""
⚠️ Muammolar:
• mypy dekoratordan keyin turlarni yo'qotadi (ParamSpec siz)
• Xato faqat ish vaqtida
• Debug qiyinroq (qo'shimcha freym)
⭐ Yechim — typing.ParamSpec (3.10+):
P = ParamSpec("P")
R = TypeVar("R")
def dekorator(f: Callable[P, R]) -> Callable[P, R]:
@wraps(f)
def ichki(*args: P.args, **kwargs: P.kwargs) -> R:
return f(*args, **kwargs)
return ichki
""")Natijaning muhim qismi:
=== 2. ⚠️ @wraps siz dekorator ===
Atribut @wraps siz @wraps bilan
──────────────────────────────────────────────────────────────────
__name__ ichki salom_yaxshi
__doc__ None Foydalanuvchini salomlay
Imzo:
@wraps siz: (*args, **kwargs)
@wraps bilan: (ism: str, salom: str = 'Salom') -> str ⭐
=== 3. Foydali dekoratorlar ===
@qayta_urin(urinishlar=3):
⚠️ 1-urinish muvaffaqiyatsiz: ulanish yo'q (#1)
⚠️ 2-urinish muvaffaqiyatsiz: ulanish yo'q (#2)
natija: muvaffaqiyat
=== 5. Meros bilan yo'naltirish ===
Menejer(jamoa=[...], maosh=..., nom=..., yosh=...)
→ Menejer({'nom': 'Aziza', 'yosh': 35, 'maosh': 10000000,
'jamoa': ['Aziz', 'Bobur']})Nima ko'rsatdi: 2.5-bo'lim.
Misol 3 — Amaliy naqshlar
"""*args va **kwargs ning kundalik qo'llanishi."""
import inspect
from collections.abc import Iterable
print("=== 1. Ikkala shakl (max/min naqshi) ===")
def yigindi(*args, sukut=0):
"""yigindi(1,2,3) va yigindi([1,2,3]) — ikkalasi ham."""
if not args:
return sukut
if len(args) == 1 and isinstance(args[0], Iterable) and not isinstance(args[0], str):
return sum(args[0], sukut)
return sum(args, sukut)
SINOVLAR = [
"yigindi()",
"yigindi(1, 2, 3)",
"yigindi([1, 2, 3])",
"yigindi((1, 2, 3))",
"yigindi(range(4))",
"yigindi({1, 2, 3})",
"yigindi(x for x in [1, 2])",
]
for kod in SINOVLAR:
print(f" {kod:<30} → {eval(kod)}")
print(f"\n Standart kutubxonada:")
print(f" max(1, 2, 3) = {max(1, 2, 3)}")
print(f" max([1, 2, 3]) = {max([1, 2, 3])}")
print(f" max([1], default=0) = {max([1], default=0)}")
print("\n=== 2. Noma'lum argumentlarni tekshirish ===")
def ulan_yomon(**kwargs):
"""⚠️ Xato yozilgan kalit jimgina e'tiborsiz qoladi."""
host = kwargs.get("host", "localhost")
port = kwargs.get("port", 5432)
ssl = kwargs.get("ssl", False)
return f"{host}:{port} ssl={ssl}"
def ulan_yaxshi(**kwargs):
"""✅ Noma'lum kalitni topadi."""
RUXSAT = {"host", "port", "ssl", "timeout"}
notogri = set(kwargs) - RUXSAT
if notogri:
import difflib
takliflar = []
for n in sorted(notogri):
mos = difflib.get_close_matches(n, RUXSAT, n=1, cutoff=0.6)
takliflar.append(f"{n!r}" + (f" ({mos[0]!r} demoqchimidingiz?)" if mos else ""))
raise TypeError(f"Noma'lum argumentlar: {', '.join(takliflar)}")
return (f"{kwargs.get('host', 'localhost')}:{kwargs.get('port', 5432)} "
f"ssl={kwargs.get('ssl', False)}")
SINOVLAR = [
{"host": "db.uz", "port": 5432},
{"host": "db.uz", "prot": 5432}, # xato yozilgan
{"hots": "db.uz", "ssl": True}, # xato yozilgan
{"host": "db.uz", "noma'lum": 1},
]
print(f" {'Argumentlar':<38} {'Yomon':<22} {'Yaxshi'}")
print(" " + "─" * 76)
for kwargs in SINOVLAR:
a = ulan_yomon(**kwargs)
try:
b = ulan_yaxshi(**kwargs)
except TypeError as x:
b = f"❌ {x}"
print(f" {str(kwargs)[:36]:<38} {a:<22} {b[:40]}")
print("""
⚠️ **kwargs xatolarni YASHIRADI — 'prot' jimgina e'tiborsiz qoldi.
⭐ Yaxshiroq: aniq parametrlar (* dan keyin) — Python o'zi tekshiradi.
""")
def ulan_eng_yaxshi(*, host="localhost", port=5432, ssl=False, timeout=30):
"""✅ Eng yaxshi — Python o'zi tekshiradi."""
return f"{host}:{port} ssl={ssl} timeout={timeout}"
try:
ulan_eng_yaxshi(prot=5432)
except TypeError as x:
print(f" ulan_eng_yaxshi(prot=5432) → ❌ {x}")
print("\n=== 3. Argumentlarni ajratish ===")
def yarat_oyna(**kwargs):
"""Prefiks bo'yicha argumentlarni ajratadi."""
guruhlar = {}
umumiy = {}
for k, v in kwargs.items():
if "_" in k:
prefiks, qolgan = k.split("_", 1)
guruhlar.setdefault(prefiks, {})[qolgan] = v
else:
umumiy[k] = v
return umumiy, guruhlar
umumiy, guruhlar = yarat_oyna(
sarlavha="Dastur",
kenglik=800,
oyna_rang="oq",
oyna_ramka=True,
tugma_matn="OK",
tugma_rang="ko'k",
tugma_kenglik=100,
)
print(f" Umumiy: {umumiy}\n")
for prefiks, args in guruhlar.items():
print(f" {prefiks}_*: {args}")
print("\n=== 4. Ma'lum kalitlarni ajratish (pop) ===")
def qayta_ishla(malumot, **sozlamalar):
"""Ma'lum kalitlarni ajratib, qolganini o'tkazadi."""
debug = sozlamalar.pop("debug", False)
qatiy = sozlamalar.pop("qatiy", True)
chegara = sozlamalar.pop("chegara", None)
natija = {
"malumot": malumot,
"debug": debug,
"qatiy": qatiy,
"chegara": chegara,
"qolgan": sozlamalar,
}
return natija
natija = qayta_ishla(
[1, 2, 3],
debug=True,
chegara=10,
boshqa_sozlama="x",
yana_biri=42,
)
for k, v in natija.items():
print(f" {k:<10} = {v}")
print(f"\n ⭐ pop() bilan ajratish — qolganini keyingi funksiyaga o'tkazish")
print("\n=== 5. Xavfsiz chaqirish (filtrlash) ===")
def xavfsiz_chaqir(f, *args, **kwargs):
"""Faqat f qabul qiladigan argumentlarni uzatadi."""
sig = inspect.signature(f)
ps = sig.parameters
if any(p.kind is p.VAR_KEYWORD for p in ps.values()):
return f(*args, **kwargs), set()
mos = {k: v for k, v in kwargs.items() if k in ps}
tashlangan = set(kwargs) - set(mos)
return f(*args, **mos), tashlangan
def a_func(x, y=2):
return f"a({x}, {y})"
def b_func(x, y=2, z=3):
return f"b({x}, {y}, {z})"
def c_func(x, **qolgan):
return f"c({x}, {qolgan})"
KWARGS = {"y": 20, "z": 30, "w": 40}
print(f" kwargs = {KWARGS}\n")
print(f" {'Funksiya':<10} {'Natija':<28} {'Tashlangan'}")
print(" " + "─" * 56)
for f in [a_func, b_func, c_func]:
natija, tashlangan = xavfsiz_chaqir(f, 1, **KWARGS)
print(f" {f.__name__:<10} {natija:<28} {sorted(tashlangan) or '—'}")
print("\n=== 6. Konfiguratsiya birlashtirish ===")
def ulan(host, port, **qolgan):
return {"host": host, "port": port, **qolgan}
STANDART = {"timeout": 30, "ssl": False, "pool": 5}
MUHIT = {"ssl": True, "host": "db.wisar.uz"}
CLI = {"port": 5433, "debug": True}
print(f" STANDART = {STANDART}")
print(f" MUHIT = {MUHIT}")
print(f" CLI = {CLI}\n")
print(f" ❌ Bir necha ** bir xil kalit bilan:")
try:
ulan(**STANDART, **MUHIT, **CLI)
except TypeError as x:
print(f" ulan(**S, **M, **C) → {x}")
print(f"\n ✅ Avval birlashtiring:")
birlashgan = {**STANDART, **MUHIT, **CLI}
print(f" {{**S, **M, **C}} = {birlashgan}")
print(f" ulan(**birlashgan) = {ulan(**birlashgan)}")
print(f"\n ✅ Yoki | (3.9+):")
print(f" ulan(**(S | M | C)) = {ulan(**(STANDART | MUHIT | CLI))}")
print("\n=== 7. print naqshi ===")
def chiqar(*qiymatlar, sep=" ", end="\n", prefiks="", tekislash=None):
"""print ga o'xshash, qo'shimcha imkoniyatlar bilan."""
matn = sep.join(str(q) for q in qiymatlar)
if tekislash:
matn = f"{matn:{tekislash}}"
print(f"{prefiks}{matn}", end=end)
print(f" def chiqar(*qiymatlar, sep=' ', end='\\n', prefiks='', tekislash=None):\n")
chiqar("a", "b", "c", prefiks=" ")
chiqar(1, 2, 3, sep=" | ", prefiks=" ")
chiqar(*range(5), sep="-", prefiks=" ")
chiqar("markazda", tekislash="^30", prefiks=" [", end="]\n")
print(f"\n ⭐ *qiymatlar dan keyin — hammasi FAQAT nomli.")
print(f" Bu print, json.dumps, subprocess.run naqshi.")
import inspect
print(f"\n print imzosi (o'xshash):")
print(f" print(*values, sep=' ', end='\\n', file=None, flush=False)")Natijaning muhim qismi:
=== 2. Noma'lum argumentlarni tekshirish ===
Argumentlar Yomon Yaxshi
────────────────────────────────────────────────────────────────────────────
{'host': 'db.uz', 'port': 5432} db.uz:5432 ssl=False db.uz:5432 ssl=False
{'host': 'db.uz', 'prot': 5432} db.uz:5432 ssl=False ❌ Noma'lum argumentlar: 'prot' ('port' d
ulan_eng_yaxshi(prot=5432) → ❌ ulan_eng_yaxshi() got an unexpected keyword argument 'prot'
=== 5. Xavfsiz chaqirish (filtrlash) ===
Funksiya Natija Tashlangan
────────────────────────────────────────────────────────
a_func a(1, 20) ['w', 'z']
b_func b(1, 20, 30) ['w']
c_func c(1, {'y': 20, 'z': 30, 'w': 40}) —Nima ko'rsatdi: 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: plagin tizimi
"""*args va **kwargs bilan kengaytiriladigan tizim."""
import inspect
import time
from functools import wraps
from typing import Callable, Any
print("=== Hodisa tizimi (event system) ===\n")
class Hodisalar:
"""Obuna va xabar tarqatish tizimi."""
def __init__(self):
self._obunachi: dict[str, list[Callable]] = {}
self._tarix: list[tuple] = []
def obuna(self, hodisa: str):
"""Dekorator: funksiyani hodisaga bog'laydi."""
def dekorator(f):
self._obunachi.setdefault(hodisa, []).append(f)
return f
return dekorator
def qosh(self, hodisa: str, f: Callable) -> None:
self._obunachi.setdefault(hodisa, []).append(f)
def tarqat(self, hodisa: str, *args, **kwargs) -> list:
"""⭐ Argumentlarni barcha obunachiga o'tkazadi."""
self._tarix.append((hodisa, args, kwargs))
natijalar = []
for f in self._obunachi.get(hodisa, []):
try:
natijalar.append(self._xavfsiz_chaqir(f, *args, **kwargs))
except Exception as x:
natijalar.append(f"❌ {type(x).__name__}: {x}")
return natijalar
@staticmethod
def _xavfsiz_chaqir(f, *args, **kwargs):
"""Faqat f qabul qiladigan argumentlarni uzatadi."""
sig = inspect.signature(f)
ps = sig.parameters
# **kwargs bor — hammasini
if any(p.kind is p.VAR_KEYWORD for p in ps.values()):
return f(*args, **kwargs)
# *args bor — barcha pozitsion
if any(p.kind is p.VAR_POSITIONAL for p in ps.values()):
mos_kw = {k: v for k, v in kwargs.items() if k in ps}
return f(*args, **mos_kw)
# Faqat mos keladiganlar
pozitsion_soni = sum(
1 for p in ps.values()
if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)
)
mos_args = args[:pozitsion_soni]
mos_kw = {k: v for k, v in kwargs.items()
if k in ps and ps[k].kind is not ps[k].POSITIONAL_ONLY}
return f(*mos_args, **mos_kw)
def statistika(self) -> dict:
from collections import Counter
return {
"hodisalar": len(self._obunachi),
"obunachi": sum(len(v) for v in self._obunachi.values()),
"tarqatilgan": len(self._tarix),
"eng_kop": Counter(h for h, _, _ in self._tarix).most_common(3),
}
hodisalar = Hodisalar()
# ─── Obunachi funksiyalar — turli imzolar ───
@hodisalar.obuna("foydalanuvchi_kirdi")
def jurnalga_yoz(ism, **qolgan):
"""**kwargs bilan — hamma narsani oladi."""
qosh = f", {qolgan}" if qolgan else ""
return f"JURNAL: {ism} kirdi{qosh}"
@hodisalar.obuna("foydalanuvchi_kirdi")
def xabar_yubor(ism):
"""Faqat ism kerak."""
return f"XABAR: Salom, {ism}!"
@hodisalar.obuna("foydalanuvchi_kirdi")
def statistika_yangila(ism, vaqt=None, ip=None):
"""Ba'zi qo'shimcha maydonlar."""
return f"STATISTIKA: {ism} @ {vaqt or 'noma`lum'} ({ip or '—'})"
@hodisalar.obuna("xato")
def xatoni_yoz(*args, **kwargs):
"""Hamma narsani oladi."""
return f"XATO: args={args}, kwargs={kwargs}"
@hodisalar.obuna("xato")
def ogohlantir(xabar, daraja="OGOH"):
return f"{daraja}: {xabar}"
print("=== 1. Hodisa tarqatish ===\n")
print(f" tarqat('foydalanuvchi_kirdi', 'Aziz', vaqt='10:00', ip='1.2.3.4')")
natijalar = hodisalar.tarqat(
"foydalanuvchi_kirdi", "Aziz", vaqt="10:00", ip="1.2.3.4"
)
for n in natijalar:
print(f" {n}")
print(f"\n tarqat('foydalanuvchi_kirdi', 'Bobur')")
for n in hodisalar.tarqat("foydalanuvchi_kirdi", "Bobur"):
print(f" {n}")
print(f"\n tarqat('xato', 'Ulanish uzildi', daraja='XATO', kod=500)")
for n in hodisalar.tarqat("xato", "Ulanish uzildi", daraja="XATO", kod=500):
print(f" {n}")
print("""
⭐ Har obunachi FAQAT o'ziga kerakli argumentlarni oladi.
Yangi maydon qo'shish eski obunachilarni buzmaydi.
""")
print("\n=== 2. Imzolarni solishtirish ===\n")
print(f" {'Funksiya':<22} {'Imzo':<32} {'Qabul qiladi'}")
print(" " + "─" * 76)
for hodisa, funksiyalar in hodisalar._obunachi.items():
for f in funksiyalar:
sig = inspect.signature(f)
ps = sig.parameters
if any(p.kind is p.VAR_KEYWORD for p in ps.values()):
qabul = "hammasini"
else:
qabul = ", ".join(ps)
print(f" {f.__name__:<22} {str(sig)[:30]:<32} {qabul}")
print("\n\n=== 3. Dekorator zanjiri ===\n")
def vaqt_olch(f):
@wraps(f)
def ichki(*args, **kwargs):
boshlandi = time.perf_counter()
natija = f(*args, **kwargs)
ichki.oxirgi_vaqt = time.perf_counter() - boshlandi
return natija
ichki.oxirgi_vaqt = 0.0
return ichki
def kesh(f):
saqlangan = {}
@wraps(f)
def ichki(*args, **kwargs):
kalit = (args, tuple(sorted(kwargs.items())))
if kalit not in saqlangan:
saqlangan[kalit] = f(*args, **kwargs)
ichki.topilmadi += 1
else:
ichki.topildi += 1
return saqlangan[kalit]
ichki.topildi = ichki.topilmadi = 0
ichki.tozala = saqlangan.clear
return ichki
def sanaqchi(f):
@wraps(f)
def ichki(*args, **kwargs):
ichki.chaqiruvlar += 1
return f(*args, **kwargs)
ichki.chaqiruvlar = 0
return ichki
@sanaqchi
@kesh
@vaqt_olch
def ogir_hisob(n, daraja=2):
"""Qimmat hisoblash."""
return sum(i ** daraja for i in range(n))
print(f" @sanaqchi @kesh @vaqt_olch")
print(f" def ogir_hisob(n, daraja=2):\n")
CHAQIRUVLAR = [
((100_000,), {}),
((100_000,), {}),
((100_000,), {"daraja": 3}),
((50_000,), {}),
((100_000,), {}),
]
for args, kwargs in CHAQIRUVLAR:
natija = ogir_hisob(*args, **kwargs)
kod = f"ogir_hisob({args[0]:,}" + (f", daraja={kwargs['daraja']})" if kwargs else ")")
print(f" {kod:<32} → {str(natija)[:14]}…")
print(f"\n Statistika:")
print(f" Chaqiruvlar: {ogir_hisob.chaqiruvlar}")
print(f" Kesh topildi: {ogir_hisob.__wrapped__.topildi}")
print(f" Hisoblandi: {ogir_hisob.__wrapped__.topilmadi}")
print(f"\n Metadata saqlandi:")
print(f" __name__: {ogir_hisob.__name__}")
print(f" __doc__: {ogir_hisob.__doc__}")
print(f" Imzo: {inspect.signature(ogir_hisob)}")
print("\n\n=== 4. Plagin registratsiyasi ===\n")
class Registr:
"""Nom bo'yicha funksiyalarni saqlaydi."""
def __init__(self, nom: str):
self.nom = nom
self._elementlar: dict[str, Callable] = {}
def royxatga_ol(self, nom: str | None = None, **metadata):
"""Dekorator: funksiyani ro'yxatga oladi."""
def dekorator(f):
kalit = nom or f.__name__
f._metadata = metadata
self._elementlar[kalit] = f
return f
return dekorator
def chaqir(self, nom: str, *args, **kwargs) -> Any:
if nom not in self._elementlar:
mavjud = ", ".join(sorted(self._elementlar))
raise KeyError(f"{nom!r} topilmadi. Mavjud: {mavjud}")
return self._elementlar[nom](*args, **kwargs)
def __contains__(self, nom):
return nom in self._elementlar
def __len__(self):
return len(self._elementlar)
def royxat(self) -> list[tuple[str, dict]]:
return [(n, getattr(f, "_metadata", {}))
for n, f in sorted(self._elementlar.items())]
formatlar = Registr("formatlar")
@formatlar.royxatga_ol("json", kengaytma=".json", ikkilik=False)
def json_format(malumot, *, indent=2, sort_keys=False):
import json
return json.dumps(malumot, indent=indent, sort_keys=sort_keys,
ensure_ascii=False)
@formatlar.royxatga_ol("csv", kengaytma=".csv", ikkilik=False)
def csv_format(malumot, *, ajratgich=","):
if not malumot:
return ""
ustunlar = list(malumot[0])
qatorlar = [ajratgich.join(ustunlar)]
qatorlar += [ajratgich.join(str(q.get(u, "")) for u in ustunlar)
for q in malumot]
return "\n".join(qatorlar)
@formatlar.royxatga_ol("jadval", kengaytma=".txt", ikkilik=False)
def jadval_format(malumot, *, kenglik=12):
if not malumot:
return ""
ustunlar = list(malumot[0])
qatorlar = [" ".join(f"{u:<{kenglik}}" for u in ustunlar)]
qatorlar.append("─" * (kenglik + 1) * len(ustunlar))
qatorlar += [" ".join(f"{str(q.get(u, '')):<{kenglik}}" for u in ustunlar)
for q in malumot]
return "\n".join(qatorlar)
MALUMOT = [
{"ism": "Aziz", "bolim": "IT", "maosh": 7000000},
{"ism": "Bobur", "bolim": "HR", "maosh": 5000000},
]
print(f" Ro'yxatdan olingan formatlar ({len(formatlar)}):\n")
print(f" {'Nom':<12} {'Metadata'}")
print(" " + "─" * 48)
for nom, meta in formatlar.royxat():
print(f" {nom:<12} {meta}")
print(f"\n formatlar.chaqir('jadval', MALUMOT, kenglik=10):")
for q in formatlar.chaqir("jadval", MALUMOT, kenglik=10).splitlines():
print(f" {q}")
print(f"\n formatlar.chaqir('csv', MALUMOT, ajratgich=' | '):")
for q in formatlar.chaqir("csv", MALUMOT, ajratgich=" | ").splitlines():
print(f" {q}")
print(f"\n formatlar.chaqir('json', MALUMOT[:1], indent=4):")
for q in formatlar.chaqir("json", MALUMOT[:1], indent=4).splitlines():
print(f" {q}")
try:
formatlar.chaqir("xml", MALUMOT)
except KeyError as x:
print(f"\n formatlar.chaqir('xml', ...) → ❌ {x}")
print("\n\n=== 5. Tizim statistikasi ===\n")
stat = hodisalar.statistika()
for k, v in stat.items():
print(f" {k:<14} {v}")
print("""
⭐ *args, **kwargs qayerda ishlatildi:
Hodisalar.tarqat(hodisa, *args, **kwargs)
→ argumentlarni barcha obunachiga o'tkazish
_xavfsiz_chaqir(f, *args, **kwargs)
→ har obunachiga faqat kerakli argumentlar
Dekoratorlar: ichki(*args, **kwargs)
→ asl funksiyaga yo'naltirish
Registr.chaqir(nom, *args, **kwargs)
→ dinamik funksiya chaqirish
""")Natijaning muhim qismi:
=== 1. Hodisa tarqatish ===
tarqat('foydalanuvchi_kirdi', 'Aziz', vaqt='10:00', ip='1.2.3.4')
JURNAL: Aziz kirdi, {'vaqt': '10:00', 'ip': '1.2.3.4'}
XABAR: Salom, Aziz!
STATISTIKA: Aziz @ 10:00 (1.2.3.4)
=== 3. Dekorator zanjiri ===
ogir_hisob(100,000) → 333328333350…
ogir_hisob(100,000) → 333328333350…
ogir_hisob(100,000, daraja=3) → 249995000025…
Statistika:
Chaqiruvlar: 5
Kesh topildi: 2
Hisoblandi: 3
Metadata saqlandi:
__name__: ogir_hisob
Imzo: (n, daraja=2)Nima ko'rsatdi: 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"args — ro'yxat" |
tuple |
"kwargs tartibi tasodifiy" |
Saqlanadi (3.6+) |
"* ta'rifda va chaqiruvda bir xil" |
Ta'rifda yig'adi, chaqiruvda ochadi |
"f(*args) va f(args) bir xil" |
f(args) — bitta argument (tuple) |
"*args dan keyin pozitsion mumkin" |
Faqat nomli |
"**kwargs istalgan joyda" |
Doim oxirida |
"@wraps ixtiyoriy" |
Metadata yo'qoladi — deyarli har doim kerak |
"**kwargs — moslashuvchan API" |
Xatolarni yashiradi; aniq parametrlar yaxshiroq |
"f(**d1, **d2) birlashtiradi" |
Umumiy kalit bo'lsa TypeError |
6. Keng tarqalgan xatolar va yechimlari
1. Ochishni unutish
def f(*args): ...
r = [1, 2, 3]
f(r) # ⚠️ ([1,2,3],) — bitta argument
f(*r) # ✅ (1,2,3)2. @wraps yo'q
def dek(f):
def ichki(*a, **k): return f(*a, **k) # ⚠️
return ichki
def dek(f):
@wraps(f) # ✅
def ichki(*a, **k): return f(*a, **k)
return ichki3. *args dan keyin pozitsion kutish
def f(*args, b): ...
f(1, 2, 3) # ❌ b majburiy va faqat nomli
f(1, 2, b=3) # ✅4. Noma'lum kalitlarni tekshirmaslik
def f(**kwargs):
host = kwargs.get("host") # ⚠️ "hots" jimgina e'tiborsiz
def f(*, host=None, port=None): # ✅ Python o'zi tekshiradi5. Bir necha ** bir xil kalit bilan
f(**d1, **d2) # ❌ umumiy kalit bo'lsa
f(**{**d1, **d2}) # ✅6. **kwargs oxirida emas
def f(**kwargs, a): ... # ❌ SyntaxError
def f(a, **kwargs): ... # ✅7. Imzoni yo'qotish
def f(*args, **kwargs): ... # ⚠️ IDE va mypy yordam bermaydi
def f(a: int, b: str): ... # ✅ aniq8. Kesh kaliti sifatida kwargs
kalit = (args, kwargs) # ❌ dict hashlanmaydi
kalit = (args, tuple(sorted(kwargs.items()))) # ✅
kalit = (args, frozenset(kwargs.items())) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 7.2, 7.4-darslar (o'tilgan): argumentlar, ochish
- 7.6-dars:
/va*— imzoni qat'iylashtirish - 8-qism:
super().__init__(*args, **kwargs), metodlar - 10-qism: dekoratorlar,
functools,partial - 14-dars:
ParamSpec, tur ko'rsatkichlari - 6.5-dars (o'tilgan): tuple ochish
inspect: imzo tahlili,bind
8. Eng yaxshi amaliyotlar
@functools.wraps— doim. Metadata va imzoni saqlaydi.*args, **kwargs— faqat yo'naltirish uchun. Oddiy funksiyada aniq parametrlar.**kwargso'rniga*bilan aniq parametrlar. Python o'zi xatoni topadi.Noma'lum kalitlarni tekshiring.
set(kwargs) - RUXSATva aniq xato.Bir necha lug'atni avval birlashtiring.
f(**{**d1, **d2}).args—tuple,kwargs—dict. Ularni o'zgartirish xavfsiz (lokal nusxa).Kesh kaliti uchun
tuple(sorted(kwargs.items())).ParamSpecbilan turlarni saqlang (Python 3.10+).
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
def f(*args): return args
def g(**kw): return kw
def h(a, *args, b, **kw): return a, args, b, kw
1. print(f())
2. print(f([1, 2]))
3. print(f(*[1, 2]))
4. print(f(*[1, 2], *[3]))
5. print(type(f()))
6. print(g(z=1, a=2))
7. print(list(g(z=1, a=2)))
8. print(h(1, 2, 3, b=4, c=5))
9. h(1, 2, 3, 4)
10. print(f(*"ab"))
11. print([*[1,2], *[3]], {**{"a":1}, **{"b":2}})
12. def k(*a, **kw): return len(a), len(kw)
print(k(*range(3), **{"x": 1}))Javoblar
()— bo'sh tuple([1, 2],)— bitta argument(1, 2)— ochildi(1, 2, 3)— ikki marta ochish<class 'tuple'>{'z': 1, 'a': 2}— tartib saqlanadi['z', 'a'](1, (2, 3), 4, {'c': 5})-
TypeError—bfaqat nomli va majburiy ('a', 'b')[1, 2, 3] {'a': 1, 'b': 2}(3, 1)
Vazifa 2: Xatolarni tuzating
1. def f(*args): ...
f(royxat)
2. def dek(f):
def ichki(*a, **k): return f(*a, **k)
return ichki
3. def f(*args, b): ...
f(1, 2, 3)
4. f(**d1, **d2) # umumiy kalitlar bor
5. def f(**kwargs, a): ...
6. kesh[(args, kwargs)] = natija
7. def f(**kwargs):
host = kwargs.get("host") # xato yozilgan kalitni topmaydi
8. def qayta_ishla(*args, **kwargs): ... # oddiy funksiyaJavoblar
1. f(*royxat)
2. @wraps(f) qo'shing
3. f(1, 2, b=3)
4. f(**{**d1, **d2})
5. def f(a, **kwargs): ...
6. kesh[(args, tuple(sorted(kwargs.items())))] = natija
7. def f(*, host=None, port=None): ...
8. def qayta_ishla(malumot: list, *, sozlamalar=None): ...Vazifa 3: Dekoratorlar to'plami
Yozing (barchasi @wraps bilan):
@vaqt_olch— bajarilish vaqti@qayta_urin(n, kutish)— xatoda qayta urinish@kesh(maxsize)— LRU kesh@tekshir(**qoidalar)— argument validatsiyasi@jurnal(daraja)— chaqiruvni yozish@chegaralangan(n, vaqt)— tezlikni cheklash- Hammasini birlashtiring va imzo saqlanganini tekshiring
Vazifa 4: Moslashuvchan chaqiruvchi
xavfsiz_chaqir ni to'liq yozing:
*args,**kwargs,/,*— barcha shakl- Majburiy argument yetishmasa aniq xato
- Tur ko'rsatkichlariga qarab aylantirish
- Statistika: uzatilgan/tashlangan
functools.singledispatchbilan solishtiring
Vazifa 5: Hodisa tizimi
4-misolni kengaytiring:
- Ustuvorlik (
priority) bilan obuna - Bir marta ishlaydigan obunachi (
once) - Filtr shartlari bilan obuna
- Asinxron obunachilar (
async def) - Xatolarni izolyatsiya qilish
- Hodisalar zanjiri (bir hodisa boshqasini chaqiradi)
Vazifa 6: Imzo moslashtiruvchi
Dekorator yozing:
@moslashtir(eski_imzo="(a, b, c)", yangi_imzo="(a, *, b, c)")
def f(a, *, b, c): ...- Eski pozitsion chaqiruvlarni qo'llab-quvvatlasin
DeprecationWarningbersin- Yangi imzoga o'tkazsin
- Docstring ga eslatma qo'shsin
inspect.signatureto'g'ri ko'rsatsin
Vazifa 7: O'ylash
Nega Python *args uchun tuple, **kwargs uchun dict tanladi (list va boshqa emas)?
Javob
Ikki qaror, ikki sabab.
args — nega tuple:
1. O'zgarmaslik — himoya.
def f(*args):
args.append(1) # ❌ AttributeErrorAgar args list bo'lganda, funksiya uni o'zgartira olardi. Bu — chalkash bo'lardi:
def f(*args):
args[0] = 99 # chaqiruvchi ko'radimi? Yo'q, lekin chalkashtuple bilan savol tug'ilmaydi.
2. Tezroq va tejamli.
sys.getsizeof(()) # 40
sys.getsizeof([]) # 56Argumentlar to'plami — har chaqiruvda yaratiladi. tuple:
- Kamroq xotira (
allocatedmaydoni yo'q) - Tezroq yaratiladi
- CPython uni maxsus optimallashtiradi
Funksiya chaqiruvi — eng ko'p bajariladigan amal, har nanosekund muhim.
3. Hashlanadi.
def kesh(f):
saqlangan = {}
def ichki(*args):
if args not in saqlangan: # ⭐ tuple hashlanadi
saqlangan[args] = f(*args)
return saqlangan[args]
return ichkilist bo'lganda bu ishlamasdi — har safar tuple(args) yozish kerak bo'lardi.
4. Semantik: argumentlar — qat'iy yozuv.
tuple — heterogen, qat'iy tuzilma (6.5-dars). Argumentlar aynan shunday: har pozitsiya o'z ma'nosiga ega.
kwargs — nega dict:
1. Boshqa variant yo'q.
Nom → qiymat moslik uchun dict — yagona tabiiy tuzilma.
2. Nega frozendict emas?
Pythonda frozendict yo'q (bir necha marta taklif qilingan — PEP 416 rad etilgan).
Lekin dict bo'lgani ham foydali:
def dek(f):
@wraps(f)
def ichki(*args, **kwargs):
kwargs.setdefault("timeout", 30) # ⭐ o'zgartirish mumkin
kwargs.pop("debug", None)
return f(*args, **kwargs)
return ichkiDekoratorlarda kwargs ni o'zgartirish — juda keng tarqalgan naqsh.
3. Har chaqiruvda YANGI lug'at.
def f(**kwargs):
kwargs["yangi"] = 1
return kwargs
f(a=1) # {'a': 1, 'yangi': 1}
f(a=1) # {'a': 1, 'yangi': 1} — tozaBu — sukut qiymat tuzog'i (7.3-dars) emas: har chaqiruvda yangi lug'at.
4. Tartib saqlanadi (3.6+).
def f(**kwargs):
return list(kwargs)
f(z=1, a=2) # ['z', 'a']PEP 468 buni rasmiy kafolat qildi. Bu — dataclass, ORM, serializatsiya uchun muhim.
Nomuvofiqlik bormi?
Ha, kichik: args o'zgarmas, kwargs o'zgaruvchan. Bu — nomuvofiq ko'rinadi.
Lekin amaliy sabablari bor:
args |
kwargs |
|
|---|---|---|
| O'zgartirish kerakmi | Kamdan-kam | Tez-tez (dekoratorlarda) |
| Hashlanishi kerakmi | Ha (kesh) | Kamdan-kam |
| Tezlik muhimmi | Ha | Kamroq |
| Muqobil bormi | list |
Yo'q |
Amaliy natija:
def f(*args, **kwargs):
args = list(args) # o'zgartirish kerak bo'lsa
args.append(1)
kwargs["yangi"] = 1 # ✅ to'g'ridan-to'g'ri
# Kesh kaliti
kalit = (args_tuple, tuple(sorted(kwargs.items())))Xulosa: har ikki tanlov — amaliy ehtiyojlardan kelib chiqqan. tuple argumentlarni himoyalaydi va keshlashni mumkin qiladi; dict dekoratorlarga argumentlarni o'zgartirish imkonini beradi. Nazariy izchillik amaliy foydaga qurbon qilingan — bu Pythonda tez-tez uchraydigan naqsh.
Nimani mustahkamlaydi: 2.1, 2.2, 2.5-bo'limlar.
Xulosa
Bu darsda *args va **kwargs ni o'rgandik.
Eng muhim uch fikr:
Bir belgi, ikki ma'no. Ta'rifda
*argsargumentlarni yig'adi (tuplega), chaqiruvda*riterable'ni ochadi.**uchun ham shunday: yig'ish →dict, ochish → nomli argumentlar.Asosiy qo'llanish — yo'naltirish. Dekoratorlar, o'rash funksiyalari,
super().__init__(*args, **kwargs). Va bu yerda@functools.wrapsmajburiy — aks holda__name__,__doc__, imzo va tur ko'rsatkichlari yo'qoladi.Oddiy funksiyada ishlatmang.
**kwargsxatolarni yashiradi (prot=5432jimgina e'tiborsiz qoladi). Aniq parametrlar (*dan keyin) — Python o'zi tekshiradi, IDE yordam beradi, hujjat aniq bo'ladi.
Keyingi darsda / va * belgilarini ko'ramiz: faqat pozitsion va faqat nomli argumentlar — API dizaynining eng kuchli vositasi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!