Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. * — faqat nomli argumentlar
- 2.2. / — faqat pozitsion argumentlar
- 2.3. To'liq shakl
- 2.4. Nega kerak — API dizayni
- 2.5. **kwargs bilan o'zaro ta'sir
- 2.6. Standart kutubxonada
- 2.7. Amaliy tavsiyalar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Ikki belgi
- Misol 2 — Nega kerak
- Misol 3 — Dizayn qarorlari
- Misol 4 — Amaliy: kutubxona 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.6-dars: Faqat pozitsion va faqat nomli argumentlar
7-QISM — FUNKSIYALAR · 6-dars
1. Kirish va motivatsiya
Standart kutubxona hujjatida g'alati belgilar uchraydi:
sorted(iterable, /, *, key=None, reverse=False)
len(obj, /)
dict.get(key, default=None, /)
print(*values, sep=' ', end='\n', file=None, flush=False)/ va * — bu nima?
Ular argumentlarni qanday uzatish mumkinligini boshqaradi:
def f(a, /, b, *, c):
...
f(1, 2, c=3) # ✅
f(1, b=2, c=3) # ✅
f(a=1, b=2, c=3) # ❌ a — faqat pozitsion
f(1, 2, 3) # ❌ c — faqat nomliNega bu kerak?
# Muammo 1: parametr nomini o'zgartirish API ni buzadi
def qayta_ishla(royxat): ...
qayta_ishla(royxat=[1, 2]) # foydalanuvchi shunday yozdi
def qayta_ishla(elementlar): ... # nom o'zgartirildi
qayta_ishla(royxat=[1, 2]) # ❌ buzildi
# Muammo 2: bool argument pozitsion
sarala(r, True) # ⚠️ True nima?Bu darsda:
/— faqat pozitsion parametrlar*— faqat nomli parametrlar- Nega kerak — API dizayni
- To'liq imzo shakli va barcha kombinatsiyalar
**kwargsbilan o'zaro ta'sir- Standart kutubxonada qo'llanishi
2. Nazariya — chuqur tushuntirish
2.1. * — faqat nomli argumentlar
* dan keyingi barcha parametrlar faqat nom bilan uzatiladi:
def f(a, b, *, c, d=4):
return a, b, c, d
f(1, 2, c=3) # ✅ (1, 2, 3, 4)
f(1, 2, c=3, d=40) # ✅
f(1, 2, 3) # ❌ TypeError: takes 2 positional arguments but 3 were givenIkki shakl:
def f(a, *, b): ... # * — qolgan pozitsion QABUL QILINMAYDI
def f(a, *args, b): ... # *args — qolgan pozitsion yig'iladiIkkalasida ham b — faqat nomli.
* dan keyin kamida bitta parametr:
def f(a, *): ... # ❌ SyntaxError: named arguments must follow bare *
def f(a, *, b): ... # ✅Sukut qiymatsiz ham bo'lishi mumkin:
def f(*, a): # a — majburiy va faqat nomli
...
f() # ❌ TypeError: missing 1 required keyword-only argument: 'a'
f(a=1) # ✅Bu — 7.3-darsdagi "sukutlar oxirida" qoidasidan istisno:
def f(a=1, b): ... # ❌ SyntaxError
def f(*, a=1, b): ... # ✅ ruxsat!Chunki * dan keyin tartib ahamiyatsiz — hammasi nom bilan uzatiladi.
2.2. / — faqat pozitsion argumentlar
Python 3.8+ (PEP 570). / dan oldingi parametrlar faqat pozitsiya bilan uzatiladi:
def f(a, b, /, c):
return a, b, c
f(1, 2, 3) # ✅
f(1, 2, c=3) # ✅
f(1, b=2, c=3) # ❌ TypeError: got some positional-only arguments passed as keyword arguments: 'b'
f(a=1, b=2, c=3) # ❌Parametr nomi ICHKI tafsilotga aylanadi:
def f(royxat, /): ...
# royxat nomini erkin o'zgartirish mumkin — hech kim unga tayanolmaydi / bitta bo'lishi kerak va * dan oldin:
def f(a, /, b, /, c): ... # ❌ SyntaxError
def f(a, *, b, /, c): ... # ❌ SyntaxError
def f(a, /, b, *, c): ... # ✅Tarixi: / dan oldin ham C da yozilgan funksiyalar shunday ishlardi:
len(obj=[1, 2]) # ❌ TypeError — Python 3.8 dan oldin hamLekin Pythonda yozish mumkin emas edi. PEP 570 buni tuzatdi.
2.3. To'liq shakl
def f(a, b, /, c, d, *args, e, f=1, **kwargs):
# ────┬─── ──┬─ ──┬── ──┬─── ────┬───
# faqat ikka qolgan faqat qolgan
# pozits. lasi pozits. nomli nomliBeshta guruh, qat'iy tartibda:
| # | Guruh | Sintaksis | inspect kind |
|---|---|---|---|
| 1 | Faqat pozitsion | / dan oldin |
POSITIONAL_ONLY |
| 2 | Pozitsion yoki nomli | Oddiy | POSITIONAL_OR_KEYWORD |
| 3 | Qolgan pozitsion | *args |
VAR_POSITIONAL |
| 4 | Faqat nomli | * dan keyin |
KEYWORD_ONLY |
| 5 | Qolgan nomli | **kwargs |
VAR_KEYWORD |
Barcha kombinatsiyalar:
def f(a): ... # 2
def f(a, /): ... # 1
def f(*, a): ... # 4
def f(a, /, b): ... # 1, 2
def f(a, *, b): ... # 2, 4
def f(a, /, *, b): ... # 1, 4 ⭐ eng qat'iy
def f(a, /, b, *, c): ... # 1, 2, 4
def f(*args): ... # 3
def f(**kwargs): ... # 5
def f(*args, **kwargs): ... # 3, 5
def f(a, /, b, *args, c, **kw): ... # hammasi2.4. Nega kerak — API dizayni
1. / — parametr nomini yashirish:
# Nomsiz
def qayta_ishla(royxat):
return len(royxat)
qayta_ishla(royxat=[1, 2]) # foydalanuvchi shunday yozdi
# Nom o'zgardi — API buzildi
def qayta_ishla(elementlar): ...
qayta_ishla(royxat=[1, 2]) # ❌# / bilan
def qayta_ishla(royxat, /):
return len(royxat)
qayta_ishla(royxat=[1, 2]) # ❌ darhol — nom API emas
qayta_ishla([1, 2]) # ✅ yagona yo'l
# Endi nomni erkin o'zgartirish mumkin
def qayta_ishla(elementlar, /): ... # ✅ hech narsa buzilmaydi2. * — o'qilishni majburlash:
# * siz
def sarala(r, teskari=False, barqaror=True): ...
sarala(data, True, False) # ⚠️ nima nima?
# * bilan
def sarala(r, *, teskari=False, barqaror=True): ...
sarala(data, True, False) # ❌ darhol
sarala(data, teskari=True) # ✅ yagona yo'l3. * — kelajakda parametr qo'shish xavfsiz:
def f(a, *, b=1, c=2): ...
# Yangi parametr qo'shish — hech narsa buzilmaydi
def f(a, *, b=1, c=2, d=3): ... # ✅
# Tartib ham muhim emas
def f(a, *, d=3, b=1, c=2): ... # ✅4. / — **kwargs bilan nom to'qnashuvi:
def f(nom, **kwargs):
return nom, kwargs
f("x", nom="y") # ❌ multiple values for argument 'nom'/ bilan:
def f(nom, /, **kwargs):
return nom, kwargs
f("x", nom="y") # ✅ ('x', {'nom': 'y'})Bu — dict va boshqa konteynerlar uchun muhim:
d = dict(self="x") # ✅ ishlaydi, chunki dict.__init__ da / bor5. / — pozitsion tezroq:
f(1, 2, 3) # ~60 ns
f(a=1, b=2, c=3) # ~85 nsTor sikllarda (masalan key= funksiyasi) bu sezilishi mumkin.
2.5. **kwargs bilan o'zaro ta'sir
Muammo — nom to'qnashuvi:
def sozla(nom, **sozlamalar):
return nom, sozlamalar
sozla("test", nom="x") # ❌ TypeError
sozla("test", debug=True) # ✅Foydalanuvchi nom kalitini uzata olmaydi.
Yechim — /:
def sozla(nom, /, **sozlamalar):
return nom, sozlamalar
sozla("test", nom="x") # ✅ ('test', {'nom': 'x'})Standart kutubxonada:
dict(self=1, dict=2) # ✅ — dict.__init__(self, /, **kwargs)
namedtuple("N", ["a"])._replace(self=1) # maxsus ishlov Metodlarda self:
class A:
def metod(self, nom): ...
a.metod(self=1) # ❌ multiple values for argument 'self'
class A:
def metod(self, /, **kwargs): ...
a.metod(self=1) # ✅CPython ichki turlarida self doim / dan oldin.
2.6. Standart kutubxonada
import inspect
inspect.signature(sorted)
# (iterable, /, *, key=None, reverse=False)Naqshlar:
# 1. Asosiy argument — pozitsion, sozlamalar — nomli
sorted(iterable, /, *, key=None, reverse=False)
sum(iterable, /, start=0)
min(arg1, arg2, *args, key=None)
# 2. Hammasi pozitsion (oddiy funksiyalar)
len(obj, /)
abs(x, /)
pow(base, exp, mod=None)
isinstance(obj, class_or_tuple, /)
# 3. *args dan keyin — hammasi nomli
print(*values, sep=' ', end='\n', file=None, flush=False)
max(*args, key=None, default=...)
# 4. Ko'p ixtiyoriy sozlama
open(file, mode='r', buffering=-1, encoding=None, errors=None,
newline=None, closefd=True, opener=None)
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, indent=None, ...) Ba'zi funksiyalarda / yo'q (eskirgan):
open(file="x.txt") # ✅ ishlaydi — `file` nomi APIYangi kodda / qo'shish orqaga moslikni buzardi.
inspect bilan tekshirish:
for f in [len, sorted, print, open]:
try:
print(f.__name__, inspect.signature(f))
except ValueError:
print(f.__name__, "(imzo yo'q)")2.7. Amaliy tavsiyalar
Yangi funksiya uchun sukut naqsh:
def f(asosiy, /, *, sozlama1=None, sozlama2=None):
# ↑ nom yopiq ↑ hammasi nomliBu:
- Asosiy parametr nomini keyinchalik o'zgartirish mumkin
- Yangi sozlama qo'shish xavfsiz
- Chaqiruv o'z-o'zini hujjatlaydi
Qachon / ishlatish:
| Holat | / kerakmi |
|---|---|
Nomi ma'nosiz (obj, x, self) |
Ha |
**kwargs bilan to'qnashuv xavfi |
Ha |
Matematik funksiya (abs, pow) |
Ha |
| Nomi ma'noli va foydali | Yo'q |
| Foydalanuvchi nom bilan yozishi mumkin | Yo'q |
Qachon * ishlatish:
| Holat | * kerakmi |
|---|---|
| Bool parametr | Doim |
| 3+ ixtiyoriy sozlama | Ha |
| Kelajakda kengaytiriladi | Ha |
| Ma'nosi kontekstsiz noaniq | Ha |
| 1-2 aniq argument | Yo'q |
Orqaga moslik:
# Mavjud funksiyaga / yoki * qo'shish — BUZUVCHI
def f(a, b): ... # v1
def f(a, /, b): ... # v2 — f(a=1, b=2) buziladi
def f(a, *, b): ... # v2 — f(1, 2) buziladiShuning uchun boshidan to'g'ri loyihalang.
3. Tez ma'lumotnoma
Ikki belgi
def f(a, /, b, *, c):
↑ ↑
/ * dan
dan keyin —
oldin — FAQAT
FAQAT NOMLI
POZITSION
f(1, 2, c=3) ✅
f(1, b=2, c=3) ✅
f(a=1, ...) ❌ a faqat pozitsion
f(1, 2, 3) ❌ c faqat nomliTo'liq shakl
def f(a, b, /, c, d, *args, e, f=1, **kwargs)
───── ──── ───── ────── ────────
1 2 3 4 5
1 POSITIONAL_ONLY / dan oldin
2 POSITIONAL_OR_KEYWORD oddiy
3 VAR_POSITIONAL *args
4 KEYWORD_ONLY * dan keyin
5 VAR_KEYWORD **kwargsNega kerak
/ → parametr NOMI ichki tafsilot (keyinchalik o'zgartirish mumkin)
/ → **kwargs bilan nom to'qnashuvi yo'q
/ → pozitsion chaqiruv tezroq
* → bool argument o'qiladigan bo'ladi
* → yangi parametr qo'shish xavfsiz
* → tartib muhim emas
* → sukutsiz parametr sukutlidan keyin bo'lishi mumkinSintaksis qoidalari
def f(a, *): ... ❌ * dan keyin kamida bitta
def f(a, /, b, /): ... ❌ bitta /
def f(a, *, b, /): ... ❌ / — * dan OLDIN
def f(*, a=1, b): ... ✅ * dan keyin tartib erkinTavsiya etilgan naqsh
def f(asosiy, /, *, sozlama1=None, sozlama2=None):Mavjud funksiyaga qo'shish — BUZUVCHI o'zgarish
4. Batafsil misollar
Misol 1 — Ikki belgi
"""/ va * — to'liq namoyish."""
import inspect
print("=== 1. * — faqat nomli ===")
def f_yulduz(a, b, *, c, d=4):
return a, b, c, d
print(f" def f(a, b, *, c, d=4):\n")
CHAQIRUVLAR = [
"f_yulduz(1, 2, c=3)",
"f_yulduz(1, 2, c=3, d=40)",
"f_yulduz(1, b=2, c=3)",
"f_yulduz(a=1, b=2, c=3)",
"f_yulduz(1, 2, 3)",
"f_yulduz(1, 2, 3, 4)",
"f_yulduz(1, 2)",
]
for kod in CHAQIRUVLAR:
try:
natija = f"✅ {eval(kod)}"
except TypeError as x:
natija = f"❌ {x}"
print(f" {kod:<32} {natija}")
print("\n=== 2. / — faqat pozitsion ===")
def f_slesh(a, b, /, c):
return a, b, c
print(f" def f(a, b, /, c):\n")
CHAQIRUVLAR = [
"f_slesh(1, 2, 3)",
"f_slesh(1, 2, c=3)",
"f_slesh(1, b=2, c=3)",
"f_slesh(a=1, b=2, c=3)",
]
for kod in CHAQIRUVLAR:
try:
natija = f"✅ {eval(kod)}"
except TypeError as x:
natija = f"❌ {x}"
print(f" {kod:<32} {natija}")
print("\n=== 3. Ikkalasi birga ===")
def f_ikkala(a, /, b, *, c):
return a, b, c
print(f" def f(a, /, b, *, c):")
print(f" ↑ ↑ ↑")
print(f" │ │ └─ faqat nomli")
print(f" │ └─────── ikkalasi ham")
print(f" └───────────── faqat pozitsion\n")
CHAQIRUVLAR = [
"f_ikkala(1, 2, c=3)",
"f_ikkala(1, b=2, c=3)",
"f_ikkala(a=1, b=2, c=3)",
"f_ikkala(1, 2, 3)",
]
for kod in CHAQIRUVLAR:
try:
natija = f"✅ {eval(kod)}"
except TypeError as x:
natija = f"❌ {str(x)[:52]}"
print(f" {kod:<28} {natija}")
print("\n=== 4. Barcha kombinatsiyalar ===")
SHAKLLAR = [
("def f(a)", "def _f1(a): pass"),
("def f(a, /)", "def _f2(a, /): pass"),
("def f(*, a)", "def _f3(*, a): pass"),
("def f(a, /, b)", "def _f4(a, /, b): pass"),
("def f(a, *, b)", "def _f5(a, *, b): pass"),
("def f(a, /, *, b)", "def _f6(a, /, *, b): pass"),
("def f(a, /, b, *, c)", "def _f7(a, /, b, *, c): pass"),
("def f(*args)", "def _f8(*args): pass"),
("def f(**kwargs)", "def _f9(**kwargs): pass"),
("def f(a, /, b, *args, c, **kw)",
"def _f10(a, /, b, *args, c, **kw): pass"),
]
print(f" {'Shakl':<32} {'Imzo'}")
print(" " + "─" * 68)
for nom, kod in SHAKLLAR:
exec(kod)
fn = eval(kod.split("(")[0].replace("def ", ""))
print(f" {nom:<32} {inspect.signature(fn)}")
print("\n=== 5. Sintaksis xatolari ===")
XATOLAR = [
"def f(a, *): pass",
"def f(a, /, b, /): pass",
"def f(a, *, b, /): pass",
"def f(/, a): pass",
"def f(*, /): pass",
"def f(a, *args, /): pass",
]
for kod in XATOLAR:
try:
exec(kod)
print(f" ✅ {kod}")
except SyntaxError as x:
print(f" ❌ {kod:<34} {x.msg}")
print("\n=== 6. ⭐ * dan keyin tartib erkin ===")
print(f" Oddiy parametrlarda sukutlar OXIRIDA:")
try:
exec("def f(a=1, b): pass")
except SyntaxError as x:
print(f" def f(a=1, b): pass → ❌ {x.msg}")
print(f"\n * dan keyin — tartib ERKIN:")
def f_erkin(*, a=1, b, c=3, d):
return a, b, c, d
print(f" def f(*, a=1, b, c=3, d): pass → ✅")
print(f" Imzo: {inspect.signature(f_erkin)}")
print(f" f(b=2, d=4) = {f_erkin(b=2, d=4)}")
print("""
⭐ Sabab: * dan keyin hammasi NOM bilan uzatiladi,
shuning uchun tartib ahamiyatsiz.
""")
print("\n=== 7. inspect bilan tahlil ===")
def toliq(a, b, /, c, d=4, *args, e, f=6, **kwargs):
...
sig = inspect.signature(toliq)
print(f" {sig}\n")
GURUHLAR = {}
for nom, p in sig.parameters.items():
GURUHLAR.setdefault(p.kind, []).append(nom)
IZOHLAR = {
inspect.Parameter.POSITIONAL_ONLY: "/ dan oldin",
inspect.Parameter.POSITIONAL_OR_KEYWORD: "oddiy",
inspect.Parameter.VAR_POSITIONAL: "*args",
inspect.Parameter.KEYWORD_ONLY: "* dan keyin",
inspect.Parameter.VAR_KEYWORD: "**kwargs",
}
print(f" {'Kind':<24} {'Parametrlar':<16} {'Sintaksis'}")
print(" " + "─" * 56)
for kind in inspect.Parameter.__dict__.values():
if not isinstance(kind, inspect._ParameterKind):
continue
nomlar = GURUHLAR.get(kind, [])
if nomlar:
print(f" {kind.name:<24} {str(nomlar):<16} {IZOHLAR[kind]}")
print("\n=== 8. Standart kutubxonada ===")
FUNKSIYALAR = [len, abs, sorted, print, sum, max, min, round, isinstance,
open, repr, hash]
print(f" {'Funksiya':<14} {'Imzo'}")
print(" " + "─" * 70)
for f in FUNKSIYALAR:
try:
print(f" {f.__name__:<14} {inspect.signature(f)}")
except (ValueError, TypeError):
print(f" {f.__name__:<14} (imzo o'qib bo'lmadi)")
print(f"\n Metodlar:")
for tur, metodlar in [(str, ["find", "replace", "split"]),
(dict, ["get", "pop", "setdefault"]),
(list, ["append", "insert", "index"])]:
for m in metodlar:
f = getattr(tur, m)
try:
print(f" {tur.__name__}.{m:<12} {inspect.signature(f)}")
except (ValueError, TypeError):
print(f" {tur.__name__}.{m:<12} (imzo yo'q)")Natijaning muhim qismi:
=== 2. / — faqat pozitsion ===
def f(a, b, /, c):
f_slesh(1, 2, 3) ✅ (1, 2, 3)
f_slesh(1, 2, c=3) ✅ (1, 2, 3)
f_slesh(1, b=2, c=3) ❌ f_slesh() got some positional-only
arguments passed as keyword arguments: 'b'
=== 5. Sintaksis xatolari ===
❌ def f(a, *): pass named arguments must follow bare *
❌ def f(a, /, b, /): pass / may appear only once
❌ def f(a, *, b, /): pass / must be ahead of *
❌ def f(/, a): pass at least one argument must precede /
=== 8. Standart kutubxonada ===
Funksiya Imzo
──────────────────────────────────────────────────────────────────────
len (obj, /)
abs (x, /)
sorted (iterable, /, *, key=None, reverse=False)
sum (iterable, /, start=0)
round (number, ndigits=None)
isinstance (obj, class_or_tuple, /)Nima ko'rsatdi: 2.1, 2.2, 2.3, 2.6-bo'limlar.
Misol 2 — Nega kerak
"""/ va * ning amaliy foydasi."""
import inspect
import warnings
print("=== 1. / — parametr nomini yashirish ===")
def qayta_ishla_v1(royxat):
"""v1 — nom ochiq."""
return len(royxat)
def qayta_ishla_v2(elementlar):
"""v2 — nom o'zgartirildi."""
return len(elementlar)
def himoyalangan_v1(royxat, /):
"""v1 — nom YOPIQ."""
return len(royxat)
def himoyalangan_v2(elementlar, /):
"""v2 — nom o'zgartirildi."""
return len(elementlar)
print(f" Foydalanuvchi kodi: f(royxat=[1, 2])\n")
print(f" {'Funksiya':<24} {'Natija'}")
print(" " + "─" * 56)
for nom, f in [("qayta_ishla_v1", qayta_ishla_v1),
("qayta_ishla_v2", qayta_ishla_v2),
("himoyalangan_v1", himoyalangan_v1),
("himoyalangan_v2", himoyalangan_v2)]:
try:
natija = f"✅ {f(royxat=[1, 2])}"
except TypeError as x:
natija = f"❌ {str(x)[:40]}"
print(f" {nom:<24} {natija}")
print(f"\n Pozitsion chaqiruv: f([1, 2])\n")
for nom, f in [("qayta_ishla_v2", qayta_ishla_v2),
("himoyalangan_v2", himoyalangan_v2)]:
print(f" {nom:<24} ✅ {f([1, 2])}")
print("""
⭐ / bilan:
• Foydalanuvchi nomni ishlata OLMAYDI (darhol xato)
• Shuning uchun nomni keyinchalik o'zgartirish XAVFSIZ
• Parametr nomi — ichki tafsilot
""")
print("\n=== 2. * — bool argumentlarni majburiy nomlash ===")
def sarala_v1(r, teskari=False, barqaror=True, tozala=False):
"""* siz — pozitsion mumkin."""
return f"sarala(teskari={teskari}, barqaror={barqaror}, tozala={tozala})"
def sarala_v2(r, *, teskari=False, barqaror=True, tozala=False):
"""* bilan — faqat nomli."""
return f"sarala(teskari={teskari}, barqaror={barqaror}, tozala={tozala})"
print(f" ⚠️ * siz:")
print(f" sarala_v1(r, True, False, True)")
print(f" → {sarala_v1([], True, False, True)}")
print(f" ⚠️ Chaqiruvni o'qib nima nimaligini bilib bo'lmaydi\n")
print(f" ✅ * bilan:")
try:
sarala_v2([], True, False, True)
except TypeError as x:
print(f" sarala_v2(r, True, False, True) → ❌ {str(x)[:56]}")
print(f" sarala_v2(r, teskari=True, tozala=True)")
print(f" → {sarala_v2([], teskari=True, tozala=True)}")
print("\n=== 3. * — kelajakda kengaytirish ===")
def hisobla_v1(malumot, *, aniqlik=2, birlik="so'm"):
return f"hisobla(aniqlik={aniqlik}, birlik={birlik})"
def hisobla_v2(malumot, *, birlik="so'm", aniqlik=2, yaxlitlash="yuqoriga"):
"""Yangi parametr qo'shildi VA tartib o'zgardi."""
return (f"hisobla(aniqlik={aniqlik}, birlik={birlik}, "
f"yaxlitlash={yaxlitlash})")
print(f" v1: def f(malumot, *, aniqlik=2, birlik=\"so'm\")")
print(f" v2: def f(malumot, *, birlik=\"so'm\", aniqlik=2, yaxlitlash=...)")
print(f" ↑ yangi parametr + tartib o'zgardi\n")
ESKI_CHAQIRUVLAR = [
("f(d)", {}),
("f(d, aniqlik=3)", {"aniqlik": 3}),
("f(d, birlik='USD')", {"birlik": "USD"}),
("f(d, aniqlik=0, birlik='€')", {"aniqlik": 0, "birlik": "€"}),
]
print(f" {'Eski chaqiruv':<30} {'v1':<14} {'v2'}")
print(" " + "─" * 62)
for kod, kwargs in ESKI_CHAQIRUVLAR:
a = "✅" if hisobla_v1([], **kwargs) else "❌"
b = "✅" if hisobla_v2([], **kwargs) else "❌"
print(f" {kod:<30} {a:<14} {b}")
print(f"""
⭐ Barcha eski chaqiruvlar ishlaydi — chunki
* dan keyin TARTIB ahamiyatsiz.
""")
print("\n=== 4. / — **kwargs bilan to'qnashuv ===")
def sozla_yomon(nom, **sozlamalar):
return nom, sozlamalar
def sozla_yaxshi(nom, /, **sozlamalar):
return nom, sozlamalar
print(f" def f(nom, **sozlamalar) — / siz")
print(f" def f(nom, /, **sozlamalar) — / bilan\n")
SINOVLAR = [
("f('x', debug=True)", ("x",), {"debug": True}),
("f('x', nom='y')", ("x",), {"nom": "y"}),
]
print(f" {'Chaqiruv':<24} {'/ siz':<28} {'/ bilan'}")
print(" " + "─" * 66)
for kod, args, kwargs in SINOVLAR:
try:
a = str(sozla_yomon(*args, **kwargs))
except TypeError as x:
a = f"❌ {str(x)[:24]}"
try:
b = str(sozla_yaxshi(*args, **kwargs))
except TypeError as x:
b = f"❌ {str(x)[:24]}"
print(f" {kod:<24} {a:<28} {b}")
print(f"\n Standart kutubxonada:")
print(f" dict(self=1, dict=2) = {dict(self=1, dict=2)}")
print(f" ⭐ dict.__init__(self, /, **kwargs) — shuning uchun ishlaydi")
print(f"\n Metodlarda ham:")
class A:
def yomon(self, nom):
return nom
def yaxshi(self, /, **kwargs):
return kwargs
a = A()
try:
a.yomon(self=1, nom="x")
except TypeError as x:
print(f" a.yomon(self=1, nom='x') → ❌ {str(x)[:44]}")
print(f" a.yaxshi(self=1, nom='x') → ✅ {a.yaxshi(self=1, nom='x')}")
print("\n=== 5. Tezlik ===")
import timeit
def f3(a, b, c):
return a + b + c
def f3_slesh(a, b, c, /):
return a + b + c
SOZLASH = "from __main__ import f3, f3_slesh"
SINOVLAR = [
("f(1, 2, 3)", "f3(1, 2, 3)"),
("f(a=1, b=2, c=3)", "f3(a=1, b=2, c=3)"),
("f_slesh(1, 2, 3)", "f3_slesh(1, 2, 3)"),
]
natijalar = []
for nom, kod in SINOVLAR:
vaqt = timeit.timeit(kod, setup=SOZLASH, number=5_000_000)
natijalar.append((nom, vaqt))
eng_tez = min(v for _, v in natijalar)
print(f" 5M chaqiruv:\n")
print(f" {'Chaqiruv':<24} {'Vaqt':>9} {'Nisbat':>9}")
print(" " + "─" * 46)
for nom, vaqt in natijalar:
print(f" {nom:<24} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")
print("""
⭐ Pozitsion chaqiruv tezroq (nom qidiruvi yo'q).
Farq kichik, lekin tor sikllarda (key=, filter=) sezilishi mumkin.
""")
print("\n=== 6. ⚠️ Orqaga moslik ===")
print("""
Mavjud funksiyaga / yoki * qo'shish — BUZUVCHI o'zgarish:
v1: def f(a, b): ...
f(1, 2) ✅
f(a=1, b=2) ✅
v2: def f(a, /, b): ...
f(1, 2) ✅
f(a=1, b=2) ❌ BUZILDI
v3: def f(a, *, b): ...
f(1, 2) ❌ BUZILDI
f(a=1, b=2) ✅
⭐ Shuning uchun BOSHIDAN to'g'ri loyihalang.
""")
print(f" Bosqichma-bosqich o'tish (deprecation):\n")
def f_otish(a, b=None, /, *, yangi_b=None):
"""Eski pozitsion `b` ni vaqtincha qo'llab-quvvatlaydi."""
if b is not None:
warnings.warn(
"Ikkinchi pozitsion argument eskirgan, yangi_b= ishlating",
DeprecationWarning, stacklevel=2,
)
yangi_b = b
return a, yangi_b
with warnings.catch_warnings(record=True) as ogohlar:
warnings.simplefilter("always")
print(f" f_otish(1, 2) → {f_otish(1, 2)}")
print(f" f_otish(1, yangi_b=2) → {f_otish(1, yangi_b=2)}")
for o in ogohlar:
print(f" ⚠️ {o.category.__name__}: {o.message}")Natijaning muhim qismi:
=== 1. / — parametr nomini yashirish ===
Foydalanuvchi kodi: f(royxat=[1, 2])
Funksiya Natija
────────────────────────────────────────────────────────
qayta_ishla_v1 ✅ 2
qayta_ishla_v2 ❌ qayta_ishla_v2() got an unexpected
himoyalangan_v1 ❌ himoyalangan_v1() got some positional
himoyalangan_v1 ❌ himoyalangan_v1() got some positional-on
=== 4. / — **kwargs bilan to'qnashuv ===
Chaqiruv / siz / bilan
──────────────────────────────────────────────────────────────────
f('x', debug=True) ('x', {'debug': True}) ('x', {'debug': True})
f('x', nom='y') ❌ sozla_yomon() got multip ('x', {'nom': 'y'})
dict(self=1, dict=2) = {'self': 1, 'dict': 2}Nima ko'rsatdi: 2.4, 2.5-bo'limlar.
Misol 3 — Dizayn qarorlari
"""Qachon / va * ishlatish."""
import inspect
from dataclasses import dataclass
from enum import Enum
print("=== 1. Naqsh: asosiy + sozlamalar ===")
def formatla(matn, /, *, kenglik=80, tekislash="chap",
toldirish=" ", kesish=True):
"""⭐ Tavsiya etilgan naqsh."""
BELGILAR = {"chap": "<", "markaz": "^", "ong": ">"}
if kesish and len(matn) > kenglik:
matn = matn[:kenglik - 1] + "…"
return f"{matn:{toldirish}{BELGILAR[tekislash]}{kenglik}}"
print(f" def formatla(matn, /, *, kenglik=80, tekislash='chap', ...):\n")
NAMUNALAR = [
("formatla('Salom', kenglik=20)", {"kenglik": 20}),
("formatla('Salom', kenglik=20, tekislash='markaz')",
{"kenglik": 20, "tekislash": "markaz"}),
("formatla('Salom', kenglik=20, tekislash='ong', toldirish='.')",
{"kenglik": 20, "tekislash": "ong", "toldirish": "."}),
]
for kod, kwargs in NAMUNALAR:
print(f" {kod}")
print(f" → [{formatla('Salom', **kwargs)}]")
print(f"\n Xatolar:")
for kod, args, kwargs in [
("formatla(matn='x')", (), {"matn": "x"}),
("formatla('x', 20)", ("x", 20), {}),
]:
try:
formatla(*args, **kwargs)
natija = "✅"
except TypeError as x:
natija = f"❌ {str(x)[:48]}"
print(f" {kod:<24} {natija}")
print("\n=== 2. Qachon / kerak ===")
QARORLAR = [
("obj, x, self, iterable", "✅ Ha", "nomi ma'nosiz"),
("**kwargs bilan", "✅ Ha", "nom to'qnashuvi xavfi"),
("abs(x), len(obj)", "✅ Ha", "matematik/oddiy"),
("fayl_yoli, foydalanuvchi_id", "❌ Yo'q", "nomi ma'noli"),
("kenglik, balandlik", "❌ Yo'q", "nom bilan o'qiladi"),
("konfiguratsiya", "❌ Yo'q", "nom foydali"),
]
print(f" {'Parametr':<28} {'/ kerakmi':<10} Sabab")
print(" " + "─" * 62)
for parametr, qaror, sabab in QARORLAR:
print(f" {parametr:<28} {qaror:<10} {sabab}")
print("\n=== 3. Qachon * kerak ===")
QARORLAR = [
("bool parametr", "✅ DOIM", "True/False o'qib bo'lmaydi"),
("3+ ixtiyoriy sozlama", "✅ Ha", "tartibni eslash qiyin"),
("kelajakda kengayadi", "✅ Ha", "yangi parametr xavfsiz"),
("noaniq ma'no (3, 5)", "✅ Ha", "nom kerak"),
("f(a, b) — 2 ta aniq", "❌ Yo'q", "ortiqcha shovqin"),
("qosh(x, y)", "❌ Yo'q", "ma'no ravshan"),
]
print(f" {'Holat':<28} {'* kerakmi':<10} Sabab")
print(" " + "─" * 62)
for holat, qaror, sabab in QARORLAR:
print(f" {holat:<28} {qaror:<10} {sabab}")
print("\n=== 4. Bir funksiyani uch xil loyihalash ===")
def yubor_v1(kimga, mavzu, matn, html, muhim, nusxa, ilova):
"""❌ Hammasi pozitsion."""
return "yuborildi"
def yubor_v2(kimga, mavzu, matn, *, html=False, muhim=False,
nusxa=(), ilova=()):
"""⚠️ Yaxshiroq — sozlamalar nomli."""
return "yuborildi"
def yubor_v3(kimga, mavzu, matn, /, *, html=False, muhim=False,
nusxa=(), ilova=()):
"""✅ Eng yaxshi — asosiy nomlar ham yopiq."""
return "yuborildi"
print(f" v1: def yubor(kimga, mavzu, matn, html, muhim, nusxa, ilova)")
print(f" v2: def yubor(kimga, mavzu, matn, *, html=False, ...)")
print(f" v3: def yubor(kimga, mavzu, matn, /, *, html=False, ...)\n")
CHAQIRUVLAR = [
('yubor("a@x", "Mavzu", "Matn", True, False, (), ())',
("a@x", "Mavzu", "Matn", True, False, (), ()), {}),
('yubor("a@x", "Mavzu", "Matn", html=True)',
("a@x", "Mavzu", "Matn"), {"html": True}),
('yubor(kimga="a@x", mavzu="M", matn="T")',
(), {"kimga": "a@x", "mavzu": "M", "matn": "T"}),
]
print(f" {'Chaqiruv':<50} {'v1':<5} {'v2':<5} {'v3'}")
print(" " + "─" * 70)
for kod, args, kwargs in CHAQIRUVLAR:
natijalar = []
for f in [yubor_v1, yubor_v2, yubor_v3]:
try:
f(*args, **kwargs)
natijalar.append("✅")
except TypeError:
natijalar.append("❌")
print(f" {kod[:48]:<50} {natijalar[0]:<5} {natijalar[1]:<5} {natijalar[2]}")
print("""
⭐ v3 yagona to'g'ri chaqiruv shaklini majburlaydi:
yubor("a@x", "Mavzu", "Matn", html=True, muhim=False)
• Asosiy uchtasi — tartib bilan (tabiiy o'qiladi)
• Sozlamalar — nom bilan (o'z-o'zini hujjatlaydi)
• Nomlarni keyinchalik o'zgartirish mumkin
""")
print("\n=== 5. Sinf metodlarida ===")
class Hujjat:
def __init__(self, matn, /, *, kodlash="utf-8", til="uz"):
self.matn = matn
self.kodlash = kodlash
self.til = til
def saqla(self, yol, /, *, formatlash=True, zaxira=False):
return f"saqla({yol}, formatlash={formatlash}, zaxira={zaxira})"
def almashtir(self, eski, yangi, /, *, hammasi=True, registr=False):
return f"almashtir({eski!r}→{yangi!r}, hammasi={hammasi})"
@staticmethod
def yukla(yol, /, **sozlamalar):
"""/ bilan — 'yol' kaliti sozlamalar ichida bo'lishi mumkin."""
return f"yukla({yol}, {sozlamalar})"
h = Hujjat("Salom dunyo", til="en")
print(f" h = Hujjat('Salom dunyo', til='en')\n")
print(f" {h.saqla('fayl.txt', zaxira=True)}")
print(f" {h.almashtir('a', 'b', registr=True)}")
print(f" {Hujjat.yukla('x.txt', yol='boshqa', kodlash='cp1251')}")
print(f"\n ⭐ yukla da / bo'lgani uchun 'yol' kaliti sozlamalarga tushdi")
print(f"\n Imzolar:")
for nom in ["__init__", "saqla", "almashtir", "yukla"]:
f = getattr(Hujjat, nom)
print(f" {nom:<12} {inspect.signature(f)}")
print("\n=== 6. Imzo sifatini baholash ===")
def imzoni_baholash(f) -> tuple[int, list[str]]:
"""Imzo dizayni sifatini baholaydi (0-100)."""
try:
sig = inspect.signature(f)
except (ValueError, TypeError):
return 0, ["imzo o'qib bo'lmadi"]
ps = list(sig.parameters.values())
if not ps:
return 100, []
ball = 100
ogohlar = []
pozitsion = [p for p in ps if p.kind is p.POSITIONAL_OR_KEYWORD]
faqat_poz = [p for p in ps if p.kind is p.POSITIONAL_ONLY]
faqat_nomli = [p for p in ps if p.kind is p.KEYWORD_ONLY]
# Bool parametr pozitsion bo'lishi mumkin
bool_poz = [p.name for p in pozitsion if isinstance(p.default, bool)]
if bool_poz:
ball -= 30
ogohlar.append(f"bool pozitsion bo'lishi mumkin: {bool_poz}")
# Ko'p pozitsion
jami_poz = len(pozitsion) + len(faqat_poz)
if jami_poz > 4:
ball -= 20
ogohlar.append(f"{jami_poz} pozitsion parametr (4 dan ko'p)")
# Ko'p sukut qiymatli pozitsion
sukutli_poz = [p.name for p in pozitsion if p.default is not p.empty]
if len(sukutli_poz) > 2:
ball -= 15
ogohlar.append(f"{len(sukutli_poz)} sukutli pozitsion — * qo'shing")
# * yo'q va sozlamalar bor
if not faqat_nomli and len(sukutli_poz) >= 2:
ball -= 15
ogohlar.append("* yo'q — sozlamalar pozitsion uzatilishi mumkin")
# O'zgaruvchan sukut
ozgaruvchan = [p.name for p in ps
if isinstance(p.default, (list, dict, set))]
if ozgaruvchan:
ball -= 25
ogohlar.append(f"o'zgaruvchan sukut: {ozgaruvchan}")
return max(0, ball), ogohlar
NAMUNALAR = [
yubor_v1, yubor_v2, yubor_v3, formatla,
sorted, len, print,
]
def yomon_namuna(a, b, c, d, e, tozala=True, qatiy=False, r=[]):
...
NAMUNALAR.append(yomon_namuna)
print(f" {'Funksiya':<16} {'Ball':>6} Ogohlantirishlar")
print(" " + "─" * 66)
for f in NAMUNALAR:
nom = getattr(f, "__name__", str(f))
ball, ogohlar = imzoni_baholash(f)
belgi = "✅" if ball >= 85 else ("⚠️" if ball >= 60 else "❌")
print(f" {belgi} {nom:<14} {ball:>5} {ogohlar[0] if ogohlar else '—'}")
for o in ogohlar[1:]:
print(f" {'':<22} {o}")Natijaning muhim qismi:
=== 4. Bir funksiyani uch xil loyihalash ===
Chaqiruv v1 v2 v3
──────────────────────────────────────────────────────────────────────
yubor("a@x", "Mavzu", "Matn", True, False, (), ( ✅ ❌ ❌
yubor("a@x", "Mavzu", "Matn", html=True) ❌ ✅ ✅
yubor(kimga="a@x", mavzu="M", matn="T") ❌ ✅ ❌
=== 6. Imzo sifatini baholash ===
Funksiya Ball Ogohlantirishlar
──────────────────────────────────────────────────────────────────
⚠️ yubor_v1 80 7 pozitsion parametr (4 dan ko'p)
✅ yubor_v2 100 —
✅ yubor_v3 100 —
✅ formatla 100 —
❌ yomon_namuna 0 bool pozitsion bo'lishi mumkin: ['tozala', 'qatiy']
8 pozitsion parametr (4 dan ko'p)
o'zgaruvchan sukut: ['r']Nima ko'rsatdi: 2.4, 2.7-bo'limlar.
Misol 4 — Amaliy: kutubxona API
"""To'liq kutubxona — / va * bilan loyihalangan."""
import inspect
import re
from dataclasses import dataclass, field
from enum import Enum
print("=== Matn qayta ishlash kutubxonasi ===\n")
class Registr(Enum):
SAQLASH = "saqlash"
KICHIK = "kichik"
KATTA = "katta"
SARLAVHA = "sarlavha"
class Tekislash(Enum):
CHAP = "<"
MARKAZ = "^"
ONG = ">"
# ─────────────────────────────────────────────
# Asosiy funksiyalar — barchasi / va * bilan
# ─────────────────────────────────────────────
def tozala(matn, /, *,
bosh_joylar=True,
takroriy_joylar=True,
registr=Registr.SAQLASH,
belgilar=None):
"""Matnni tozalaydi.
matn — faqat pozitsion (nomi ichki tafsilot)
qolgan hammasi — faqat nomli (o'qiladigan chaqiruv)
"""
if belgilar:
matn = matn.translate(str.maketrans("", "", belgilar))
if takroriy_joylar:
matn = re.sub(r"\s+", " ", matn)
if bosh_joylar:
matn = matn.strip()
if registr is Registr.KICHIK:
matn = matn.casefold()
elif registr is Registr.KATTA:
matn = matn.upper()
elif registr is Registr.SARLAVHA:
matn = " ".join(s.capitalize() for s in matn.split())
return matn
def kes(matn, uzunlik, /, *, oxiri="…", sozlarni_saqlash=True):
"""Matnni belgilangan uzunlikka kesadi."""
if len(matn) <= uzunlik:
return matn
kesish_nuqtasi = uzunlik - len(oxiri)
if kesish_nuqtasi <= 0:
return oxiri[:uzunlik]
kesilgan = matn[:kesish_nuqtasi]
if sozlarni_saqlash and " " in kesilgan:
kesilgan = kesilgan.rsplit(" ", 1)[0]
return kesilgan + oxiri
def joyla(matn, kenglik, /, *,
tekislash=Tekislash.CHAP,
toldirish=" ",
kesish=True):
"""Matnni belgilangan kenglikka joylaydi."""
if kesish and len(matn) > kenglik:
matn = kes(matn, kenglik)
return f"{matn:{toldirish}{tekislash.value}{kenglik}}"
def bol(matn, /, *, ajratgich=None, chegara=-1, bosh_tashla=True):
"""Matnni bo'laklarga ajratadi."""
qismlar = matn.split(ajratgich, chegara)
if bosh_tashla:
qismlar = [q for q in qismlar if q.strip()]
return qismlar
def almashtir(matn, eski, yangi, /, *,
soni=-1,
registr_farqi=True,
butun_soz=False):
"""Matnda almashtirish."""
if butun_soz:
naqsh = rf"\b{re.escape(eski)}\b"
else:
naqsh = re.escape(eski)
bayroqlar = 0 if registr_farqi else re.IGNORECASE
return re.sub(naqsh, yangi, matn, count=0 if soni < 0 else soni,
flags=bayroqlar)
def ramka(matn, /, *,
kenglik=None,
uslub="oddiy",
sarlavha=None,
tekislash=Tekislash.CHAP):
"""Matnni ramkaga oladi."""
USLUBLAR = {
"oddiy": "─│┌┐└┘",
"qalin": "━┃┏┓┗┛",
"ikki": "═║╔╗╚╝",
"nuqta": "╌╎┌┐└┘",
}
h, v, yc, yo_, pc, po = USLUBLAR[uslub]
qatorlar = matn.splitlines() or [""]
kenglik = kenglik or max(len(q) for q in qatorlar) + 2
ichki = kenglik - 2
natija = []
if sarlavha:
s = f" {kes(sarlavha, ichki - 2)} "
natija.append(yc + s.center(ichki, h) + yo_)
else:
natija.append(yc + h * ichki + yo_)
for q in qatorlar:
natija.append(v + joyla(q, ichki, tekislash=tekislash) + v)
natija.append(pc + h * ichki + po)
return "\n".join(natija)
# ═══ NAMOYISH ═══
XOM = " Salom, DUNYO! Bu — sinov matni. "
print("=== 1. tozala ===\n")
print(f" Xom: {XOM!r}\n")
VARIANTLAR = [
("tozala(m)", {}),
("tozala(m, registr=Registr.KICHIK)", {"registr": Registr.KICHIK}),
("tozala(m, registr=Registr.SARLAVHA)", {"registr": Registr.SARLAVHA}),
("tozala(m, belgilar=',.!—')", {"belgilar": ",.!—"}),
("tozala(m, takroriy_joylar=False)", {"takroriy_joylar": False}),
]
for kod, kwargs in VARIANTLAR:
print(f" {kod:<40}")
print(f" → {tozala(XOM, **kwargs)!r}")
print("\n\n=== 2. kes ===\n")
MATN = "Python — kuchli va oddiy dasturlash tili"
print(f" Matn: {MATN!r} ({len(MATN)} belgi)\n")
for uzunlik in [20, 30, 15]:
for saqlash in [True, False]:
natija = kes(MATN, uzunlik, sozlarni_saqlash=saqlash)
print(f" kes(m, {uzunlik}, sozlarni_saqlash={saqlash!s:<5}) "
f"→ {natija!r}")
print()
print("=== 3. ramka ===\n")
for uslub in ["oddiy", "qalin", "ikki", "nuqta"]:
print(ramka(
"Salom, dunyo!\nBu — ikkinchi qator.",
kenglik=34,
uslub=uslub,
sarlavha=uslub.upper(),
tekislash=Tekislash.MARKAZ,
))
print()
print("=== 4. almashtir ===\n")
MATN2 = "Python python PYTHON pythonic"
print(f" Matn: {MATN2!r}\n")
VARIANTLAR = [
("almashtir(m, 'python', 'Py')", ("python", "Py"), {}),
("almashtir(m, 'python', 'Py', registr_farqi=False)",
("python", "Py"), {"registr_farqi": False}),
("almashtir(m, 'python', 'Py', registr_farqi=False, butun_soz=True)",
("python", "Py"), {"registr_farqi": False, "butun_soz": True}),
("almashtir(m, 'python', 'Py', registr_farqi=False, soni=1)",
("python", "Py"), {"registr_farqi": False, "soni": 1}),
]
for kod, args, kwargs in VARIANTLAR:
print(f" {kod}")
print(f" → {almashtir(MATN2, *args, **kwargs)!r}\n")
print("=== 5. ⭐ API dizayni tahlili ===\n")
FUNKSIYALAR = [tozala, kes, joyla, bol, almashtir, ramka]
print(f" {'Funksiya':<12} {'Poz.':>5} {'Nomli':>6} Imzo")
print(" " + "─" * 76)
for f in FUNKSIYALAR:
sig = inspect.signature(f)
ps = sig.parameters.values()
poz = sum(1 for p in ps if p.kind is p.POSITIONAL_ONLY)
nomli = sum(1 for p in ps if p.kind is p.KEYWORD_ONLY)
imzo = str(sig)
if len(imzo) > 50:
imzo = imzo[:48] + "…"
print(f" {f.__name__:<12} {poz:>5} {nomli:>6} {imzo}")
print(f"""
⭐ Barcha funksiyalarda bir xil naqsh:
def f(asosiy..., /, *, sozlama1=..., sozlama2=...)
• Asosiy argumentlar — faqat pozitsion
(nomlarini keyinchalik o'zgartirish mumkin)
• Sozlamalar — faqat nomli
(chaqiruv o'z-o'zini hujjatlaydi, yangi qo'shish xavfsiz)
""")
print("=== 6. Noto'g'ri chaqiruvlar ===\n")
XATOLAR = [
("tozala(matn='x')", lambda: tozala(matn="x")),
("kes('abc', uzunlik=2)", lambda: kes("abc", uzunlik=2)),
("kes('abcdef', 3, '...')", lambda: kes("abcdef", 3, "...")),
("joyla('x', 10, Tekislash.ONG)", lambda: joyla("x", 10, Tekislash.ONG)),
("bol('a b', ' ')", lambda: bol("a b", " ")),
]
for kod, f in XATOLAR:
try:
natija = f"✅ {f()!r}"
except TypeError as x:
natija = f"❌ {str(x)[:52]}"
print(f" {kod:<34} {natija}")
print("""
⭐ Har bir xato DARHOL va ANIQ:
• Foydalanuvchi to'g'ri shaklni o'rganadi
• Jimgina noto'g'ri natija bo'lmaydi
""")
print("\n=== 7. Kelajakdagi kengaytirish ===\n")
def tozala_v2(matn, /, *,
bosh_joylar=True,
takroriy_joylar=True,
registr=Registr.SAQLASH,
belgilar=None,
# ⭐ YANGI parametrlar — hech narsa buzilmaydi
normalizatsiya=None,
apostrof_birlashtirish=False,
maksimal_uzunlik=None):
"""v2 — uchta yangi parametr qo'shildi."""
natija = tozala(matn, bosh_joylar=bosh_joylar,
takroriy_joylar=takroriy_joylar,
registr=registr, belgilar=belgilar)
if apostrof_birlashtirish:
for a in "ʻʼ''`":
natija = natija.replace(a, "'")
if normalizatsiya:
import unicodedata
natija = unicodedata.normalize(normalizatsiya, natija)
if maksimal_uzunlik:
natija = kes(natija, maksimal_uzunlik)
return natija
print(f" Eski chaqiruvlar v2 da ham ishlaydi:\n")
ESKI = [
("tozala(m)", {}),
("tozala(m, registr=Registr.KICHIK)", {"registr": Registr.KICHIK}),
("tozala(m, belgilar=',.')", {"belgilar": ",."}),
]
for kod, kwargs in ESKI:
v1 = tozala(XOM, **kwargs)
v2 = tozala_v2(XOM, **kwargs)
belgi = "✅" if v1 == v2 else "❌"
print(f" {belgi} {kod:<40} {v1[:26]!r}")
print(f"\n Yangi imkoniyatlar:")
print(f" tozala_v2(m, apostrof_birlashtirish=True, maksimal_uzunlik=20)")
print(f" → {tozala_v2(' Oʻzbekiston Respublikasi ', apostrof_birlashtirish=True, maksimal_uzunlik=20)!r}")
print("""
⭐ * dan keyin yangi parametr qo'shish — MUTLAQO xavfsiz:
• Tartib muhim emas
• Eski chaqiruvlar buzilmaydi
• Sukut qiymatlar orqaga moslikni saqlaydi
""")Natijaning muhim qismi:
=== 3. ramka ===
┌──────────── ODDIY ─────────────┐
│ Salom, dunyo! │
│ Bu — ikkinchi qator. │
└────────────────────────────────┘
╔═════════════ IKKI ═════════════╗
║ Salom, dunyo! ║
║ Bu — ikkinchi qator. ║
╚════════════════════════════════╝
=== 5. ⭐ API dizayni tahlili ===
Funksiya Poz. Nomli Imzo
────────────────────────────────────────────────────────────────────────────
tozala 1 4 (matn, /, *, bosh_joylar=True, takroriy_joyl…
kes 2 2 (matn, uzunlik, /, *, oxiri='…', sozlarni_s…
joyla 2 3 (matn, kenglik, /, *, tekislash=<Tekislash.C…
almashtir 3 3 (matn, eski, yangi, /, *, soni=-1, registr_f…
=== 6. Noto'g'ri chaqiruvlar ===
tozala(matn='x') ❌ tozala() got some positional-only arg
kes('abcdef', 3, '...') ❌ kes() takes 2 positional arguments butNima ko'rsatdi: 2.4, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"/ va * — ekzotik" |
Standart kutubxonada keng ishlatiladi |
"/ faqat C funksiyalarida" |
Python 3.8+ da har qanday funksiyada |
"* — *args bilan bir xil" |
* argument yig'maydi, faqat chegara qo'yadi |
"* dan keyin sukutlar oxirida bo'lishi kerak" |
Tartib erkin |
"/ qo'shish xavfsiz" |
Buzuvchi — nomli chaqiruvlar |
"* qo'shish xavfsiz" |
Buzuvchi — pozitsion chaqiruvlar |
"/ faqat estetika" |
**kwargs bilan nom to'qnashuvini hal qiladi |
| "Nomli argument har doim yaxshiroq" | Pozitsion tezroq va ba'zan tabiiy |
"def f(a, *) mumkin" |
SyntaxError — * dan keyin parametr kerak |
6. Keng tarqalgan xatolar va yechimlari
1. Bool parametr * siz
def sarala(r, teskari=False): ... # ⚠️ sarala(r, True)
def sarala(r, *, teskari=False): ... # ✅2. Mavjud funksiyaga * qo'shish
def f(a, b): ... # v1
def f(a, *, b): ... # ❌ f(1, 2) buzildi3. / dan keyin nomli chaqirish
def f(a, /): ...
f(a=1) # ❌
f(1) # ✅4. * dan keyin parametr yo'q
def f(a, *): ... # ❌ SyntaxError
def f(a, *, b): ... # ✅5. / * dan keyin
def f(a, *, b, /): ... # ❌ SyntaxError
def f(a, /, *, b): ... # ✅6. **kwargs bilan nom to'qnashuvi
def f(nom, **kw): ...
f("x", nom="y") # ❌
def f(nom, /, **kw): ... # ✅7. Ko'p sukutli pozitsion
def f(a, b=1, c=2, d=3, e=4): ... # ⚠️ f(x, 1, 2, 3, 4)
def f(a, *, b=1, c=2, d=3, e=4): ... # ✅8. / ma'noli nom uchun
def ochish(fayl_yoli, /): ... # ⚠️ nom foydali edi
def ochish(fayl_yoli): ... # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 7.2, 7.4, 7.5-darslar (o'tilgan): argumentlar, nomli,
*args - 8-qism: metodlar,
self,dataclass - 10-qism: dekoratorlar,
functools - 14-dars: tur ko'rsatkichlari,
ParamSpec inspect: imzo tahlili- PEP 570 (
/), PEP 3102 (*) - API dizayni: semantik versiyalash, orqaga moslik
8. Eng yaxshi amaliyotlar
Sukut naqsh:
def f(asosiy, /, *, sozlama=None). Nom yopiq, sozlamalar nomli.Bool parametrni doim
*dan keyin. Bu — eng muhim qoida.3+ ixtiyoriy sozlama —
*dan keyin. Tartibni eslash shart emas.Nomi ma'nosiz parametrlarga
/.obj,x,iterable,self.**kwargsbilan/ishlating. Nom to'qnashuvini oldini oladi.Boshidan to'g'ri loyihalang.
/yoki*qo'shish — buzuvchi o'zgarish.Ma'noli nomlarga
/qo'ymang.fayl_yoli=,foydalanuvchi_id=foydali.inspect.signaturebilan tekshiring. Imzo kutilganidek ekanini.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
def f(a, /, b, *, c): return a, b, c
def g(a, *, b=1, c): return a, b, c
def h(a, /, **kw): return a, kw
1. print(f(1, 2, c=3))
2. print(f(1, b=2, c=3))
3. f(a=1, b=2, c=3)
4. f(1, 2, 3)
5. print(g(1, c=3))
6. print(g(1, c=3, b=2))
7. g(1, 2, 3)
8. print(h(1, a=2))
9. print(h(1, x=2, y=3))
10. def k(a, *): pass
11. def m(a, *, b, /): pass
12. import inspect; print(inspect.signature(len))Javoblar
(1, 2, 3)(1, 2, 3)-
TypeError—afaqat pozitsion -
TypeError—cfaqat nomli (1, 1, 3)(1, 2, 3)-
TypeError—bvacfaqat nomli (1, {'a': 2})—/tufayli(1, {'x': 2, 'y': 3})-
SyntaxError—*dan keyin parametr kerak -
SyntaxError—/*dan oldin (obj, /)
Vazifa 2: Xatolarni tuzating
1. def sarala(r, teskari=False, barqaror=True): ...
2. def f(a, *): ...
3. def f(a, *, b, /): ...
4. def f(nom, **kwargs): ... # nom kaliti kerak bo'lishi mumkin
5. def f(a, b=1, c=2, d=3, e=4, g=5): ...
6. def hisobla(malumot, True, False): ...
7. # v1: def f(a, b) → v2: def f(a, *, b)
8. def ochish(fayl_yoli, /, rejim="r"): ...Javoblar
1. def sarala(r, /, *, teskari=False, barqaror=True): ...
2. def f(a, *, b): ...
3. def f(a, /, *, b): ...
4. def f(nom, /, **kwargs): ...
5. def f(a, *, b=1, c=2, d=3, e=4, g=5): ...
6. def hisobla(malumot, /, *, tozala=True, qatiy=False): ...
7. Deprecation davri bilan: def f(a, b=None, *, yangi_b=None)
8. def ochish(fayl_yoli, *, rejim="r"): ... # nom ma'noli, / kerak emasVazifa 3: API refaktoring
Berilgan funksiyalarni qayta loyihalang (/ va * bilan):
def yubor(kimga, mavzu, matn, html, muhim, nusxa, ilova, urinishlar)
def qidir(matn, naqsh, katta_kichik, butun_soz, teskari, chegara)
def chiz(x, y, kenglik, balandlik, rang, ramka, toldirish, shaffof)
def ulan(host, port, foydalanuvchi, parol, ssl, timeout, pool)Har biri uchun:
- Qaysi parametrlar
/dan oldin - Qaysi parametrlar
*dan keyin - Sabab
inspect.signaturebilan tekshiring
Vazifa 4: Imzo linteri
Vosita yozing:
- Modul funksiyalarini skanerlaydi
- Har biri uchun ball (0-100) beradi
- Ogohlantirishlar:
- Bool parametr
*siz - 4+ pozitsion parametr
- 3+ sukutli pozitsion
**kwargsbor, lekin/yo'q- O'zgaruvchan sukut
- Bool parametr
- Tuzatilgan imzo taklifini beradi
- Hisobot jadval ko'rinishida
Vazifa 5: Migratsiya vositasi
Dekorator yozing:
@imzo_migratsiyasi(eski="(a, b, c)", yangi="(a, /, *, b, c)")
def f(a, /, *, b, c): ...- Eski chaqiruv shakllarini qabul qilsin
DeprecationWarningbersin- Yangi shaklga o'tkazsin
inspect.signatureyangi shaklni ko'rsatsin- Bir necha versiyani qo'llab-quvvatlasin
Vazifa 6: Kutubxona loyihalash
To'liq kutubxona yozing (10+ funksiya):
- Barchasida
asosiy, /, *, sozlamalarnaqshi Enumbilan sozlamalar (bool o'rniga)- Har biri uchun docstring va tur ko'rsatkichlari
- Kelajakdagi kengaytirishni sinab ko'ring
- Noto'g'ri chaqiruvlar uchun testlar
inspectbilan API hisoboti
Vazifa 7: O'ylash
Nega Python / ni faqat 3.8 da qo'shdi, garchi C funksiyalari uni 20 yil ishlatgan bo'lsa ham?
Javob
Chunki muammo faqat vaqt o'tib ko'rindi.
Tarixiy holat:
C da yozilgan funksiyalar har doim faqat pozitsion edi:
len(obj=[1, 2]) # ❌ Python 2 da ham
abs(x=-5) # ❌Sabab — texnik: C API (PyArg_ParseTuple) nomli argumentlarni qo'llab-quvvatlamasdi. Bu — cheklov edi, dizayn qarori emas.
Pythonda yozilgan funksiyalar esa har doim nomli chaqiruvni qabul qilardi:
def f(a): ...
f(a=1) # ✅ har doim ishlaganNomuvofiqlik:
len([1, 2]) # ✅
len(obj=[1, 2]) # ❌
def mening_len(obj): return len(obj)
mening_len(obj=[1, 2]) # ✅ — nomuvofiq!Yillar davomida bu "shunchaki shunday" deb qabul qilindi.
Muammo qachon ko'rindi:
1. Pure-Python qayta yozishlar.
Ba'zi C modullari Pythonda qayta yozildi (io, datetime, decimal). Ular endi nomli argumentni qabul qila boshladi — bu xatti-harakat o'zgarishi:
# C versiyasi
_datetime.date(year=2026, month=9, day=8) # ❌
# Python versiyasi
datetime.date(year=2026, month=9, day=8) # ✅ — farq!2. Argument Clinic.
2013 da CPython ga Argument Clinic vositasi qo'shildi — u C funksiyalari uchun imzolarni avtomatik generatsiya qiladi. Endi C funksiyalari nomli argumentni qabul qila olardi.
Lekin ko'p funksiya uchun bu kerak emas edi:
len(obj=[1, 2]) # foydali emas, lekin endi mumkin?Va obj nomi — ichki tafsilot. Uni API ga aylantirish istalmagan.
Shuning uchun / sintaksisi hujjatlarda paydo bo'ldi — imzoda "bu yerdan oldin faqat pozitsion" degan belgi.
3. **kwargs bilan to'qnashuv.
def f(nom, **kwargs): ...
f("x", nom="y") # ❌ TypeErrorBu — real muammo. dict() uni maxsus C kodi bilan hal qilgan, lekin Python funksiyalari uchun yo'l yo'q edi.
4. Kutubxona mualliflari so'radi.
API dizaynerlari parametr nomlarini yopish imkonini so'ray boshladi — chunki nomni o'zgartirish orqaga moslikni buzardi.
PEP 570 (2018):
Yozuvchilar: Larry Hastings, Pablo Galindo, Mario Corchero, Eric N. Vander Weele.
Asosiy dalillar:
- Nomuvofiqlikni bartaraf etish — Python funksiyalari C funksiyalari kabi bo'la oladi
- Nomlarni yopish — API evolyutsiyasi uchun
**kwargsto'qnashuvi — hal qilinadi- Hujjatlar sintaksisini rasmiylashtirish —
/allaqachonhelp()da ko'rinardi
Qarshi dalillar (muhokamada):
- "Yana bir sintaksis — o'rganish narxi"
- "
_nomkelishuvi yetarli" (lekin u majburlamaydi) - "Kam ishlatiladi"
Nega 20 yil ketdi:
1. Muammo asta-sekin to'plandi.
Har bir sabab alohida kichik edi. Faqat birgalikda ular PEP ni oqladi.
2. Sintaksis tanlash qiyin edi.
Muqobil takliflar:
def f(a, b, __, c): ... # __ ajratgich
def f(*, a, b; c): ... # nuqtali vergul
@positional_only(2) # dekorator
def f(a, b, c): .../ tanlandi, chunki u allaqachon hujjatlarda ishlatilardi (help() chiqishida).
3. * (PEP 3102, 2006) birinchi keldi.
Faqat nomli argumentlar 12 yil oldin qo'shilgan. / — uning simmetrik juftligi. Lekin * ning ehtiyoji aniqroq edi (bool argumentlar muammosi).
Bugungi holat:
# Python 3.8+ da to'liq nazorat
def f(a, /, b, *, c): ...Standart kutubxona asta-sekin / qo'shmoqda — lekin faqat yangi funksiyalarga yoki / allaqachon amalda bo'lgan C funksiyalariga. Mavjud Python funksiyalariga qo'shish — buzuvchi o'zgarish.
Xulosa: bu — til evolyutsiyasining tipik namunasi. Muammo yillar davomida to'planadi, bir necha sabab birlashadi, keyin PEP paydo bo'ladi. Va yechim ko'pincha allaqachon amalda mavjud narsani rasmiylashtiradi — bu holda help() dagi / belgisini.
Nimani mustahkamlaydi: 2.2, 2.4, 2.6-bo'limlar.
Xulosa
Bu darsda / va * belgilarini o'rgandik.
Eng muhim uch fikr:
*— bool argumentlarni o'qiladigan qiladi.sarala(r, True, False)o'rnigasarala(r, teskari=True). Va*dan keyin yangi parametr qo'shish mutlaqo xavfsiz — tartib ham, sukut qiymatlar tartibi ham muhim emas./— parametr nomini ichki tafsilotga aylantiradi. Nomni keyinchalik o'zgartirish mumkin bo'ladi, va**kwargsbilan nom to'qnashuvi yo'qoladi (f("x", nom="y")ishlaydi).Sukut naqsh:
def f(asosiy, /, *, sozlama=None). Bu — standart kutubxonaning naqshi (sorted,print,json.dumps). Lekin/yoki*ni mavjud funksiyaga qo'shish — buzuvchi o'zgarish, shuning uchun boshidan to'g'ri loyihalang.
Keyingi darsda return ni chuqur o'rganamiz: bir nechta qiymat, erta qaytish, None semantikasi va generator funksiyalari bilan farq.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!