IlmHamroh
Python kursi/Asoslar6/14-dars21 daqiqa
Mundarija (23)

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:

python
print(print("salom"))       # None — print hech narsa qaytarmaydi
python
royxat = [3, 1, 2]
saralangan = royxat.sort()
print(saralangan)           # None ← kutilmagan!
python
lugat = {"ism": "Ali"}
print(lugat.get("yosh"))    # None — kalit yo'q

Va eng mashhur xato:

text
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.

python
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 obyekt

Bu — singleton naqshi (27-qism). Python ishga tushganda bitta None yaratadi va uni hamma joyda ishlatadi.

Yangi NoneType yaratib bo'lmaydi:

python
import types
types.NoneType()            # TypeError: cannot create 'NoneType' instances

Aynan shuning uchun is None to'g'ri usul:

python
if qiymat is None:          # ✅ eng tez va eng aniq
if qiymat == None:          # ⚠️ ishlaydi, lekin sekinroq va noto'g'ri uslub

is — 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:

python
class Gaalati:
    def __eq__(self, boshqa):
        return True         # hamma narsaga teng!

g = Gaalati()
print(g == None)            # True  — yolg'on
print(g is None)            # False — haqiqat

Bu — nazariy misol, lekin is None odatini shakllantirish uchun yaxshi sabab.

2.2. None falsy, lekin False emas

python
print(bool(None))           # False — falsy (3.5-dars)
print(None == False)        # False — lekin teng emas!
print(None == 0)            # False
print(None == "")           # False

None falsy, lekin u False, 0 yoki "" bilan teng emas.

Bu farq juda muhim:

python
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'ri

Qoida:

"Berilmagan" va "bo'sh" — turli narsalar. is None bilan birinchisini, truthiness bilan ikkinchisini tekshiring.

2.3. None qayerdan keladi

1. Funksiya return qilmasa

python
def salomlash(ism):
    print(f"Salom, {ism}!")
    # return yo'q

natija = salomlash("Ali")
print(natija)               # None

Pythonda har bir funksiya qiymat qaytaradi. return yozilmasa — None.

python
def bosh():
    pass

def bosh2():
    return

def bosh3():
    return None

# Uchalasi ham bir xil — None qaytaradi

2. O'zgartiruvchi metodlar

Bu — eng ko'p tuzoq beradigan manba:

python
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())       # None

Sabab — Python kelishuvi:

Obyektni joyida o'zgartiradigan metodlar None qaytaradi. Yangi obyekt qaytaradigan funksiyalar natijani qaytaradi.

python
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 qaytaradi

Bu kelishuv ataylab — sizni "o'zgartirdimmi yoki nusxa oldimmi?" degan savoldan qutqaradi.

3. Lug'at .get() metodi

python
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

python
import re

natija = re.search(r"\d+", "salom dunyo")
print(natija)               # None — raqam topilmadi

5. Sukut parametr qiymati

python
def hisobla(a, b=None):
    if b is None:
        b = 10
    return a + b

Bu — eng keng tarqalgan None ishlatilishi (2.6-bo'limda batafsil).

2.4. None bilan ishlash: AttributeError tuzog'i

Eng ko'p uchraydigan xato:

python
ism = None
print(ism.strip())
text
AttributeError: 'NoneType' object has no attribute 'strip'

None da hech qanday foydali metod yo'q:

python
print([m for m in dir(None) if not m.startswith("_")])
text
[]

Bo'sh — faqat sehrli metodlar bor.

Yechimlar:

python
# 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

python
def foydalanuvchi_topish(id):
    if id in BAZA:
        return BAZA[id]
    # implicit None

Chaqiruvchi har safar tekshirishi kerak va uni unutish oson.

Yaxshi: aniq va hujjatlashtirilgan

python
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

python
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:

python
lugat.get("kalit")          # None qaytaradi
lugat["kalit"]              # KeyError ko'taradi

Chaqiruvchi tanlaydi.

2.6. O'zgaruvchan sukut argument tuzog'i

Bu — Pythondagi eng mashhur tuzoq. Har bir dasturchi unga bir marta tushadi.

python
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.

python
def qosh(element, royxat=[]):
    ...

print(qosh.__defaults__)    # ([],) — funksiyada saqlanadi
qosh(1)
print(qosh.__defaults__)    # ([1],) — o'zgardi!

To'g'ri yechim — None naqshi:

python
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 — None ishlating va funksiya ichida yarating.

Ruff bu xatoni topadi: B006 ("mutable default argument").

2.7. None va tur ishoralari

python
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 sifatida

Optional[int] aynan int | None degani — "yo int, yo None".

Sukut qiymat bilan:

python
def salomlash(ism: str | None = None) -> str:
    if ism is None:
        return "Salom, mehmon!"
    return f"Salom, {ism}!"

Pylance endi tekshiradi:

python
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 — str

Bu — 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

python
if qiymat is None:
    ...
if qiymat is not None:
    ...

2. Sukut qiymat berish

python
# Faqat None uchun
qiymat = 10 if kirish is None else kirish

# Barcha falsy uchun (ehtiyot!)
qiymat = kirish or 10

3. Zanjirli xavfsiz kirish

python
# ❌ 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

python
yosh = malumot.get("yosh")                  # None bo'lishi mumkin
yosh = malumot.get("yosh", 0)               # sukut bilan
yosh = malumot.get("yosh") or 0             # ⚠️ 0 ni ham almashtiradi

5. Sentinel qiymat — None yaroqli qiymat bo'lganda

Ba'zan None — haqiqiy qiymat bo'lishi mumkin. Unda alohida belgi kerak:

python
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")                 # KeyError

object() — 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:

python
def keyinroq_yozamiz():
    ...             # `pass` o'rniga, "hali yozilmagan" ma'nosida

from typing import Protocol

class Interfeys(Protocol):
    def metod(self) -> str: ...

... — haqiqiy obyekt:

python
print(type(...))            # <class 'ellipsis'>
print(... is Ellipsis)      # True
print(bool(...))            # True — falsy EMAS

Qaysi birini tanlash:

python
# ❌ 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'sh

3. Tez ma'lumotnoma

Asosiy qoidalar

python
qiymat is None              ✅ doim shunday
qiymat == None              ❌ sekinroq, ishonchsizroq

if qiymat is None:          ✅ faqat None ni tekshiradi
if not qiymat:              ⚠️ 0, "", [] ni ham ushlaydi

Xususiyatlar

python
type(None)      → NoneType
bool(None)      → False
None == False   → False   (falsy, lekin teng emas)
None == 0       → False
dir(None)       → faqat sehrli metodlar

None qayerdan keladi

text
return yo'q funksiya
royxat.sort(), .append(), .clear()  — joyida o'zgartiruvchilar
lugat.get(yo'q_kalit)
re.search(topilmadi)

Sukut argument naqshi

python
def f(royxat=[]):           ❌ HECH QACHON
def f(royxat=None):         ✅
    if royxat is None:
        royxat = []

Tur ishorasi

python
def f(x: int | None = None) -> str | None: ...

4. Batafsil misollar

Misol 1 — None qayerdan keladi

python
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}")
text
=== 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: None

Eng muhim xulosa: royxat.sort() None qaytaradi. saralangan = royxat.sort() — klassik xato.

Nima ko'rsatdi: 2.3-bo'lim.

Misol 2 — Sukut argument tuzog'i

python
"""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()}")
text
=== ❌ 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

python
"""'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)}")
text
=== ❌ `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

python
"""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)
text
┌─ 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 topilmadi

Diqqat: 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 ishorasi None bo'lishi mumkinligini aytadi
  • if foydalanuvchi is None: return — erta chiqish
  • .get() yo'q kalit uchun None beradi
  • korsat() None va bo'sh satrni ajratadi, 0 ni 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.

python
ism = lugat.get("ism")      # None bo'lishi mumkin
print(ism.upper())          # ❌

Yechimlar:

python
if ism is not None:
    print(ism.upper())              # ✅

print((ism or "").upper())          # ✅ sukut bilan

ism = lugat.get("ism", "")          # ✅ boshidan sukut

2. TypeError: 'NoneType' object is not subscriptable

python
malumot = qidirish()        # None qaytardi
print(malumot[0])           # ❌

3. TypeError: 'NoneType' object is not iterable

python
for x in olish_royxat():    # None qaytardi
    ...                     # ❌

Yechim — funksiya doim ro'yxat qaytarsin:

python
def olish_royxat() -> list:
    natija = qidirish()
    return natija if natija is not None else []

4. sort() natijasini ishlatish

python
saralangan = royxat.sort()      # ❌ None
saralangan = sorted(royxat)     # ✅
royxat.sort()                   # ✅ joyida saralaydi

5. TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

python
yosh = lugat.get("yosh")
print(yosh + 1)                 # ❌ None + 1

yosh = lugat.get("yosh", 0)     # ✅
print(yosh + 1)

6. O'zgaruvchan sukut argument

python
def f(x=[]):                    # ❌ Ruff: B006
def f(x=None):                  # ✅
    if x is None:
        x = []

7. None ni JSON'ga yozish

python
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

python
ism = None
print("Salom, " + ism)          # ❌ TypeError
print(f"Salom, {ism}")          # ✅ 'Salom, None' — ishlaydi
print(f"Salom, {ism or 'mehmon'}")  # ✅ yaxshiroq

f-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: None falsy, lekin False emas
  • 3.9-dars: None ni aylantirish — str(None) → 'None'
  • 6-qism: lugat.get(), ro'yxat metodlarining None qaytarishi
  • 7-qism: sukut argumentlar, return bo'lmagan funksiyalar
  • 8-qism: __init__ None qaytarishi shart
  • 9-qism: None qaytarish vs istisno ko'tarish
  • 13-qism: Optional, | None, tur toraytirish
  • 16-qism: JSON null ↔ Python None
  • 23-qism: ma'lumotlar bazasi NULL ↔ None

8. Eng yaxshi amaliyotlar

  1. is None yozing, == None emas. Tezroq, aniqroq, xavfsizroq.

  2. O'zgaruvchan sukut argument — hech qachon. def f(x=None) va ichida yarating. Bu qoidada istisno yo'q.

  3. "Berilmagan" va "bo'sh" ni ajrating. is None birinchisi uchun, truthiness ikkinchisi uchun.

  4. None qaytarish mumkinligini tur ishorasida bildiring. -> dict | None. Bu chaqiruvchini himoya qiladi.

  5. Ro'yxat qaytaruvchi funksiya None emas, bo'sh ro'yxat qaytarsin. Chaqiruvchi tekshirishi shart bo'lmaydi.

  6. .get() da sukut qiymat bering. lugat.get("kalit", 0) — None bilan hisoblashdan yaxshiroq.

  7. None yaroqli qiymat bo'lsa, sentinel ishlating. YOQ = object().

  8. Ruff'ga ishoning. B006 (o'zgaruvchan sukut) va boshqa None bilan bog'liq muammolarni topadi.


9. Amaliy topshiriq

Vazifa 1: None ni tanib olish

Har birining natijasi nima?

python
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
  1. x chiqadi, keyin None
  2. None
  3. [1, 2, 3]
  4. None
  5. 0
  6. None
  7. False
  8. True
  9. False
  10. '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

python
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 * 2
Javoblar
python
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 * 2

Vazifa 4: Xavfsiz funksiya

xavfsiz_bolish(a, b) funksiyasini yozing:

  • b 0 bo'lsa None qaytarsin
  • a yoki b None bo'lsa None qaytarsin
  • Aks holda a / b qaytarsin
  • Tur ishoralari bo'lsin
Yechim
python
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)}")
text
10 / 2 = 5.0
10 / 0 = None
None / 5 = None
10 / None = None
0 / 5 = 0.0

Diqqat: 0 / 5 0.0 qaytardi — None emas. if b == 0 faqat maxrajni tekshiradi.

Vazifa 5: Profil dasturini kengaytirish

4-misoldagi dasturga qo'shing:

  1. yangilash(user_id, maydon, qiymat) funksiyasi
  2. Foydalanuvchi topilmasa False qaytarsin
  3. qiymat None bo'lsa maydonni o'chirsin
  4. Yangilashdan keyin profilni qayta chiqarsin

Vazifa 6: Sentinel naqshi

birinchi(iterable, sukut=...) funksiyasini yozing:

  • Birinchi elementni qaytarsin
  • Bo'sh bo'lsa va sukut berilgan bo'lsa — uni qaytarsin
  • Bo'sh bo'lsa va sukut berilmagan bo'lsa — ValueError ko'tarsin
  • None yaroqli sukut qiymat bo'lishi kerak
Yechim
python
_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:

python
yangi = royxat.sort()

royxat o'zgardimi yoki yo'qmi? Ko'rinmaydi.

Hozirgi dizaynda:

python
royxat.sort()               # aniq: joyida o'zgartirdi
yangi = sorted(royxat)      # aniq: yangi ro'yxat

Bu — "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:

  1. is None yozing, == None emas. None — yagona obyekt, shuning uchun is doim to'g'ri, tezroq va ishonchliroq ishlaydi.

  2. "Berilmagan" va "bo'sh" — turli narsalar. if not x: 0, "", [] ni ham ushlaydi. Faqat None ni tekshirish uchun is None kerak. Bu farq jimgina noto'g'ri natijalarning keng tarqalgan manbai.

  3. O'zgaruvchan sukut argument — hech qachon. def f(x=[]) o'rniga def 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.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
3.6-dars: None nima — IlmHamroh