Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Semantika va qoidalar
- 2.2. Qachon nomli argument ishlatish
- 2.3. API dizayni
- 2.4. ** bilan ochish nozikliklari
- 2.5. Nomli argumentlar va *args
- 2.6. Tezlik
- 2.7. inspect bilan tahlil
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Qoidalar va tuzoqlar
- Misol 2 — API dizayni va evolyutsiya
- Misol 3 — inspect va argumentlarni bog'lash
- Misol 4 — Amaliy: konfiguratsiyalanadigan API
- 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.4-dars: Nomli argumentlar
7-QISM — FUNKSIYALAR · 4-dars
1. Kirish va motivatsiya
Ikki chaqiruv, bir xil natija:
yarat_oyna("Hisobot", 800, 600, True, False, True, None, 3)yarat_oyna(
sarlavha="Hisobot",
kenglik=800,
balandlik=600,
korinadigan=True,
modal=False,
ozgartirilsin=True,
ota=None,
ramka_qalinligi=3,
)Birinchisini o'qib bo'lmaydi. True, False, True nimani anglatadi? 3 nima?
Ikkinchisi uzunroq, lekin o'z-o'zini hujjatlaydi. Va parametr tartibi o'zgarsa ham buzilmaydi.
Lekin nomli argumentlarning o'z qoidalari bor:
def f(a, b, c): ...
f(1, 2, c=3) # ✅
f(a=1, 2, 3) # ❌ SyntaxError
f(1, a=2) # ❌ TypeError — a ikki marta
f(1, 2, 3, d=4) # ❌ TypeError — d yo'qVa nozik holatlar:
def f(**kwargs): ...
f(**{"1-kalit": 1}) # ✅ ishlaydi
f(**{1: "a"}) # ❌ TypeErrorBu darsda:
- Nomli argumentlar semantikasi va qoidalari
- Qachon ishlatish — o'qilish qoidalari
- API dizayni — parametr tartibi va evolyutsiyasi
**bilan ochish nozikliklari- Nomlarni o'zgartirish — orqaga moslik
- Tezlik va
inspectbilan tahlil
2. Nazariya — chuqur tushuntirish
2.1. Semantika va qoidalar
def f(a, b, c=3):
return a, b, cTo'rt shakl:
f(1, 2) # pozitsion
f(1, 2, 3) # pozitsion
f(1, b=2) # aralash
f(a=1, b=2, c=3) # to'liq nomli
f(c=3, a=1, b=2) # tartib erkinUchta qoida:
1. Pozitsion argumentlar nomlidan OLDIN:
f(1, b=2) # ✅
f(a=1, 2) # ❌ SyntaxError: positional argument follows keyword argumentBu — sintaksis xatosi, ish vaqtida emas.
2. Har parametr bir marta:
f(1, a=2) # ❌ TypeError: got multiple values for argument 'a'
f(1, 2, b=3) # ❌ TypeError: got multiple values for argument 'b'3. Nom mavjud bo'lishi kerak:
f(1, 2, d=4) # ❌ TypeError: got an unexpected keyword argument 'd'Nomli argumentda tartib muhim emas:
f(c=3, b=2, a=1) # ✅ (1, 2, 3)Lekin hisoblash tartibi — yozilish tartibida:
f(c=birinchi(), a=ikkinchi()) # birinchi() avval chaqiriladi2.2. Qachon nomli argument ishlatish
1. Bool argumentlar — DOIM nomli:
sarala(r, True) # ❌ True nima?
sarala(r, reverse=True) # ✅
f(matn, True, False, True) # ❌ o'qib bo'lmaydi
f(matn, qatiy=True, hisobga=False, tozala=True) # ✅Bu — eng muhim qoida. Bool argument nomsiz — deyarli har doim xato.
2. Ikkitadan ko'p bir xil turdagi argument:
kesim(matn, 0, 10) # ⚠️ 0 va 10 nima?
kesim(matn, boshi=0, oxiri=10) # ✅
masofa(1, 2, 3, 4) # ⚠️
masofa(x1=1, y1=2, x2=3, y2=4) # ✅3. Sukut qiymatli parametrlar:
ochish(yol, "r", "utf-8") # ⚠️ ikkinchi "utf-8" nima?
ochish(yol, kodlash="utf-8") # ✅4. Ma'nosi kontekstsiz tushunarsiz:
qayta_urin(f, 3, 5) # ⚠️ 3 nima, 5 nima?
qayta_urin(f, urinishlar=3, kutish=5) # ✅5. Kelajakda parametr qo'shilishi mumkin:
# v1
def f(a, b): ...
f(1, 2)
# v2 — parametr O'RTAGA qo'shildi
def f(a, yangi, b): ...
f(1, 2) # ⚠️ endi b o'rniga yangi ga tushdi!
# Nomli bilan xavfsiz
f(a=1, b=2) # ✅ har doim to'g'riQachon pozitsion yetarli:
len(r) # ✅ bitta aniq argument
maks(a, b) # ✅ ma'no ravshan
qosh(1, 2) # ✅
d[kalit] # ✅
r.append(x) # ✅Amaliy qoida: agar chaqiruvni o'qib, argument nima ekanini funksiya ta'rifiga qaramasdan aytib bo'lmasa — nom bilan yozing.
2.3. API dizayni
Parametr tartibi — muhim va o'zgartirilmaydigan:
def f(a, b, c): ...Bu tartib — ochiq shartnoma. Uni o'zgartirish barcha pozitsion chaqiruvni buzadi.
Xavfsiz evolyutsiya:
# ✅ Yangi parametrni OXIRIGA, sukut bilan
def f(a, b, c=3): ...
def f(a, b, c=3, d=4): ...
# ✅ Yoki * dan keyin (6-dars)
def f(a, b, *, c=3, d=4): ...
# ❌ O'rtaga qo'shish
def f(a, yangi, b): ... # barcha chaqiruv buziladi
# ❌ Tartibni o'zgartirish
def f(b, a): ... # jimgina noto'g'ri natija!Parametr nomini o'zgartirish — ham buzuvchi:
# v1
def f(royxat): ...
f(royxat=[1, 2]) # ✅
# v2 — nom o'zgardi
def f(elementlar): ...
f(royxat=[1, 2]) # ❌ TypeErrorShuning uchun parametr nomlari ham ochiq API.
Himoya — faqat pozitsion (6-dars):
def f(royxat, /): # nom yopiq — o'zgartirish xavfsiz
...Deprecation naqshi:
def f(elementlar=None, *, royxat=None):
"""royxat — eskirgan, elementlar ishlating."""
if royxat is not None:
import warnings
warnings.warn(
"royxat eskirgan, elementlar ishlating",
DeprecationWarning, stacklevel=2,
)
elementlar = royxat
...2.4. ** bilan ochish nozikliklari
def f(a, b, c=3): ...
f(**{"a": 1, "b": 2}) # ✅
f(1, **{"b": 2}) # ✅ aralash
f(**{"a": 1}, **{"b": 2}) # ✅ ikki lug'at (3.5+)Takrorlangan kalit:
f(**{"a": 1}, **{"a": 2}) # ❌ TypeError: got multiple values for keyword argument 'a'
f(a=1, **{"a": 2}) # ❌ bir xilKalitlar satr bo'lishi kerak:
f(**{1: "a"}) # ❌ TypeError: keywords must be strings Lekin identifikator bo'lishi SHART EMAS (agar **kwargs bo'lsa):
def g(**kwargs): return kwargs
g(**{"1-kalit": 1, "bo'sh joy": 2}) # ✅ {'1-kalit': 1, "bo'sh joy": 2}
g(**{"class": 1}) # ✅ kalit so'z hamChunki **kwargs — oddiy lug'at, uning kalitlariga cheklov yo'q.
To'g'ridan-to'g'ri yozib bo'lmaydi:
g(1-kalit=1) # ❌ SyntaxError
g(class=1) # ❌ SyntaxError
g(**{"class": 1}) # ✅Lug'atlarni birlashtirish:
STANDART = {"host": "localhost", "port": 5432}
FOYDALANUVCHI = {"host": "db.uz"}
ulan(**STANDART, **FOYDALANUVCHI) # ❌ host ikki marta!
ulan(**{**STANDART, **FOYDALANUVCHI}) # ✅
ulan(**(STANDART | FOYDALANUVCHI)) # ✅ 3.9+Filtrlash — faqat mos kalitlarni uzatish:
import inspect
def xavfsiz_chaqir(f, **kwargs):
"""Faqat f qabul qiladigan argumentlarni uzatadi."""
sig = inspect.signature(f)
if any(p.kind is p.VAR_KEYWORD for p in sig.parameters.values()):
return f(**kwargs) # **kwargs bor — hammasini
mos = {k: v for k, v in kwargs.items() if k in sig.parameters}
return f(**mos)2.5. Nomli argumentlar va *args
def f(a, b, *args, c=3, **kwargs):
return a, b, args, c, kwargs *args dan keyingi parametrlar — FAQAT nomli:
f(1, 2, 3, 4) # a=1, b=2, args=(3,4), c=3
f(1, 2, 3, 4, 5) # c ga hech qachon pozitsion tushmaydi
f(1, 2, 3, c=30) # ✅ c=30Bu — 5 va 6-darslarda batafsil.
Tartib qoidasi:
def f(pozitsion, /, oddiy, *args, faqat_nomli, **kwargs):
# ↑ faqat pozitsion ↑ ikkalasi ↑ qolgan pozitsion
# ↑ faqat nomli ↑ qolgan nomliTo'liq shakl (6-dars):
def f(a, b, /, c, d, *args, e, f=1, **kwargs)
───── ──── ───── ────── ────────
faqat ikka qolgan faqat qolgan
pozits. lasi pozits. nomli nomli2.6. Tezlik
Nomli argumentlar biroz sekinroq — nom bo'yicha qidiruv kerak:
def f(a, b, c): ...
f(1, 2, 3) # ~60 ns
f(a=1, b=2, c=3) # ~85 ns (~40% sekinroq)
f(**{"a": 1, "b": 2, "c": 3}) # ~130 nsBu — mikro-farq. Funksiya tanasi har doim bundan ko'p vaqt oladi.
Qachon muhim: juda tor sikllarda (millionlab chaqiruv), masalan sorted(key=...) ichida.
Amaliy tavsiya: o'qilishni tanlang. Tezlik faqat profillash muammoni ko'rsatgandan keyin.
CPython optimallashtirishi:
Python 3.11+ da CALL_FUNCTION_KW va adaptiv bytecode nomli chaqiruvni tezlashtirdi. Farq avvalgidan kichikroq.
2.7. inspect bilan tahlil
import inspect
def f(a, b=2, *args, c, d=4, **kwargs): ...
sig = inspect.signature(f)
print(sig) # (a, b=2, *args, c, d=4, **kwargs)
for nom, p in sig.parameters.items():
print(nom, p.kind.name, p.default)a POSITIONAL_OR_KEYWORD <empty>
b POSITIONAL_OR_KEYWORD 2
args VAR_POSITIONAL <empty>
c KEYWORD_ONLY <empty>
d KEYWORD_ONLY 4
kwargs VAR_KEYWORD <empty>Beshta kind:
| Kind | Ma'nosi | Sintaksis |
|---|---|---|
POSITIONAL_ONLY |
Faqat pozitsion | / dan oldin |
POSITIONAL_OR_KEYWORD |
Ikkalasi ham | Oddiy |
VAR_POSITIONAL |
Qolgan pozitsion | *args |
KEYWORD_ONLY |
Faqat nomli | * dan keyin |
VAR_KEYWORD |
Qolgan nomli | **kwargs |
Argumentlarni bog'lash:
bound = sig.bind(1, c=3)
bound.apply_defaults()
print(bound.arguments) # {'a': 1, 'b': 2, 'args': (), 'c': 3, 'd': 4, 'kwargs': {}}Bu — dekoratorlar va validatsiyada juda foydali.
3. Tez ma'lumotnoma
Qoidalar
f(1, b=2) ✅ pozitsion → nomli
f(a=1, 2) ❌ SyntaxError
f(1, a=2) ❌ multiple values
f(1, 2, d=4) ❌ unexpected keyword
f(c=3, a=1, b=2) ✅ nomli tartib erkinQachon nomli
Bool argument DOIM nomli ⭐
2+ bir xil turda boshi=0, oxiri=10
Sukut qiymatli kodlash="utf-8"
Ma'no tushunarsiz urinishlar=3
Kelajakda o'zgarishi xavfsizroq
Pozitsion yetarli: len(r), max(a,b), r.append(x)API dizayni
✅ Yangi parametr OXIRIGA, sukut bilan
✅ Yoki * dan keyin
❌ O'rtaga qo'shish — pozitsion chaqiruv buziladi
❌ Tartibni o'zgartirish — jimgina noto'g'ri natija
❌ Nomni o'zgartirish — nomli chaqiruv buziladi
→ def f(x, /) bilan nomni yoping** ochish
f(**{"a": 1}) ✅
f(**{1: "a"}) ❌ keywords must be strings
f(**{"a":1}, **{"a":2}) ❌ multiple values
f(**{**d1, **d2}) ✅ birlashtirish
g(**{"class": 1}) ✅ **kwargs bo'lsa — identifikator shart emasinspect
sig = inspect.signature(f)
p.kind: POSITIONAL_ONLY | POSITIONAL_OR_KEYWORD | VAR_POSITIONAL
| KEYWORD_ONLY | VAR_KEYWORD
sig.bind(...).arguments argumentlarni bog'lash4. Batafsil misollar
Misol 1 — Qoidalar va tuzoqlar
"""Nomli argumentlarning barcha qoidalari."""
print("=== 1. To'rt shakl ===")
def f(a, b, c=3):
return a, b, c
SHAKLLAR = [
("f(1, 2)", lambda: f(1, 2)),
("f(1, 2, 3)", lambda: f(1, 2, 3)),
("f(1, b=2)", lambda: f(1, b=2)),
("f(1, 2, c=30)", lambda: f(1, 2, c=30)),
("f(a=1, b=2)", lambda: f(a=1, b=2)),
("f(c=30, a=1, b=2)", lambda: f(c=30, a=1, b=2)),
("f(b=2, a=1)", lambda: f(b=2, a=1)),
]
for kod, fn in SHAKLLAR:
print(f" {kod:<24} → {fn()}")
print(f"\n ⭐ Nomli argumentlarda TARTIB ERKIN")
print("\n=== 2. Xatolar ===")
XATOLAR = [
("f(1)", "f(1)", TypeError),
("f(1, 2, 3, 4)", "f(1, 2, 3, 4)", TypeError),
("f(1, a=2)", "f(1, a=2)", TypeError),
("f(1, 2, d=4)", "f(1, 2, d=4)", TypeError),
("f(a=1, b=2, a=3)", "f(a=1, b=2, a=3)", SyntaxError),
]
for nom, kod, kutilgan in XATOLAR:
try:
eval(kod)
natija = "✅ ishladi"
except (TypeError, SyntaxError) as x:
natija = f"❌ {type(x).__name__}: {x if not isinstance(x, SyntaxError) else x.msg}"
print(f" {nom:<22} {natija}")
print(f"\n f(a=1, 2):")
try:
eval("f(a=1, 2)")
except SyntaxError as x:
print(f" ❌ SyntaxError: {x.msg}")
print("""
⭐ Ikki xil xato:
SyntaxError — kod noto'g'ri yozilgan (kompilyatsiyada)
TypeError — argumentlar mos kelmadi (ish vaqtida)
""")
print("\n=== 3. Hisoblash tartibi ===")
kuzatuv = []
def kuzat(nom, qiymat):
kuzatuv.append(nom)
return qiymat
def g(a, b, c):
return a, b, c
kuzatuv.clear()
natija = g(c=kuzat("c", 3), a=kuzat("a", 1), b=kuzat("b", 2))
print(f" g(c=kuzat('c',3), a=kuzat('a',1), b=kuzat('b',2))\n")
print(f" Natija: {natija}")
print(f" Hisoblash tartibi: {kuzatuv}")
print("""
⭐ Argumentlar YOZILISH tartibida hisoblanadi,
lekin parametrlarga NOM bo'yicha bog'lanadi.
""")
print("\n=== 4. ⚠️ Bool argumentlar ===")
def qidir(matn, naqsh, katta_kichik=False, butun_soz=False,
teskari=False, sanash=False):
natija = []
if katta_kichik:
natija.append("katta-kichik farqlanadi")
if butun_soz:
natija.append("butun so'z")
if teskari:
natija.append("teskari")
if sanash:
natija.append("sanash")
return f"qidir({naqsh!r}: {', '.join(natija) or 'sukut'})"
print(f" ❌ Pozitsion:")
print(f" qidir(matn, 'x', True, False, True, False)")
print(f" → {qidir('matn', 'x', True, False, True, False)}")
print(f" ⚠️ Qaysi True nimani anglatadi?\n")
print(f" ✅ Nomli:")
print(f" qidir(matn, 'x', katta_kichik=True, teskari=True)")
print(f" → {qidir('matn', 'x', katta_kichik=True, teskari=True)}")
print("""
⭐ ENG MUHIM QOIDA:
Bool argument nomsiz — deyarli har doim xato.
""")
print(f" Standart kutubxonadan namunalar:")
NAMUNALAR = [
"sorted(r, reverse=True)",
"json.dumps(d, indent=2, sort_keys=True)",
"open(yol, newline='')",
"re.sub(naqsh, yangi, matn, count=1)",
"subprocess.run(cmd, capture_output=True, check=True)",
]
for n in NAMUNALAR:
print(f" {n}")
print("\n=== 5. Bir xil turdagi argumentlar ===")
def kesim(matn, boshi, oxiri, qadam=1):
return matn[boshi:oxiri:qadam]
def masofa(x1, y1, x2, y2):
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
print(f" ⚠️ kesim('abcdefgh', 2, 6, 2)")
print(f" → {kesim('abcdefgh', 2, 6, 2)}")
print(f" Qaysi son nima?\n")
print(f" ✅ kesim('abcdefgh', boshi=2, oxiri=6, qadam=2)")
print(f" → {kesim('abcdefgh', boshi=2, oxiri=6, qadam=2)}\n")
print(f" ⚠️ masofa(0, 0, 3, 4) → {masofa(0, 0, 3, 4)}")
print(f" ✅ masofa(x1=0, y1=0, x2=3, y2=4) → {masofa(x1=0, y1=0, x2=3, y2=4)}")
print(f"\n ⚠️ Tartibni adashtirish oson:")
print(f" masofa(0, 3, 0, 4) → {masofa(0, 3, 0, 4)} ← boshqa natija!")
print(f" Nomli bilan bunday xato bo'lmaydi")
print("\n=== 6. ⭐ ** bilan ochish ===")
def ulan(host, port, ssl=False, timeout=30):
return f"{'https' if ssl else 'http'}://{host}:{port} (timeout={timeout})"
SINOVLAR = [
("f(**{'host':'x','port':1})", {"host": "x", "port": 1}),
("f(**{'host':'x','port':1,'ssl':True})",
{"host": "x", "port": 1, "ssl": True}),
("f(**{'host':'x'})", {"host": "x"}),
("f(**{'host':'x','port':1,'yangi':1})",
{"host": "x", "port": 1, "yangi": 1}),
("f(**{1:'x'})", {1: "x"}),
]
for nom, kwargs in SINOVLAR:
try:
natija = ulan(**kwargs)
except TypeError as x:
natija = f"❌ {x}"
print(f" {nom:<40}")
print(f" → {natija}")
print(f"\n Aralash:")
print(f" ulan('x', 5432, **{{'ssl': True}})")
print(f" → {ulan('x', 5432, **{'ssl': True})}")
print(f"\n ⚠️ Ikki lug'atda bir xil kalit:")
try:
ulan(**{"host": "a"}, **{"host": "b", "port": 1})
except TypeError as x:
print(f" ulan(**d1, **d2) → ❌ {x}")
print(f" ulan(**{{**d1, **d2}}) → "
f"{ulan(**{**{'host': 'a'}, **{'host': 'b', 'port': 1}})} ✅")
print("\n=== 7. **kwargs bilan erkin kalitlar ===")
def g(**kwargs):
return kwargs
ERKIN = [
("{'oddiy': 1}", {"oddiy": 1}),
("{'1-kalit': 1}", {"1-kalit": 1}),
("{'bo`sh joy': 1}", {"bo'sh joy": 1}),
("{'class': 1}", {"class": 1}),
("{'': 1}", {"": 1}),
("{1: 1}", {1: 1}),
]
print(f" def g(**kwargs): return kwargs\n")
for nom, d in ERKIN:
try:
natija = f"✅ {g(**d)}"
except TypeError as x:
natija = f"❌ {x}"
print(f" g(**{nom:<18}) → {natija}")
print("""
⭐ **kwargs — oddiy lug'at, kalitlari identifikator bo'lishi SHART EMAS.
Lekin ular faqat ** orqali uzatiladi:
g(class=1) ❌ SyntaxError
g(**{"class": 1}) ✅
""")Natijaning muhim qismi:
=== 2. Xatolar ===
f(1) ❌ TypeError: f() missing 1 required positional argument: 'b'
f(1, 2, 3, 4) ❌ TypeError: f() takes from 2 to 3 positional arguments but 4 were given
f(1, a=2) ❌ TypeError: f() got multiple values for argument 'a'
f(1, 2, d=4) ❌ TypeError: f() got an unexpected keyword argument 'd'
f(a=1, 2):
❌ SyntaxError: positional argument follows keyword argument
=== 3. Hisoblash tartibi ===
Natija: (1, 2, 3)
Hisoblash tartibi: ['c', 'a', 'b']
=== 7. **kwargs bilan erkin kalitlar ===
g(**{'1-kalit': 1} ) → ✅ {'1-kalit': 1}
g(**{'class': 1} ) → ✅ {'class': 1}
g(**{1: 1} ) → ❌ keywords must be stringsNima ko'rsatdi: 2.1, 2.2, 2.4-bo'limlar.
Misol 2 — API dizayni va evolyutsiya
"""Parametr tartibi va nomlari — ochiq shartnoma."""
import warnings
print("=== 1. ⚠️ Tartibni o'zgartirish ===")
def bol_v1(a, b):
"""Versiya 1."""
return a / b
def bol_v2(b, a):
"""⚠️ Versiya 2 — tartib o'zgardi."""
return a / b
print(f" v1: def bol(a, b): return a / b")
print(f" v2: def bol(b, a): return a / b ⚠️ tartib almashdi\n")
print(f" Pozitsion chaqiruv:")
print(f" bol_v1(10, 2) = {bol_v1(10, 2)}")
print(f" bol_v2(10, 2) = {bol_v2(10, 2)} ⚠️ JIMGINA boshqa natija!")
print(f"\n Nomli chaqiruv:")
print(f" bol_v1(a=10, b=2) = {bol_v1(a=10, b=2)}")
print(f" bol_v2(a=10, b=2) = {bol_v2(a=10, b=2)} ✅ bir xil")
print("""
⭐ Nomli chaqiruv tartib o'zgarishidan HIMOYALAYDI.
Pozitsion chaqiruv — jimgina buziladi (xato yo'q!).
""")
print("\n=== 2. ⚠️ O'rtaga parametr qo'shish ===")
def yarat_v1(nom, yosh):
return f"{nom} ({yosh})"
def yarat_v2(nom, familiya, yosh):
"""⚠️ familiya O'RTAGA qo'shildi."""
return f"{nom} {familiya} ({yosh})"
def yarat_v3(nom, yosh, familiya=""):
"""✅ familiya OXIRIGA, sukut bilan."""
return f"{nom} {familiya} ({yosh})".replace(" ", " ")
print(f" Eski kod: yarat('Aziz', 30)\n")
print(f" v1: {yarat_v1('Aziz', 30)}")
try:
print(f" v2: {yarat_v2('Aziz', 30)}")
except TypeError as x:
print(f" v2: ❌ TypeError: {x}")
print(f" v3: {yarat_v3('Aziz', 30)} ✅ eski kod ishlaydi")
print(f"\n ⚠️ Yanada yomoni — sukut bilan o'rtaga:")
def yarat_v4(nom, familiya="", yosh=0):
return f"{nom} {familiya} ({yosh})"
print(f" def yarat(nom, familiya='', yosh=0)")
print(f" yarat('Aziz', 30) → {yarat_v4('Aziz', 30)}")
print(f" ⚠️ 30 familiya ga tushdi — JIMGINA noto'g'ri!")
print("\n=== 3. ⚠️ Parametr nomini o'zgartirish ===")
def qayta_ishla_v1(royxat):
return len(royxat)
def qayta_ishla_v2(elementlar):
"""⚠️ Nom o'zgardi."""
return len(elementlar)
print(f" v1: def qayta_ishla(royxat)")
print(f" v2: def qayta_ishla(elementlar)\n")
print(f" Pozitsion chaqiruv:")
print(f" qayta_ishla_v1([1,2]) = {qayta_ishla_v1([1, 2])}")
print(f" qayta_ishla_v2([1,2]) = {qayta_ishla_v2([1, 2])} ✅")
print(f"\n Nomli chaqiruv:")
print(f" qayta_ishla_v1(royxat=[1,2]) = {qayta_ishla_v1(royxat=[1, 2])}")
try:
qayta_ishla_v2(royxat=[1, 2])
except TypeError as x:
print(f" qayta_ishla_v2(royxat=[1,2]) → ❌ {x}")
print("""
⭐ Parametr NOMLARI ham ochiq API!
Ularni o'zgartirish nomli chaqiruvlarni buzadi.
""")
print("\n=== 4. ✅ Himoya: faqat pozitsion (/) ===")
def qayta_ishla_himoyalangan(royxat, /):
"""/ — royxat nomi YOPIQ (6-dars)."""
return len(royxat)
print(f" def qayta_ishla(royxat, /):\n")
print(f" qayta_ishla([1,2]) = {qayta_ishla_himoyalangan([1, 2])} ✅")
try:
qayta_ishla_himoyalangan(royxat=[1, 2])
except TypeError as x:
print(f" qayta_ishla(royxat=[1,2]) → ❌ {x}")
print("""
⭐ / bilan parametr nomi ICHKI tafsilotga aylanadi —
uni erkin o'zgartirish mumkin.
Standart kutubxonada ko'p ishlatiladi:
len(obj, /), abs(x, /), pow(base, exp, mod=None)
""")
print("\n=== 5. Deprecation naqshi ===")
def qayta_ishla_v3(elementlar=None, *, royxat=None):
"""Eski `royxat` nomini vaqtincha qo'llab-quvvatlaydi."""
if royxat is not None:
if elementlar is not None:
raise TypeError("elementlar va royxat birga berilmaydi")
warnings.warn(
"royxat parametri eskirgan, elementlar ishlating",
DeprecationWarning,
stacklevel=2,
)
elementlar = royxat
if elementlar is None:
raise TypeError("elementlar majburiy")
return len(elementlar)
print(f" def f(elementlar=None, *, royxat=None):\n")
with warnings.catch_warnings(record=True) as ogohlar:
warnings.simplefilter("always")
print(f" f([1,2]) = {qayta_ishla_v3([1, 2])} ✅ yangi")
print(f" f(elementlar=[1,2]) = {qayta_ishla_v3(elementlar=[1, 2])} ✅")
natija = qayta_ishla_v3(royxat=[1, 2])
print(f" f(royxat=[1,2]) = {natija} ⚠️ ishlaydi + ogohlantirish")
print(f"\n Ogohlantirishlar:")
for o in ogohlar:
print(f" {o.category.__name__}: {o.message}")
try:
qayta_ishla_v3([1], royxat=[2])
except TypeError as x:
print(f"\n f([1], royxat=[2]) → ❌ {x}")
print("\n=== 6. ✅ Xavfsiz evolyutsiya ===")
print("""
┌───────────────────────────────┬──────────────────────────────┐
│ O'zgarish │ Xavfsizmi │
├───────────────────────────────┼──────────────────────────────┤
│ Yangi parametr OXIRIGA+sukut │ ✅ Ha │
│ Yangi parametr * dan keyin │ ✅ Ha (eng xavfsiz) │
│ Sukut qiymatni o'zgartirish │ ⚠️ Xatti-harakat o'zgaradi │
│ Parametrni o'rtaga qo'shish │ ❌ Yo'q │
│ Tartibni o'zgartirish │ ❌ Yo'q (jimgina buziladi) │
│ Nomni o'zgartirish │ ❌ Yo'q (nomli chaqiruvlar) │
│ Parametrni olib tashlash │ ❌ Yo'q │
│ Majburiyni ixtiyoriy qilish │ ✅ Ha │
│ Ixtiyoriyni majburiy qilish │ ❌ Yo'q │
│ / qo'shish (nomni yopish) │ ❌ Yo'q (nomli chaqiruvlar) │
│ * qo'shish (nomni majburiy) │ ❌ Yo'q (pozitsion chaqiruv) │
└───────────────────────────────┴──────────────────────────────┘
""")
print(f" ⭐ ENG XAVFSIZ dizayn — boshidan:\n")
print(f""" def f(majburiy, /, *, ixtiyoriy1=None, ixtiyoriy2=None):
# ↑ nom yopiq ↑ tartib muhim emas
• majburiy nomini erkin o'zgartirish mumkin
• yangi ixtiyoriy parametr har doim qo'shish mumkin
• ixtiyoriylar tartibi muhim emas
""")
print("\n=== 7. Standart kutubxonadan namunalar ===")
NAMUNALAR = [
("sorted(iterable, /, *, key=None, reverse=False)",
"iterable nomi yopiq, key/reverse faqat nomli"),
("open(file, mode='r', buffering=-1, encoding=None, ...)",
"ko'p ixtiyoriy — amalda nomli ishlatiladi"),
("dict.get(key, default=None, /)",
"ikkalasi ham faqat pozitsion"),
("print(*values, sep=' ', end='\\n', file=None, flush=False)",
"*values dan keyin — hammasi faqat nomli"),
("json.dumps(obj, *, skipkeys=False, indent=None, ...)",
"obj dan keyin — hammasi faqat nomli"),
]
for imzo, izoh in NAMUNALAR:
print(f" {imzo}")
print(f" → {izoh}\n")
import inspect
print(f" Haqiqiy imzolar:")
for f in [sorted, print, len]:
try:
print(f" {f.__name__:<10} {inspect.signature(f)}")
except ValueError:
print(f" {f.__name__:<10} (C funksiyasi — imzo yo'q)")Natijaning muhim qismi:
=== 1. ⚠️ Tartibni o'zgartirish ===
Pozitsion chaqiruv:
bol_v1(10, 2) = 5.0
bol_v2(10, 2) = 0.2 ⚠️ JIMGINA boshqa natija!
Nomli chaqiruv:
bol_v1(a=10, b=2) = 5.0
bol_v2(a=10, b=2) = 5.0 ✅ bir xil
=== 4. ✅ Himoya: faqat pozitsion (/) ===
qayta_ishla([1,2]) = 2 ✅
qayta_ishla(royxat=[1,2]) → ❌ qayta_ishla_himoyalangan() got some
positional-only arguments passed as keyword arguments: 'royxat'
=== 5. Deprecation naqshi ===
Ogohlantirishlar:
DeprecationWarning: royxat parametri eskirgan, elementlar ishlatingNima ko'rsatdi: 2.3-bo'lim.
Misol 3 — inspect va argumentlarni bog'lash
"""Funksiya imzosini tahlil qilish va argumentlarni bog'lash."""
import inspect
from functools import wraps
print("=== 1. Imzo tahlili ===")
def toliq(a, b, /, c, d=4, *args, e, f=6, **kwargs):
"""Barcha parametr turlari."""
return locals()
sig = inspect.signature(toliq)
print(f" def toliq(a, b, /, c, d=4, *args, e, f=6, **kwargs):\n")
print(f" Imzo: {sig}\n")
print(f" {'Parametr':<12} {'Kind':<24} {'Sukut'}")
print(" " + "─" * 50)
for nom, p in sig.parameters.items():
sukut = "—" if p.default is p.empty else repr(p.default)
print(f" {nom:<12} {p.kind.name:<24} {sukut}")
print(f"\n Guruhlar:")
GURUHLAR = {}
for nom, p in sig.parameters.items():
GURUHLAR.setdefault(p.kind.name, []).append(nom)
for kind, nomlar in GURUHLAR.items():
print(f" {kind:<24} {nomlar}")
print("\n=== 2. Argumentlarni bog'lash ===")
CHAQIRUVLAR = [
"toliq(1, 2, 3, e=5)",
"toliq(1, 2, c=3, e=5)",
"toliq(1, 2, 3, 4, 5, 6, e=7, f=8, x=9)",
"toliq(1, 2, 3)",
"toliq(1, c=3, e=5)",
]
for kod in CHAQIRUVLAR:
print(f" {kod}")
try:
# Argumentlarni ajratish
ichki = kod[kod.index("(") + 1:-1]
bound = eval(f"sig.bind({ichki})")
bound.apply_defaults()
print(f" ✅ {dict(bound.arguments)}")
except TypeError as x:
print(f" ❌ TypeError: {x}")
print()
print("=== 3. Amaliy: argumentlarni jurnalga yozish ===")
def jurnalga_yoz(f):
"""Chaqiruv argumentlarini nomlari bilan chiqaradi."""
sig = inspect.signature(f)
@wraps(f)
def ichki(*args, **kwargs):
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
argumentlar = ", ".join(
f"{k}={v!r}" for k, v in bound.arguments.items()
)
print(f" → {f.__name__}({argumentlar})")
natija = f(*args, **kwargs)
print(f" ← {natija!r}")
return natija
return ichki
@jurnalga_yoz
def hisobla(asos, daraja=2, *, modul=None):
natija = asos ** daraja
return natija % modul if modul else natija
print(f" @jurnalga_yoz\n def hisobla(asos, daraja=2, *, modul=None):\n")
for kod, args, kwargs in [
("hisobla(5)", (5,), {}),
("hisobla(5, 3)", (5, 3), {}),
("hisobla(5, daraja=3, modul=7)", (5,), {"daraja": 3, "modul": 7}),
]:
print(f" {kod}:")
hisobla(*args, **kwargs)
print()
print("=== 4. Xavfsiz chaqirish ===")
def xavfsiz_chaqir(f, **kwargs):
"""Faqat f qabul qiladigan argumentlarni uzatadi."""
sig = inspect.signature(f)
parametrlar = sig.parameters
if any(p.kind is p.VAR_KEYWORD for p in parametrlar.values()):
return f(**kwargs) # **kwargs bor
mos = {k: v for k, v in kwargs.items() if k in parametrlar}
ortiqcha = set(kwargs) - set(mos)
if ortiqcha:
print(f" (e'tiborsiz: {sorted(ortiqcha)})")
return f(**mos)
def ulan(host, port, ssl=False):
return f"{host}:{port} ssl={ssl}"
def ulan_erkin(host, port, **qolgan):
return f"{host}:{port} qolgan={qolgan}"
SOZLAMALAR = {"host": "db.uz", "port": 5432, "ssl": True,
"noma'lum": 1, "yana_bir": 2}
print(f" SOZLAMALAR = {SOZLAMALAR}\n")
print(f" ulan(**SOZLAMALAR) to'g'ridan-to'g'ri:")
try:
ulan(**SOZLAMALAR)
except TypeError as x:
print(f" ❌ {x}\n")
print(f" xavfsiz_chaqir(ulan, **SOZLAMALAR):")
print(f" → {xavfsiz_chaqir(ulan, **SOZLAMALAR)}\n")
print(f" xavfsiz_chaqir(ulan_erkin, **SOZLAMALAR):")
print(f" → {xavfsiz_chaqir(ulan_erkin, **SOZLAMALAR)}")
print("\n=== 5. Imzo validatori ===")
def imzoni_baholash(f) -> dict:
"""Funksiya imzosining sifat ko'rsatkichlari."""
try:
sig = inspect.signature(f)
except (ValueError, TypeError):
return {"xato": "imzo o'qib bo'lmadi"}
ps = list(sig.parameters.values())
pozitsion = [p for p in ps
if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)]
nomli = [p for p in ps if p.kind is p.KEYWORD_ONLY]
bool_sukutli = [p for p in ps
if isinstance(p.default, bool)
and p.kind is p.POSITIONAL_OR_KEYWORD]
ozgaruvchan_sukut = [p for p in ps
if isinstance(p.default, (list, dict, set))]
ogohlar = []
if len(pozitsion) > 4:
ogohlar.append(f"{len(pozitsion)} pozitsion parametr (4 dan ko'p)")
if bool_sukutli:
ogohlar.append(
f"bool parametr pozitsion bo'lishi mumkin: "
f"{[p.name for p in bool_sukutli]}"
)
if ozgaruvchan_sukut:
ogohlar.append(
f"o'zgaruvchan sukut: {[p.name for p in ozgaruvchan_sukut]}"
)
if len(ps) > 8:
ogohlar.append(f"{len(ps)} parametr — juda ko'p")
return {
"jami": len(ps),
"pozitsion": len(pozitsion),
"faqat_nomli": len(nomli),
"ogohlar": ogohlar,
}
def yomon1(a, b, c, d, e, f): ...
def yomon2(matn, tozala=True, qatiy=False, teskari=True): ...
def yomon3(a, r=[], d={}): ...
def yaxshi1(a, b, *, c=1, d=2): ...
def yaxshi2(malumot, /, *, sozlamalar=None): ...
FUNKSIYALAR = [yomon1, yomon2, yomon3, yaxshi1, yaxshi2, sorted, print]
for f in FUNKSIYALAR:
nom = getattr(f, "__name__", str(f))
natija = imzoni_baholash(f)
if "xato" in natija:
print(f" {nom:<10} (imzo o'qib bo'lmadi)")
continue
belgi = "⚠️" if natija["ogohlar"] else "✅"
print(f" {belgi} {nom:<10} jami={natija['jami']}, "
f"pozitsion={natija['pozitsion']}, nomli={natija['faqat_nomli']}")
for o in natija["ogohlar"]:
print(f" • {o}")
print("\n=== 6. Tezlik ===")
import timeit
def f3(a, b, c):
return a + b + c
SOZLASH = "from __main__ import f3\nd = {'a': 1, 'b': 2, 'c': 3}"
SINOVLAR = [
("f(1, 2, 3)", "f3(1, 2, 3)"),
("f(1, 2, c=3)", "f3(1, 2, c=3)"),
("f(a=1, b=2, c=3)", "f3(a=1, b=2, c=3)"),
("f(**d)", "f3(**d)"),
("f(**{'a':1,'b':2,'c':3})", "f3(**{'a': 1, 'b': 2, 'c': 3})"),
]
natijalar = []
for nom, kod in SINOVLAR:
vaqt = timeit.timeit(kod, setup=SOZLASH, number=3_000_000)
natijalar.append((nom, vaqt))
eng_tez = min(v for _, v in natijalar)
print(f" 3M chaqiruv:\n")
print(f" {'Chaqiruv':<28} {'Vaqt':>9} {'Nisbat':>9}")
print(" " + "─" * 50)
for nom, vaqt in natijalar:
print(f" {nom:<28} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")
print("""
⚠️ Nomli argument ~20-40% sekinroq (nom bo'yicha qidiruv).
⭐ Lekin bu — nanosekundlar. Funksiya tanasi har doim ko'proq oladi.
O'qilishni tanlang, tezlikni profillashdan keyin optimallashtiring.
""")Natijaning muhim qismi:
=== 1. Imzo tahlili ===
Parametr Kind Sukut
──────────────────────────────────────────────────
a POSITIONAL_ONLY —
b POSITIONAL_ONLY —
c POSITIONAL_OR_KEYWORD —
d POSITIONAL_OR_KEYWORD 4
args VAR_POSITIONAL —
e KEYWORD_ONLY —
f KEYWORD_ONLY 6
kwargs VAR_KEYWORD —
=== 3. Amaliy: argumentlarni jurnalga yozish ===
hisobla(5, daraja=3, modul=7):
→ hisobla(asos=5, daraja=3, modul=7)
← 6
=== 5. Imzo validatori ===
⚠️ yomon1 jami=6, pozitsion=6, nomli=0
• 6 pozitsion parametr (4 dan ko'p)
⚠️ yomon2 jami=4, pozitsion=4, nomli=0
• bool parametr pozitsion bo'lishi mumkin: ['tozala', 'qatiy', 'teskari']
✅ yaxshi1 jami=4, pozitsion=2, nomli=2Nima ko'rsatdi: 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: konfiguratsiyalanadigan API
"""Nomli argumentlar bilan yaxshi API dizayni."""
import inspect
from dataclasses import dataclass
from enum import Enum
print("=== Jadval chizuvchi API ===\n")
class Tekislash(Enum):
CHAP = "<"
MARKAZ = "^"
ONG = ">"
class Uslub(Enum):
ODDIY = ("│", "─", "┌", "┐", "└", "┘", "├", "┤", "┬", "┴", "┼")
QALIN = ("┃", "━", "┏", "┓", "┗", "┛", "┣", "┫", "┳", "┻", "╋")
IKKI = ("║", "═", "╔", "╗", "╚", "╝", "╠", "╣", "╦", "╩", "╬")
YOQ = (" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ")
def jadval(
qatorlar: list[dict],
/, # ⭐ qatorlar nomi yopiq
*, # ⭐ qolgan hammasi FAQAT nomli
ustunlar: tuple[str, ...] | None = None,
sarlavha: str | None = None,
uslub: Uslub = Uslub.ODDIY,
tekislash: Tekislash | dict[str, Tekislash] = Tekislash.CHAP,
raqamlar: bool = False,
jami_qatori: bool = False,
jami_ustunlari: tuple[str, ...] = (),
maksimal_kenglik: int = 30,
bosh_qiymat: str = "—",
) -> str:
"""Lug'atlar ro'yxatidan matn jadvali yaratadi.
Barcha sozlamalar FAQAT nomli — chaqiruv o'z-o'zini hujjatlaydi.
"""
if not qatorlar:
return "(bo'sh)"
ustunlar = ustunlar or tuple(qatorlar[0])
v, h, yc, yo_, pc, po, chap, ong, yuq, past, orta = uslub.value
def matn(q, u):
qiymat = q.get(u)
if qiymat is None:
return bosh_qiymat
if isinstance(qiymat, (int, float)) and not isinstance(qiymat, bool):
return f"{qiymat:,}"
return str(qiymat)[:maksimal_kenglik]
barcha_qatorlar = list(qatorlar)
if jami_qatori and jami_ustunlari:
jami = {u: "JAMI" for u in ustunlar[:1]}
for u in jami_ustunlari:
jami[u] = sum(q.get(u, 0) for q in qatorlar
if isinstance(q.get(u), (int, float)))
barcha_qatorlar.append(jami)
kengliklar = {
u: max(len(str(u)), max(len(matn(q, u)) for q in barcha_qatorlar))
for u in ustunlar
}
if raqamlar:
raqam_kengligi = max(3, len(str(len(qatorlar))))
def tekislash_ol(u):
if isinstance(tekislash, dict):
return tekislash.get(u, Tekislash.CHAP).value
return tekislash.value
def chiziq(chap_b, orta_b, ong_b):
qismlar = [h * (kengliklar[u] + 2) for u in ustunlar]
if raqamlar:
qismlar.insert(0, h * (raqam_kengligi + 2))
return chap_b + orta_b.join(qismlar) + ong_b
def qator_chiz(qiymatlar, tekislashlar):
qismlar = [f" {q:{t}{kengliklar[u]}} "
for q, t, u in zip(qiymatlar, tekislashlar, ustunlar)]
if raqamlar:
qismlar.insert(0, f" {qiymatlar_raqami:>{raqam_kengligi}} ")
return v + v.join(qismlar) + v
natija = []
if sarlavha:
kenglik = sum(kengliklar.values()) + 3 * len(ustunlar) - 1
if raqamlar:
kenglik += raqam_kengligi + 3
natija.append(f"{yc}{h * kenglik}{yo_}")
natija.append(f"{v} {sarlavha:^{kenglik - 2}} {v}")
natija.append(chiziq(chap, yuq, ong))
else:
natija.append(chiziq(yc, yuq, yo_))
qiymatlar_raqami = "#"
natija.append(qator_chiz(list(ustunlar), ["^"] * len(ustunlar)))
natija.append(chiziq(chap, orta, ong))
for i, q in enumerate(qatorlar, 1):
qiymatlar_raqami = i
natija.append(qator_chiz(
[matn(q, u) for u in ustunlar],
[tekislash_ol(u) for u in ustunlar],
))
if jami_qatori and jami_ustunlari:
natija.append(chiziq(chap, orta, ong))
qiymatlar_raqami = ""
jami_q = barcha_qatorlar[-1]
natija.append(qator_chiz(
[matn(jami_q, u) for u in ustunlar],
[tekislash_ol(u) for u in ustunlar],
))
natija.append(chiziq(pc, past, po))
return "\n".join(" " + q for q in natija)
# ═══ NAMOYISH ═══
XODIMLAR = [
{"ism": "Aziz", "bolim": "IT", "yosh": 30, "maosh": 7_000_000},
{"ism": "Bobur", "bolim": "HR", "yosh": 25, "maosh": 5_000_000},
{"ism": "Aziza", "bolim": "IT", "yosh": 35, "maosh": 8_500_000},
{"ism": "Dilnoza", "bolim": "Moliya", "yosh": 28, "maosh": None},
]
print("=== 1. Sukut sozlamalar ===\n")
print(jadval(XODIMLAR))
print("\n\n=== 2. Sarlavha va raqamlar ===\n")
print(jadval(
XODIMLAR,
sarlavha="XODIMLAR RO'YXATI",
raqamlar=True,
))
print("\n\n=== 3. Tekislash va uslub ===\n")
print(jadval(
XODIMLAR,
ustunlar=("ism", "yosh", "maosh"),
uslub=Uslub.IKKI,
tekislash={
"ism": Tekislash.CHAP,
"yosh": Tekislash.MARKAZ,
"maosh": Tekislash.ONG,
},
))
print("\n\n=== 4. Jami qatori ===\n")
print(jadval(
XODIMLAR,
sarlavha="MAOSH HISOBOTI",
ustunlar=("ism", "bolim", "maosh"),
uslub=Uslub.QALIN,
tekislash={"maosh": Tekislash.ONG},
jami_qatori=True,
jami_ustunlari=("maosh",),
bosh_qiymat="(yo'q)",
))
print("\n\n=== 5. ⭐ Chaqiruv o'z-o'zini hujjatlaydi ===\n")
print(""" ❌ Agar hammasi pozitsion bo'lganda:
jadval(XODIMLAR, ("ism","bolim","maosh"), "MAOSH HISOBOTI",
Uslub.QALIN, {...}, False, True, ("maosh",), 30, "(yo'q)")
← False va True nima? 30 nima?
✅ Nomli argumentlar bilan:
jadval(
XODIMLAR,
sarlavha="MAOSH HISOBOTI",
ustunlar=("ism", "bolim", "maosh"),
uslub=Uslub.QALIN,
jami_qatori=True,
jami_ustunlari=("maosh",),
bosh_qiymat="(yo'q)",
)
← har argument o'zini tushuntiradi
""")
print("=== 6. Imzo tahlili ===\n")
sig = inspect.signature(jadval)
print(f" {'Parametr':<20} {'Kind':<22} {'Sukut'}")
print(" " + "─" * 62)
for nom, p in sig.parameters.items():
sukut = "—" if p.default is p.empty else repr(p.default)
if len(sukut) > 18:
sukut = sukut[:16] + "…"
print(f" {nom:<20} {p.kind.name:<22} {sukut}")
pozitsion = sum(1 for p in sig.parameters.values()
if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD))
nomli = sum(1 for p in sig.parameters.values() if p.kind is p.KEYWORD_ONLY)
print(f"\n Pozitsion: {pozitsion}, faqat nomli: {nomli}")
print("""
⭐ Dizayn qarorlari:
qatorlar, / — nom yopiq, kelajakda o'zgartirish mumkin
* — qolgan HAMMASI faqat nomli
bool parametrlar — hech qachon pozitsion bo'lolmaydi
Enum sozlamalar — True/False o'rniga ma'noli qiymatlar
Yangi parametr — istalgan vaqtda qo'shish xavfsiz
""")
print("\n=== 7. Kelajakdagi kengaytirish ===\n")
print(""" Yangi parametr qo'shish — hech narsani buzmaydi:
def jadval(qatorlar, /, *, ..., rang=None, eksport=None):
↑ yangi ↑ yangi
• Barcha mavjud chaqiruvlar ishlaydi
• Tartib muhim emas
• Sukut qiymat orqaga moslikni saqlaydi
Solishtiring — pozitsion bo'lganda:
def jadval(qatorlar, ustunlar, sarlavha, uslub, ..., rang, eksport)
↑ oxiriga majburiy
• Faqat oxiriga qo'shish mumkin
• 12-argument sifatida chaqirish — o'qib bo'lmaydi
""")Natijaning muhim qismi:
=== 2. Sarlavha va raqamlar ===
┌───────────────────────────────────────────┐
│ XODIMLAR RO'YXATI │
├─────┬─────────┬────────┬──────┬───────────┤
│ # │ ism │ bolim │ yosh │ maosh │
├─────┼─────────┼────────┼──────┼───────────┤
│ 1 │ Aziz │ IT │ 30 │ 7,000,000 │
│ 2 │ Bobur │ HR │ 25 │ 5,000,000 │
│ 3 │ Aziza │ IT │ 35 │ 8,500,000 │
│ 4 │ Dilnoza │ Moliya │ 28 │ — │
└─────┴─────────┴────────┴──────┴───────────┘
=== 6. Imzo tahlili ===
Parametr Kind Sukut
──────────────────────────────────────────────────────────────
qatorlar POSITIONAL_ONLY —
ustunlar KEYWORD_ONLY None
sarlavha KEYWORD_ONLY None
uslub KEYWORD_ONLY <Uslub.ODDIY: ('…
raqamlar KEYWORD_ONLY False
Pozitsion: 1, faqat nomli: 9Nima ko'rsatdi: 2.2, 2.3, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Nomli argument tartibi muhim" | Tartib erkin (lekin hisoblash — yozilish tartibida) |
"f(a=1, 2) ishlaydi" |
SyntaxError |
| "Parametr nomi ichki tafsilot" | Ochiq API — o'zgartirish buzuvchi |
| "Parametr qo'shish har doim xavfsiz" | Faqat oxiriga sukut bilan yoki * dan keyin |
"** kalitlari identifikator bo'lishi kerak" |
**kwargs bo'lsa — shart emas |
"f(**d1, **d2) birlashtiradi" |
Umumiy kalit bo'lsa TypeError |
| "Nomli argument sezilarli sekin" | ~20-40% — nanosekundlar |
| "Bool argument pozitsion bo'lsa bo'ladi" | Deyarli har doim o'qilishni buzadi |
"/ va * — ekzotik" |
Standart kutubxonada keng ishlatiladi |
6. Keng tarqalgan xatolar va yechimlari
1. Bool argument pozitsion
sarala(r, True) # ❌ True nima?
sarala(r, reverse=True) # ✅2. Nomli pozitsiondan oldin
f(a=1, 2) # ❌ SyntaxError
f(1, b=2) # ✅3. Ikki lug'atni ** bilan
f(**d1, **d2) # ❌ umumiy kalit bo'lsa
f(**{**d1, **d2}) # ✅
f(**(d1 | d2)) # ✅ 3.9+4. Parametr nomini o'zgartirish
def f(royxat): ... → def f(elementlar): ... # ⚠️ buzuvchi
def f(royxat, /): ... # ✅ nom yopiq5. Parametrni o'rtaga qo'shish
def f(a, yangi, b): ... # ❌ barcha chaqiruv buziladi
def f(a, b, *, yangi=None): ... # ✅6. Mos kelmaydigan kalitlarni uzatish
f(**sozlamalar) # ❌ ortiqcha kalit bo'lsa
xavfsiz_chaqir(f, **sozlamalar) # ✅ filtrlaydi7. Sukut qiymatni o'zgartirish
def f(a, rejim="r"): ... → def f(a, rejim="w"): ... # ⚠️ jimgina o'zgarish8. Ko'p pozitsion parametr
def f(a, b, c, d, e, g): ... # ❌
def f(a, /, *, b, c, d=1): ... # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 7.2-dars (o'tilgan): argument uzatish asoslari
- 7.3-dars (o'tilgan): sukut qiymatlar
- 7.5-dars:
*argsva**kwargs - 7.6-dars:
/va*— faqat pozitsion va faqat nomli - 8-qism:
dataclass, metodlar imzosi - 10-qism: dekoratorlar,
functools.wraps inspect: imzo tahlili,bind, validatsiya- API dizayni: semantik versiyalash, deprecation
8. Eng yaxshi amaliyotlar
Bool argumentni doim nom bilan.
f(x, faol=True).Ikkitadan ko'p bir xil turdagi argument — nom bilan.
kesim(m, boshi=0, oxiri=10).Muhim parametrlarni
*bilan nomli qiling. Yangi parametr qo'shish xavfsiz bo'ladi.Ichki nomlarni
/bilan yoping. Keyinchalik o'zgartirish mumkin bo'ladi.Parametr tartibi va nomlari — ochiq API. O'zgartirish — buzuvchi o'zgarish.
Yangi parametr faqat oxiriga sukut bilan yoki
*dan keyin.Eskirgan nom uchun
DeprecationWarning. Bir necha versiya qo'llab-quvvatlang.Bool o'rniga
Enum.Tekislash.MARKAZTrue, Falsedan aniqroq.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
def f(a, b, c=3): return a, b, c
def g(**kw): return kw
1. print(f(1, 2))
2. print(f(c=3, a=1, b=2))
3. print(f(1, b=2))
4. f(a=1, 2)
5. f(1, a=2)
6. f(1, 2, d=4)
7. print(f(**{"a": 1, "b": 2}))
8. print(f(1, **{"b": 2, "c": 30}))
9. f(**{"a": 1}, **{"a": 2})
10. print(g(**{"class": 1, "1-x": 2}))
11. g(**{1: "a"})
12. print(f(*[1, 2], **{"c": 3}))Javoblar
(1, 2, 3)(1, 2, 3)— tartib erkin(1, 2, 3)-
SyntaxError— nomli pozitsiondan oldin -
TypeError—aikki marta -
TypeError—dyo'q (1, 2, 3)(1, 2, 30)-
TypeError—aikki marta {'class': 1, '1-x': 2}—**kwargserkin-
TypeError: keywords must be strings (1, 2, 3)
Vazifa 2: Xatolarni tuzating
1. sarala(r, True, False)
2. f(a=1, 2)
3. ulan(**standart, **foydalanuvchi) # umumiy kalitlar bor
4. def f(a, yangi, b): ... # v2 da o'rtaga qo'shildi
5. def f(elementlar): ... # v1 da royxat edi
6. kesim(matn, 2, 6, 2)
7. f(**barcha_sozlamalar) # ortiqcha kalitlar
8. def yarat(nom, aktiv, korinadigan, tahrirlanadigan): ...Javoblar
1. sarala(r, reverse=True, barqaror=False)
2. f(1, b=2) yoki f(a=1, b=2)
3. ulan(**{**standart, **foydalanuvchi})
4. def f(a, b, *, yangi=None): ...
5. def f(elementlar=None, *, royxat=None): ... + DeprecationWarning
6. kesim(matn, boshi=2, oxiri=6, qadam=2)
7. xavfsiz_chaqir(f, **barcha_sozlamalar)
8. def yarat(nom, *, aktiv=True, korinadigan=True, tahrirlanadigan=True): ...Vazifa 3: API refaktoring
Berilgan funksiyani qayta loyihalang:
def yubor(kimga, mavzu, matn, html, muhim, nusxa, yashirin_nusxa,
ilova, kodlash, urinishlar, kutish):/va*bilan- Bool argumentlarni nomli qiling
- Bog'liq parametrlarni guruhlang (
dataclass) - Yangi parametr qo'shishni sinab ko'ring
inspectbilan imzoni tahlil qiling- Eski API uchun moslashtiruvchi (adapter) yozing
Vazifa 4: Xavfsiz chaqiruvchi
xavfsiz_chaqir ni kengaytiring:
- Pozitsion argumentlarni ham qo'llab-quvvatlasin
*argsbo'lsa to'g'ri ishlasin- Majburiy argument yetishmasa aniq xato bersin
- Tur ko'rsatkichlariga qarab tekshirsin
- Statistika: qaysi kalitlar ishlatildi/tashlandi
- Dekorator versiyasi:
@moslashuvchan
Vazifa 5: Deprecation vositasi
Dekorator yozing:
@eskirgan_parametr(eski="royxat", yangi="elementlar", versiya="2.0")
def f(elementlar): ...- Eski nomni yangi nomga yo'naltirsin
DeprecationWarningbersin- Ikkalasi berilsa xato bersin
- Bir necha eskirgan nomni qo'llab-quvvatlasin
- Docstring ga avtomatik eslatma qo'shsin
- Test yozing (
pytest.warns)
Vazifa 6: Imzo linteri
Vosita yozing:
- Modul funksiyalarini skanerlaydi
- Har biri uchun ogohlantirishlar:
- 4+ pozitsion parametr
- Bool parametr pozitsion bo'lishi mumkin
- O'zgaruvchan sukut
*yoki/yo'q- 8+ parametr
- Tuzatish taklifini beradi
- Hisobot chiqaradi (jadval)
ruffnatijasi bilan solishtiradi
Vazifa 7: O'ylash
Nega Python nomli argumentlarda tartibni erkin qildi, lekin pozitsion argument nomlidan keyin kelishini taqiqladi?
Javob
Chunki aks holda bog'lash noaniq bo'lardi.
Muammo:
def f(a, b, c): ...
f(a=1, 2, 3) # taqiqlanganAgar bunga ruxsat berilsa, 2 va 3 qaysi parametrga tegishli?
Ikki mumkin bo'lgan qoida:
Qoida A: "qolgan pozitsiyalar tartib bo'yicha"
f(a=1, 2, 3) # b=2, c=3?Lekin:
f(b=2, 1, 3) # a=1, c=3?
# yoki a=1, keyin 3 qaerga?Qoida B: "pozitsiyalar o'z o'rnida"
f(a=1, 2, 3) # 2 → 1-pozitsiya = a? ❌ konfliktHar ikki qoida ham chalkash va xatoga moyil.
Pythonning yechimi — sodda va aniq:
1. Pozitsion argumentlar CHAPDAN o'ngga parametrlarga bog'lanadi
2. Keyin nomli argumentlar nom bo'yicha bog'lanadi
3. Konflikt bo'lsa — xatoBu — bir yo'nalishli algoritm. Uni tushuntirish va amalga oshirish oson.
Nega nomlilar orasida tartib erkin:
Nomli argumentlar nom bo'yicha bog'lanadi — pozitsiya ahamiyatsiz:
f(c=3, a=1, b=2) # har biri o'z nomigaHech qanday noaniqlik yo'q. Cheklash ham foyda bermasdi.
Amaliy foyda:
# Muhim argumentlarni oldinga qo'yish
yubor(
kimga="aziz@mail.uz",
mavzu="Muhim",
...20 qator sozlama...
)
# Yoki mantiqiy guruhlash
chiz(
x=10, y=20, # koordinata
kenglik=100, balandlik=50, # o'lcham
rang="qizil", # ko'rinish
)O'quvchi uchun qulay tartibni tanlash mumkin.
Lekin hisoblash tartibi — yozilish tartibida:
f(c=birinchi(), a=ikkinchi())birinchi() avval chaqiriladi. Bu — muhim, chunki argumentlar yon ta'sirli bo'lishi mumkin:
f(b=stack.pop(), a=stack.pop()) # tartib muhim!Boshqa tillar:
| Til | Nomli argument | Aralash tartib |
|---|---|---|
| Python | Pozitsion oldin | |
| C# | Pozitsion oldin (7.2 gacha) | |
| Swift | Majburiy | Ta'rif tartibida! |
| Kotlin | Pozitsion oldin | |
| Ruby | (hash orqali) | Pozitsion oldin |
| JavaScript | (obyekt orqali) | — |
| Go | — | |
| C, Java | — |
Swift qiziq: u nomli argumentlarni majburiy qiladi va tartib ta'rif tartibida bo'lishi kerak:
func f(a: Int, b: Int) {}
f(a: 1, b: 2) // ✅
f(b: 2, a: 1) // ❌ xato!Swift falsafasi: "chaqiruv ta'rifga o'xshasin". Python falsafasi: "chaqiruvchiga erkinlik".
C# 7.2 dan keyin:
f(a: 1, 2, 3) // ✅ ruxsat — "non-trailing named arguments"C# qoida A ni tanladi: nomli argument o'z pozitsiyasida bo'lsa, keyingi pozitsionlar davom etadi. Bu — moslashuvchan, lekin qoida murakkabroq.
Xulosa: Python soddalikni tanladi. "Pozitsion oldin" qoidasi — bir jumlada tushuntiriladi va hech qanday chekka holat yaratmaydi. Bu — Zen ning "Sodda murakkabdan yaxshi" tamoyiliga mos.
Nimani mustahkamlaydi: 2.1, 2.2, 2.3-bo'limlar.
Xulosa
Bu darsda nomli argumentlarni chuqur o'rgandik.
Eng muhim uch fikr:
Bool argumentni doim nom bilan uzating.
f(x, True, False)— o'qib bo'lmaydi,f(x, faol=True, modal=False)— o'z-o'zini hujjatlaydi. Bu — nomli argumentlarning eng muhim qo'llanishi.Parametr tartibi VA nomlari — ochiq API. Tartibni o'zgartirish pozitsion chaqiruvlarni jimgina buzadi (xato yo'q, natija noto'g'ri). Nomni o'zgartirish nomli chaqiruvlarni buzadi.
/bilan nomni yoping,*bilan nomlini majburiy qiling.Qoida: pozitsion argumentlar nomlidan oldin. Nomlilar orasida tartib erkin, lekin hisoblash yozilish tartibida bo'ladi.
f(a=1, 2)—SyntaxError,f(1, a=2)—TypeError.
Keyingi darsda *args va **kwargs ni ko'ramiz: cheksiz argumentlar, ularni yo'naltirish va dekoratorlar uchun asos.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!