Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. None — yagona obyekt
- 2.2. None falsy, lekin False emas
- 2.3. None qayerdan keladi
- 2.4. None bilan ishlash: AttributeError tuzog'i
- 2.5. None ni qaytaruvchi funksiyalar
- 2.6. O'zgaruvchan sukut argument tuzog'i
- 2.7. None va tur ishoralari
- 2.8. None ni tekshirish naqshlari
- 2.9. None va boshqa "bo'shlik" turlari
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — None qayerdan keladi
- Misol 2 — Sukut argument tuzog'i
- Misol 3 — None va falsy farqi
- Misol 4 — Amaliy dastur: foydalanuvchi profili
- 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
3.6-dars: None nima
3-QISM — ASOSLAR · 6-dars
1. Kirish va motivatsiya
None — Pythondagi eng oddiy ko'ringan, lekin eng ko'p muammo keltiradigan qiymat.
U "hech narsa", "qiymat yo'q", "hali aniqlanmagan" degan ma'noni bildiradi. Va aynan shuning uchun u hamma joyda paydo bo'ladi:
print(print("salom")) # None — print hech narsa qaytarmaydiroyxat = [3, 1, 2]
saralangan = royxat.sort()
print(saralangan) # None ← kutilmagan!lugat = {"ism": "Ali"}
print(lugat.get("yosh")) # None — kalit yo'qVa eng mashhur xato:
AttributeError: 'NoneType' object has no attribute 'strip'Tony Hoare — null tushunchasining ixtirochisi — 2009-yilda uni "milliard dollarlik xato" deb atadi:
"Men buni 1965-yilda kiritdim... Bu shunchaki qulay edi. Lekin u so'nggi qirq yilda son-sanoqsiz xatolar, zaifliklar va tizim ishdan chiqishlariga sabab bo'ldi — ehtimol milliard dollarlik zarar."
Bu darsda None ni to'g'ri ishlatishni o'rganamiz: qachon kerak, qachon kerak emas va uning tuzoqlaridan qanday qochish kerak.
2. Nazariya — chuqur tushuntirish
2.1. None — yagona obyekt
None — NoneType turining yagona namunasi. Butun dasturda faqat bitta None obyekti mavjud.
print(type(None)) # <class 'NoneType'>
print(None is None) # True
print(id(None)) # doim bir xil
a = None
b = None
print(a is b) # True — bitta obyektBu — singleton naqshi (27-qism). Python ishga tushganda bitta None yaratadi va uni hamma joyda ishlatadi.
Yangi NoneType yaratib bo'lmaydi:
import types
types.NoneType() # TypeError: cannot create 'NoneType' instancesAynan shuning uchun is None to'g'ri usul:
if qiymat is None: # ✅ eng tez va eng aniq
if qiymat == None: # ⚠️ ishlaydi, lekin sekinroq va noto'g'ri uslubis — bu manzil solishtiruvi (3.1-dars). Bitta obyekt bo'lgani uchun bu har doim to'g'ri ishlaydi va eng tez.
== esa __eq__ metodini chaqiradi — uni sinf qayta yozishi mumkin:
class Gaalati:
def __eq__(self, boshqa):
return True # hamma narsaga teng!
g = Gaalati()
print(g == None) # True — yolg'on
print(g is None) # False — haqiqatBu — nazariy misol, lekin is None odatini shakllantirish uchun yaxshi sabab.
2.2. None falsy, lekin False emas
print(bool(None)) # False — falsy (3.5-dars)
print(None == False) # False — lekin teng emas!
print(None == 0) # False
print(None == "") # FalseNone falsy, lekin u False, 0 yoki "" bilan teng emas.
Bu farq juda muhim:
def hisobla(qiymat=None):
if not qiymat: # ❌ 0, "", [] ni ham ushlaydi
return "Qiymat yo'q"
return f"Qiymat: {qiymat}"
print(hisobla(0)) # "Qiymat yo'q" — NOTO'G'RI
def hisobla_togri(qiymat=None):
if qiymat is None: # ✅ faqat None
return "Qiymat yo'q"
return f"Qiymat: {qiymat}"
print(hisobla_togri(0)) # "Qiymat: 0" — to'g'riQoida:
"Berilmagan" va "bo'sh" — turli narsalar.
is Nonebilan birinchisini, truthiness bilan ikkinchisini tekshiring.
2.3. None qayerdan keladi
1. Funksiya return qilmasa
def salomlash(ism):
print(f"Salom, {ism}!")
# return yo'q
natija = salomlash("Ali")
print(natija) # NonePythonda har bir funksiya qiymat qaytaradi. return yozilmasa — None.
def bosh():
pass
def bosh2():
return
def bosh3():
return None
# Uchalasi ham bir xil — None qaytaradi2. O'zgartiruvchi metodlar
Bu — eng ko'p tuzoq beradigan manba:
royxat = [3, 1, 2]
print(royxat.sort()) # None ← ro'yxat emas!
print(royxat) # [1, 2, 3] — ro'yxat o'zgardi
print(royxat.append(4)) # None
print(royxat.reverse()) # None
print(royxat.clear()) # NoneSabab — Python kelishuvi:
Obyektni joyida o'zgartiradigan metodlar
Noneqaytaradi. Yangi obyekt qaytaradigan funksiyalar natijani qaytaradi.
royxat = [3, 1, 2]
royxat.sort() # joyida o'zgartiradi, None qaytaradi
yangi = sorted(royxat) # YANGI ro'yxat qaytaradi
matn = "salom"
katta = matn.upper() # satr o'zgarmas → yangi satr qaytaradiBu kelishuv ataylab — sizni "o'zgartirdimmi yoki nusxa oldimmi?" degan savoldan qutqaradi.
3. Lug'at .get() metodi
foydalanuvchi = {"ism": "Ali"}
print(foydalanuvchi.get("ism")) # 'Ali'
print(foydalanuvchi.get("yosh")) # None — kalit yo'q
print(foydalanuvchi.get("yosh", 0)) # 0 — sukut qiymat
print(foydalanuvchi["yosh"]) # KeyError!4. re qidiruvi topilmaganda
import re
natija = re.search(r"\d+", "salom dunyo")
print(natija) # None — raqam topilmadi5. Sukut parametr qiymati
def hisobla(a, b=None):
if b is None:
b = 10
return a + bBu — eng keng tarqalgan None ishlatilishi (2.6-bo'limda batafsil).
2.4. None bilan ishlash: AttributeError tuzog'i
Eng ko'p uchraydigan xato:
ism = None
print(ism.strip())AttributeError: 'NoneType' object has no attribute 'strip'None da hech qanday foydali metod yo'q:
print([m for m in dir(None) if not m.startswith("_")])[]Bo'sh — faqat sehrli metodlar bor.
Yechimlar:
# 1. Aniq tekshiruv
if ism is not None:
print(ism.strip())
# 2. Qisqa tutashuv (3.5-dars)
if ism and ism.strip():
print("Ism bor")
# 3. Sukut qiymat
tozalangan = (ism or "").strip()
# 4. Shartli ifoda
tozalangan = ism.strip() if ism else ""2.5. None ni qaytaruvchi funksiyalar
Funksiya None qaytarishi normal — lekin izchil bo'lish kerak.
Yomon: ba'zan qiymat, ba'zan None
def foydalanuvchi_topish(id):
if id in BAZA:
return BAZA[id]
# implicit NoneChaqiruvchi har safar tekshirishi kerak va uni unutish oson.
Yaxshi: aniq va hujjatlashtirilgan
def foydalanuvchi_topish(user_id: int) -> dict | None:
"""Foydalanuvchini topadi.
Returns:
Foydalanuvchi lug'ati, yoki topilmasa None.
"""
return BAZA.get(user_id)dict | None — tur ishorasi (13-qism). U chaqiruvchiga None bo'lishi mumkinligini aytadi va Pylance tekshiradi.
Muqobil: xato ko'tarish
def foydalanuvchi_olish(user_id: int) -> dict:
"""Foydalanuvchini qaytaradi.
Raises:
KeyError: foydalanuvchi topilmasa.
"""
if user_id not in BAZA:
raise KeyError(f"Foydalanuvchi topilmadi: {user_id}")
return BAZA[user_id]Qaysi biri yaxshi?
| Vaziyat | Yechim |
|---|---|
| "Topilmaslik" — normal holat | None qaytaring |
| "Topilmaslik" — xato | Istisno ko'taring |
Standart kutubxona ikkalasini ham beradi:
lugat.get("kalit") # None qaytaradi
lugat["kalit"] # KeyError ko'taradiChaqiruvchi tanlaydi.
2.6. O'zgaruvchan sukut argument tuzog'i
Bu — Pythondagi eng mashhur tuzoq. Har bir dasturchi unga bir marta tushadi.
def qosh(element, royxat=[]): # ❌ XAVFLI
royxat.append(element)
return royxat
print(qosh(1)) # [1]
print(qosh(2)) # [1, 2] ← kutilmagan!
print(qosh(3)) # [1, 2, 3]Nega?
Sukut qiymat funksiya aniqlanganda bir marta yaratiladi — har chaqiruvda emas. Ya'ni barcha chaqiruv bitta ro'yxatni ishlatadi.
def qosh(element, royxat=[]):
...
print(qosh.__defaults__) # ([],) — funksiyada saqlanadi
qosh(1)
print(qosh.__defaults__) # ([1],) — o'zgardi!To'g'ri yechim — None naqshi:
def qosh(element, royxat=None): # ✅
if royxat is None:
royxat = []
royxat.append(element)
return royxat
print(qosh(1)) # [1]
print(qosh(2)) # [2] ✅
print(qosh(3)) # [3] ✅Endi har chaqiruvda yangi ro'yxat yaratiladi.
Qaysi turlar xavfli?
| Xavfli (o'zgaruvchan) | Xavfsiz (o'zgarmas) |
|---|---|
list — [] |
int — 0 |
dict — {} |
float — 0.0 |
set — set() |
str — "" |
| Sinf namunalari | tuple — () |
bool, None |
Qoida:
Sukut qiymat o'zgaruvchan bo'lsa —
Noneishlating va funksiya ichida yarating.
Ruff bu xatoni topadi: B006 ("mutable default argument").
2.7. None va tur ishoralari
from typing import Optional
# Uch xil yozuv — bir xil ma'no
def f1(x: int | None) -> str | None: ... # ✅ zamonaviy (3.10+)
def f2(x: Optional[int]) -> Optional[str]: ... # eski uslub
def f3(x: "int | None") -> "str | None": ... # satr sifatidaOptional[int] aynan int | None degani — "yo int, yo None".
Sukut qiymat bilan:
def salomlash(ism: str | None = None) -> str:
if ism is None:
return "Salom, mehmon!"
return f"Salom, {ism}!"Pylance endi tekshiradi:
def uzunlik(matn: str | None) -> int:
return len(matn) # ⚠️ Pylance: matn None bo'lishi mumkin
def uzunlik_togri(matn: str | None) -> int:
if matn is None:
return 0
return len(matn) # ✅ endi Pylance biladi: matn — strBu — tur toraytirish (type narrowing). Pylance if matn is None: return dan keyin matn faqat str bo'lishini tushunadi.
13-qismda batafsil.
2.8. None ni tekshirish naqshlari
1. Oddiy tekshiruv
if qiymat is None:
...
if qiymat is not None:
...2. Sukut qiymat berish
# Faqat None uchun
qiymat = 10 if kirish is None else kirish
# Barcha falsy uchun (ehtiyot!)
qiymat = kirish or 103. Zanjirli xavfsiz kirish
# ❌ Uzun va noqulay
if foydalanuvchi is not None:
if foydalanuvchi.manzil is not None:
if foydalanuvchi.manzil.shahar is not None:
print(foydalanuvchi.manzil.shahar)
# ✅ Qisqa tutashuv
shahar = (
foydalanuvchi
and foydalanuvchi.manzil
and foydalanuvchi.manzil.shahar
)Eslatma: Pythonda JavaScript'dagi
?.operatori yo'q. Bu taklif qilingan (PEP 505), lekin qabul qilinmagan.
4. Lug'atlar bilan
yosh = malumot.get("yosh") # None bo'lishi mumkin
yosh = malumot.get("yosh", 0) # sukut bilan
yosh = malumot.get("yosh") or 0 # ⚠️ 0 ni ham almashtiradi5. Sentinel qiymat — None yaroqli qiymat bo'lganda
Ba'zan None — haqiqiy qiymat bo'lishi mumkin. Unda alohida belgi kerak:
YOQ = object() # noyob sentinel obyekt
def olish(lugat, kalit, sukut=YOQ):
if kalit in lugat:
return lugat[kalit]
if sukut is YOQ:
raise KeyError(kalit)
return sukut
lugat = {"a": None}
print(olish(lugat, "a")) # None — haqiqiy qiymat
print(olish(lugat, "b", None)) # None — sukut qiymat
# olish(lugat, "b") # KeyErrorobject() — har safar noyob obyekt yaratadi. Uni hech narsa bilan adashtirib bo'lmaydi.
2.9. None va boshqa "bo'shlik" turlari
Pythonda "hech narsa" ni ifodalovchi bir necha usul bor:
| Qiymat | Ma'nosi | Qachon |
|---|---|---|
None |
Qiymat yo'q / aniqlanmagan | Umumiy holat |
0 |
Nol miqdor | Sanoq, hisob |
"" |
Bo'sh matn | Satrlar |
[] |
Bo'sh to'plam | Ro'yxatlar |
float("nan") |
Aniqlanmagan son | Ilmiy hisob (3.4-dars) |
... (Ellipsis) |
To'ldirilishi kerak | Joy egallovchi |
... (Ellipsis) — kam ma'lum, lekin foydali:
def keyinroq_yozamiz():
... # `pass` o'rniga, "hali yozilmagan" ma'nosida
from typing import Protocol
class Interfeys(Protocol):
def metod(self) -> str: ...... — haqiqiy obyekt:
print(type(...)) # <class 'ellipsis'>
print(... is Ellipsis) # True
print(bool(...)) # True — falsy EMASQaysi birini tanlash:
# ❌ Turli ma'nolarni aralashtirish
def qidirish(matn):
if not matn:
return "" # topilmadimi yoki bo'sh natijami?
# ✅ Aniq
def qidirish(matn: str) -> str | None:
if not matn:
return None # qidirish o'tkazilmadi
natija = ...
return natija or "" # topildi, lekin bo'sh3. Tez ma'lumotnoma
Asosiy qoidalar
qiymat is None ✅ doim shunday
qiymat == None ❌ sekinroq, ishonchsizroq
if qiymat is None: ✅ faqat None ni tekshiradi
if not qiymat: ⚠️ 0, "", [] ni ham ushlaydiXususiyatlar
type(None) → NoneType
bool(None) → False
None == False → False (falsy, lekin teng emas)
None == 0 → False
dir(None) → faqat sehrli metodlarNone qayerdan keladi
return yo'q funksiya
royxat.sort(), .append(), .clear() — joyida o'zgartiruvchilar
lugat.get(yo'q_kalit)
re.search(topilmadi)Sukut argument naqshi
def f(royxat=[]): ❌ HECH QACHON
def f(royxat=None): ✅
if royxat is None:
royxat = []Tur ishorasi
def f(x: int | None = None) -> str | None: ...4. Batafsil misollar
Misol 1 — None qayerdan keladi
import re
print("=== 1. return yo'q ===")
def salomlash(ism):
print(f" Salom, {ism}!")
natija = salomlash("Ali")
print(f" Qaytardi: {natija!r}")
print("\n=== 2. Joyida o'zgartiruvchi metodlar ===")
royxat = [3, 1, 2]
print(f" royxat.sort() → {royxat.sort()!r}")
print(f" royxat endi: {royxat}")
print(f" royxat.append(4) → {royxat.append(4)!r}")
print(f" royxat endi: {royxat}")
print(f" sorted(royxat) → {sorted(royxat, reverse=True)!r} ← yangi ro'yxat")
print("\n=== 3. Lug'at .get() ===")
foydalanuvchi = {"ism": "Ali", "yosh": 25}
print(f" .get('ism') → {foydalanuvchi.get('ism')!r}")
print(f" .get('shahar') → {foydalanuvchi.get('shahar')!r}")
print(f" .get('shahar','?')→ {foydalanuvchi.get('shahar', '?')!r}")
print("\n=== 4. Muntazam ifoda ===")
print(f" re.search(raqam, 'abc123') → {re.search(r'\\d+', 'abc123')}")
print(f" re.search(raqam, 'abcdef') → {re.search(r'\\d+', 'abcdef')!r}")
print("\n=== 5. print ning o'zi ===")
print(f" print('x') qaytaradi: {print(' x')!r}")=== 1. return yo'q ===
Salom, Ali!
Qaytardi: None
=== 2. Joyida o'zgartiruvchi metodlar ===
royxat.sort() → None
royxat endi: [1, 2, 3]
royxat.append(4) → None
royxat endi: [1, 2, 3, 4]
sorted(royxat) → [4, 3, 2, 1] ← yangi ro'yxat
=== 3. Lug'at .get() ===
.get('ism') → 'Ali'
.get('shahar') → None
.get('shahar','?')→ '?'
=== 4. Muntazam ifoda ===
re.search(raqam, 'abc123') → <re.Match object; span=(3, 6), match='123'>
re.search(raqam, 'abcdef') → None
=== 5. print ning o'zi ===
x
print('x') qaytaradi: NoneEng muhim xulosa: royxat.sort() None qaytaradi. saralangan = royxat.sort() — klassik xato.
Nima ko'rsatdi: 2.3-bo'lim.
Misol 2 — Sukut argument tuzog'i
"""Pythondagi eng mashhur tuzoq."""
print("=== ❌ XAVFLI versiya ===")
def qosh_xavfli(element, royxat=[]):
royxat.append(element)
return royxat
print(f" qosh_xavfli(1) → {qosh_xavfli(1)}")
print(f" qosh_xavfli(2) → {qosh_xavfli(2)}")
print(f" qosh_xavfli(3) → {qosh_xavfli(3)}")
print(f" Funksiyaning sukut qiymati: {qosh_xavfli.__defaults__}")
print("\n=== ✅ TO'G'RI versiya ===")
def qosh_togri(element, royxat=None):
if royxat is None:
royxat = []
royxat.append(element)
return royxat
print(f" qosh_togri(1) → {qosh_togri(1)}")
print(f" qosh_togri(2) → {qosh_togri(2)}")
print(f" qosh_togri(3) → {qosh_togri(3)}")
print(f" Berilgan ro'yxat bilan: {qosh_togri(4, [10, 20])}")
print(f" Funksiyaning sukut qiymati: {qosh_togri.__defaults__}")
print("\n=== Lug'at bilan ham xuddi shunday ===")
def sozla_xavfli(kalit, qiymat, sozlama={}):
sozlama[kalit] = qiymat
return sozlama
print(f" {sozla_xavfli('a', 1)}")
print(f" {sozla_xavfli('b', 2)}")
print("\n=== Xavfsiz turlar ===")
def xavfsiz(a=0, b="", c=(), d=None, e=True):
"""Bu sukut qiymatlar o'zgarmas — xavfsiz."""
return a, b, c, d, e
print(f" {xavfsiz()}")=== ❌ XAVFLI versiya ===
qosh_xavfli(1) → [1]
qosh_xavfli(2) → [1, 2]
qosh_xavfli(3) → [1, 2, 3]
Funksiyaning sukut qiymati: ([1, 2, 3],)
=== ✅ TO'G'RI versiya ===
qosh_togri(1) → [1]
qosh_togri(2) → [2]
qosh_togri(3) → [3]
Berilgan ro'yxat bilan: [10, 20, 4]
Funksiyaning sukut qiymati: (None,)
=== Lug'at bilan ham xuddi shunday ===
{'a': 1}
{'a': 1, 'b': 2}
=== Xavfsiz turlar ===
(0, '', (), None, True)qosh_xavfli.__defaults__ ([1, 2, 3],) bo'lib qoldi — sukut qiymatning o'zi o'zgardi.
Nima ko'rsatdi: 2.6-bo'lim. Bu tajribani bir marta o'tkazish — umr bo'yi eslab qolish uchun yetarli.
Misol 3 — None va falsy farqi
"""'Berilmagan' va 'bo'sh' — turli narsalar."""
def hisobot_notogri(soni=None, chegirma=None, izoh=None):
soni = soni or 1
chegirma = chegirma or 10
izoh = izoh or "Izoh yo'q"
return f"soni={soni}, chegirma={chegirma}%, izoh={izoh!r}"
def hisobot_togri(soni=None, chegirma=None, izoh=None):
soni = 1 if soni is None else soni
chegirma = 10 if chegirma is None else chegirma
izoh = "Izoh yo'q" if izoh is None else izoh
return f"soni={soni}, chegirma={chegirma}%, izoh={izoh!r}"
sinovlar = [
((), {}),
((0, 0, ""), {}),
((5, 20, "Tez"), {}),
((), {"chegirma": 0}),
]
print("=== ❌ `or` bilan ===")
for args, kwargs in sinovlar:
print(f" {args}{kwargs} → {hisobot_notogri(*args, **kwargs)}")
print("\n=== ✅ `is None` bilan ===")
for args, kwargs in sinovlar:
print(f" {args}{kwargs} → {hisobot_togri(*args, **kwargs)}")=== ❌ `or` bilan ===
(){} → soni=1, chegirma=10%, izoh='Izoh yo'q'
(0, 0, ''){} → soni=1, chegirma=10%, izoh='Izoh yo'q'
(5, 20, 'Tez'){} → soni=5, chegirma=20%, izoh='Tez'
(){'chegirma': 0} → soni=1, chegirma=10%, izoh='Izoh yo'q'
=== ✅ `is None` bilan ===
(){} → soni=1, chegirma=10%, izoh='Izoh yo'q'
(0, 0, ''){} → soni=0, chegirma=0%, izoh=''
(5, 20, 'Tez'){} → soni=5, chegirma=20%, izoh='Tez'
(){'chegirma': 0} → soni=1, chegirma=0%, izoh='Izoh yo'q'Ikkinchi va to'rtinchi qatorlar hal qiluvchi: foydalanuvchi ataylab chegirma=0 berdi. or versiyasi uni 10 ga almashtirdi — jimgina noto'g'ri natija.
Bunday xato eng xavflisi: dastur qulamaydi, faqat noto'g'ri javob beradi.
Nima ko'rsatdi: 2.2 va 2.8-bo'limlar.
Misol 4 — Amaliy dastur: foydalanuvchi profili
"""Foydalanuvchi profilini xavfsiz ko'rsatish."""
from typing import Any
FOYDALANUVCHILAR: dict[int, dict[str, Any]] = {
1: {"ism": "Ali", "yosh": 25, "shahar": "Toshkent", "telefon": "+998901234567"},
2: {"ism": "Vali", "yosh": None, "shahar": "", "telefon": None},
3: {"ism": "", "yosh": 0, "shahar": None, "telefon": ""},
}
def topish(user_id: int) -> dict[str, Any] | None:
"""Foydalanuvchini topadi, bo'lmasa None qaytaradi."""
return FOYDALANUVCHILAR.get(user_id)
def korsat(qiymat: Any, sukut: str = "— kiritilmagan —") -> str:
"""Qiymatni ko'rsatiladigan matnga aylantiradi.
None va bo'sh satr — 'kiritilmagan'.
0 — haqiqiy qiymat, ko'rsatiladi.
"""
if qiymat is None:
return sukut
if isinstance(qiymat, str) and not qiymat.strip():
return sukut
return str(qiymat)
def profil_chiqar(user_id: int) -> None:
foydalanuvchi = topish(user_id)
if foydalanuvchi is None:
print(f"\n❌ Foydalanuvchi #{user_id} topilmadi")
return
print(f"\n┌─ Foydalanuvchi #{user_id}")
print(f"│ Ism: {korsat(foydalanuvchi.get('ism'))}")
print(f"│ Yosh: {korsat(foydalanuvchi.get('yosh'))}")
print(f"│ Shahar: {korsat(foydalanuvchi.get('shahar'))}")
print(f"│ Telefon: {korsat(foydalanuvchi.get('telefon'))}")
print(f"│ Email: {korsat(foydalanuvchi.get('email'))}")
print(f"└─")
for user_id in [1, 2, 3, 99]:
profil_chiqar(user_id)┌─ Foydalanuvchi #1
│ Ism: Ali
│ Yosh: 25
│ Shahar: Toshkent
│ Telefon: +998901234567
│ Email: — kiritilmagan —
└─
┌─ Foydalanuvchi #2
│ Ism: Vali
│ Yosh: — kiritilmagan —
│ Shahar: — kiritilmagan —
│ Telefon: — kiritilmagan —
│ Email: — kiritilmagan —
└─
┌─ Foydalanuvchi #3
│ Ism: — kiritilmagan —
│ Yosh: 0
│ Shahar: — kiritilmagan —
│ Telefon: — kiritilmagan —
└─
❌ Foydalanuvchi #99 topilmadiDiqqat: 3-foydalanuvchining yoshi 0 — va u ko'rsatildi, chunki 0 haqiqiy qiymat. Agar if not qiymat: ishlatganimizda, u "kiritilmagan" bo'lib chiqardi.
Kodda ko'rish kerak:
dict[str, Any] | None— tur ishorasiNonebo'lishi mumkinligini aytadiif foydalanuvchi is None: return— erta chiqish.get()yo'q kalit uchunNoneberadikorsat()Noneva bo'sh satrni ajratadi,0ni saqlaydi
Nima ko'rsatdi: 2.2, 2.5, 2.7, 2.8-bo'limlar birgalikda.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"None == False" |
False. None falsy, lekin False bilan teng emas |
"None == 0" |
False. Turli obyektlar |
"if not x: None ni tekshiradi" |
0, "", [] ni ham ushlaydi. is None aniqroq |
"royxat.sort() saralangan ro'yxat qaytaradi" |
None. sorted() yangi ro'yxat qaytaradi |
"def f(x=[]) normal" |
Eng mashhur tuzoq. None ishlating |
"== None va is None bir xil" |
is tezroq va ishonchliroq |
"None da metodlar bor" |
Faqat sehrli metodlar. dir(None) — bo'sh |
"Har bir funksiya return yozishi kerak" |
Yozilmasa None qaytadi — bu normal |
"None — xato belgisi" |
Yo'q, u yaroqli qiymat. Xato uchun istisno bor |
6. Keng tarqalgan xatolar va yechimlari
1. AttributeError: 'NoneType' object has no attribute 'X'
Eng ko'p uchraydigan None xatosi.
ism = lugat.get("ism") # None bo'lishi mumkin
print(ism.upper()) # ❌Yechimlar:
if ism is not None:
print(ism.upper()) # ✅
print((ism or "").upper()) # ✅ sukut bilan
ism = lugat.get("ism", "") # ✅ boshidan sukut2. TypeError: 'NoneType' object is not subscriptable
malumot = qidirish() # None qaytardi
print(malumot[0]) # ❌3. TypeError: 'NoneType' object is not iterable
for x in olish_royxat(): # None qaytardi
... # ❌Yechim — funksiya doim ro'yxat qaytarsin:
def olish_royxat() -> list:
natija = qidirish()
return natija if natija is not None else []4. sort() natijasini ishlatish
saralangan = royxat.sort() # ❌ None
saralangan = sorted(royxat) # ✅
royxat.sort() # ✅ joyida saralaydi5. TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
yosh = lugat.get("yosh")
print(yosh + 1) # ❌ None + 1
yosh = lugat.get("yosh", 0) # ✅
print(yosh + 1)6. O'zgaruvchan sukut argument
def f(x=[]): # ❌ Ruff: B006
def f(x=None): # ✅
if x is None:
x = []7. None ni JSON'ga yozish
import json
print(json.dumps({"qiymat": None})) # {"qiymat": null}None JSON'da null bo'ladi — bu normal va kutilgan.
8. None ni satr bilan qo'shish
ism = None
print("Salom, " + ism) # ❌ TypeError
print(f"Salom, {ism}") # ✅ 'Salom, None' — ishlaydi
print(f"Salom, {ism or 'mehmon'}") # ✅ yaxshiroqf-satr None ni avtomatik "None" ga aylantiradi. Bu ba'zan yashirin xato bo'lishi mumkin.
7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 3.5-dars:
Nonefalsy, lekinFalseemas - 3.9-dars:
Noneni aylantirish —str(None)→'None' - 6-qism:
lugat.get(), ro'yxat metodlariningNoneqaytarishi - 7-qism: sukut argumentlar,
returnbo'lmagan funksiyalar - 8-qism:
__init__Noneqaytarishi shart - 9-qism:
Noneqaytarish vs istisno ko'tarish - 13-qism:
Optional,| None, tur toraytirish - 16-qism: JSON
null↔ PythonNone - 23-qism: ma'lumotlar bazasi
NULL↔None
8. Eng yaxshi amaliyotlar
is Noneyozing,== Noneemas. Tezroq, aniqroq, xavfsizroq.O'zgaruvchan sukut argument — hech qachon.
def f(x=None)va ichida yarating. Bu qoidada istisno yo'q."Berilmagan" va "bo'sh" ni ajrating.
is Nonebirinchisi uchun, truthiness ikkinchisi uchun.Noneqaytarish mumkinligini tur ishorasida bildiring.-> dict | None. Bu chaqiruvchini himoya qiladi.Ro'yxat qaytaruvchi funksiya
Noneemas, bo'sh ro'yxat qaytarsin. Chaqiruvchi tekshirishi shart bo'lmaydi..get()da sukut qiymat bering.lugat.get("kalit", 0)—Nonebilan hisoblashdan yaxshiroq.Noneyaroqli qiymat bo'lsa, sentinel ishlating.YOQ = object().Ruff'ga ishoning.
B006(o'zgaruvchan sukut) va boshqaNonebilan bog'liq muammolarni topadi.
9. Amaliy topshiriq
Vazifa 1: None ni tanib olish
Har birining natijasi nima?
1. print(print("x"))
2. [1, 2, 3].sort()
3. sorted([3, 1, 2])
4. {"a": 1}.get("b")
5. {"a": 1}.get("b", 0)
6. [].append(1)
7. None == False
8. None == None
9. bool(None)
10. type(None).__name__Javoblar
xchiqadi, keyinNoneNone[1, 2, 3]None0NoneFalseTrueFalse'NoneType'
Vazifa 2: Tuzoqni takrorlash
2-misoldagi qosh_xavfli ni yozing va besh marta chaqiring. Keyin __defaults__ ni chiqaring.
Savol: nega sukut qiymat o'zgardi?
Vazifa 3: Xatolarni tuzatish
1. def f(elementlar=[]):
elementlar.append(1)
return elementlar
2. saralangan = mening_royxatim.sort()
3. ism = malumot.get("ism")
print(ism.upper())
4. if qiymat == None:
...
5. def hisobla(x=None):
if not x:
x = 100
return x * 2Javoblar
1. def f(elementlar=None):
if elementlar is None:
elementlar = []
elementlar.append(1)
return elementlar
2. saralangan = sorted(mening_royxatim)
3. ism = malumot.get("ism", "")
print(ism.upper())
# yoki
ism = malumot.get("ism")
if ism is not None:
print(ism.upper())
4. if qiymat is None:
5. def hisobla(x=None):
if x is None: # 0 ni ushlamaydi
x = 100
return x * 2Vazifa 4: Xavfsiz funksiya
xavfsiz_bolish(a, b) funksiyasini yozing:
b0bo'lsaNoneqaytarsinayokibNonebo'lsaNoneqaytarsin- Aks holda
a / bqaytarsin - Tur ishoralari bo'lsin
Yechim
def xavfsiz_bolish(a: float | None, b: float | None) -> float | None:
"""Xavfsiz bo'lish. Bo'lib bo'lmasa None qaytaradi."""
if a is None or b is None:
return None
if b == 0:
return None
return a / b
for a, b in [(10, 2), (10, 0), (None, 5), (10, None), (0, 5)]:
print(f"{a} / {b} = {xavfsiz_bolish(a, b)}")10 / 2 = 5.0
10 / 0 = None
None / 5 = None
10 / None = None
0 / 5 = 0.0Diqqat: 0 / 5 0.0 qaytardi — None emas. if b == 0 faqat maxrajni tekshiradi.
Vazifa 5: Profil dasturini kengaytirish
4-misoldagi dasturga qo'shing:
yangilash(user_id, maydon, qiymat)funksiyasi- Foydalanuvchi topilmasa
Falseqaytarsin qiymatNonebo'lsa maydonni o'chirsin- Yangilashdan keyin profilni qayta chiqarsin
Vazifa 6: Sentinel naqshi
birinchi(iterable, sukut=...) funksiyasini yozing:
- Birinchi elementni qaytarsin
- Bo'sh bo'lsa va
sukutberilgan bo'lsa — uni qaytarsin - Bo'sh bo'lsa va
sukutberilmagan bo'lsa —ValueErrorko'tarsin Noneyaroqli sukut qiymat bo'lishi kerak
Yechim
_YOQ = object()
def birinchi(iterable, sukut=_YOQ):
"""Birinchi elementni qaytaradi."""
for element in iterable:
return element
if sukut is _YOQ:
raise ValueError("Bo'sh to'plam va sukut qiymat berilmagan")
return sukut
print(birinchi([1, 2, 3])) # 1
print(birinchi([], "yo'q")) # yo'q
print(birinchi([], None)) # None — yaroqli sukut qiymat
try:
birinchi([])
except ValueError as x:
print(f"ValueError: {x}")None ni sukut sifatida ishlatganimizda "berilmagan" va "None berilgan" ni ajrata olmasdik. object() bu muammoni hal qiladi (2.8-bo'lim).
Vazifa 7: O'ylash
Nega Python royxat.sort() ni None qaytaradigan qilib yaratdi? Yangi ro'yxat qaytarsa yaxshi bo'lmasmidi?
Javob
Bu — ataylab qilingan dizayn qarori.
Sabab: Python "joyida o'zgartirish" va "yangi obyekt yaratish" ni aniq ajratadi. Agar sort() ro'yxat qaytarsa, quyidagi kod noaniq bo'lardi:
yangi = royxat.sort()royxat o'zgardimi yoki yo'qmi? Ko'rinmaydi.
Hozirgi dizaynda:
royxat.sort() # aniq: joyida o'zgartirdi
yangi = sorted(royxat) # aniq: yangi ro'yxatBu — "Aniq yashirinlikdan yaxshi" Zen qoidasi (1.5-dars).
Yon foyda: None qaytarish xatoni darhol ko'rsatadi. saralangan = royxat.sort() keyin saralangan[0] yozsangiz, TypeError chiqadi va siz xatoni topasiz.
Nimani mustahkamlaydi: 2.1, 2.2, 2.3, 2.6, 2.8-bo'limlar.
Xulosa
Bu darsda None — "hech narsa" qiymatini o'rgandik.
Eng muhim uch fikr:
is Noneyozing,== Noneemas.None— yagona obyekt, shuning uchunisdoim to'g'ri, tezroq va ishonchliroq ishlaydi."Berilmagan" va "bo'sh" — turli narsalar.
if not x:0,"",[]ni ham ushlaydi. FaqatNoneni tekshirish uchunis Nonekerak. Bu farq jimgina noto'g'ri natijalarning keng tarqalgan manbai.O'zgaruvchan sukut argument — hech qachon.
def f(x=[])o'rnigadef f(x=None)va funksiya ichida yarating. Bu — Pythondagi eng mashhur tuzoq va u bir marta o'rganilsa, umr bo'yi qaytmaydi.
Keyingi darsda str — satrlar bilan tanishamiz. Bu — eng ko'p ishlatiladigan tur va Pythonda u juda boy imkoniyatlarga ega. 4-qism butunlay satrlarga bag'ishlanadi, lekin asosini shu darsda qo'yamiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!