Skip to content

Pythonning yangi imkoniyati match-case operatori

Agar siz if-elif-else yoki ichma-ich if shartlardan tozaroq va “pythonic” yechim izlayotgan bo'lsangiz, bu aynan siz uchun.

Avval Pythonda hammamiz biladigan holatni, ketma-ket shartlarni tekshirishni ko'rib chiqaylik. Tasavur qiling siz foydalanuvchining tizimdagi rolini aniqlaydigan dastur yozyapsiz. An'anaviy usulda bu quyidagicha bo'ladi:

1-misol. if, elif, else bilan.


if_elif_else.py
role = input('Rol kiriting: ')

if role == 'admin':
    print("Assalomu alaykum admin!")
elif role == 'moderator':
    print("Assalomu alaykum moderator!")
elif role == 'user':
    print("Assalomu alaykum user!")
else:
    print("Bunday rol mavjud emas")

Bu ishlaydi, lekin biroz noqulay. Agar rollar soni oshsa, elif lar ham ko'payib boradi va kodni o'qish ham, keyinchalik kengaytirish ham qiyinlashadi. Endi shu funksionallikni match-case yordamida ko'rib chiqamiz.

2-misol. match-case bilan.


match_case.py
role = input('Rol kiriting: ')

match role:
    case 'admin':
        print("Assalomu alaykum admin!")
    case 'moderator':
        print("Assalomu alaykum moderator!")
    case 'user':
        print("Assalomu alaykum user!")
    case _:
        print("Bunday rol mavjud emas")

Bu yerda kod ancha toza va tartibli bo'ladi. Keling endi bu yerda nima bo'layotganini o'rganamiz.

  • match kalit so'zidan keyin tekshiriladigan qiymat yoziladi. Bizni holatimizda bu role.
  • case orqali har bir ehtimoliy qiymat uchun alohida blok yoziladi. Bu yerda qiymatga mos case bloki ishga tushadi.
  • case _ esa barcha case larga mos kelmagan holatlar uchun ishlaydi xuddi else kabi.

Har bir case kodda alohida ko'rinadi va barcha shartlarni bir qarashda ko'rib tushunish mumkin bo'ladi.

Info

match case operatori Python 3.10 versiyadan boshlab qo'shilgan.

Pattern matching


match-case ning kuchli tomonlaridan biri pattern matching, ya'ni berilgan andoza bo'yicha tekshiradi. Aytaylik siz biror tizim bilan integratsiya qilishingizda ikkinchi tomon API xizmati quyidagicha javob qaytaradi:

response.json
1
2
3
4
5
6
{
  "type": "error",
  "code": 404,
  "message": "Not found",
  "result": null
}

Yuqoridagi APIdan kelgan javobni if-else orqali tekshirib ko'ramiz:

3-misol. pattern matching if-else bilan.


if_else_api.py
response = {
    "type": "error",
    "code": 404,
    "message": "Not found",
    "result": None
}

type = response.get("type")
result = response.get("result")
code = response.get("code")

if type == "error" and code == 404:
    print("Topilmadi")
elif type == "error":
    print(f"Xatolik yuz berdi. Kod: {code}")
elif type == "success":
    print("Muvaffaqiyatli:", result)
else:
    print("Noma'lum javob")

Bu kod hammasini to'g'ri bajaradi lekin bu yerda struktura emas, qiymatlar tekshirilyapdi.

type = response.get("type")
code = response.get("code")

get() metodlari ishlatilganda None natija olinishi mumkin, bu esa bizni qo'shimcha yana tekshiruvlarni qo'shishga majbur qiladi. Yana bir muamo ichma-ich holatlarda yana ortiqcha kodlar va tekshiruvlarni amalga oshirish kerak bo'ladi, bu esa kodni murakkablashtirib yuboradi.

match-case esa APIdan kelgan javob strukturasini qanday ekanini tekshiradi, ya'ni maydon borligini va qiymat mosligini bir vaqtda tekshiradi.

Keling endi match-case bilan qanday amalga oshirilishini ko'ramiz:

4-misol. pattern matching.


match_case.py
response = {
    "type": "error",
    "code": 404,
    "message": "Not found",
    "result": None
}

match response:
    case {"type": "error", "code": 404}:
        print("Topilmadi")
    case {"type": "error", "code": code}:
        print(f"Xatolik yuz berdi. Kod: {code}")
    case {"type": "success", "result": result}:
        print("Muvaffaqiyatli:", result)
    case _:
        print("Noma'lum javob")

Bu yerda {"type": "error", "code": 404} aniq andoza(pattern), code esa o'zgaruvchi sifatida qiymatni qabul qilib oladi. Buni o'zingiz ishlatib ko'rishingiz davomida code:404 ga boshqa qiymatlar bering, natija qanday o'zgarayotganini kuzating shunda tushunish osonroq bo'ladi.

Tuple va match-case


Masalan sizda foydalanuvchi va rol tuplelari bor, ularni roliga qarab ekranga chiqarishingiz kerak. Bu quyidagicha amalga oshiriladi:

5-misol. match-case tuple bilan.


match_tuple.py
roles = [('Sardor', 'admin'), ('Akmal', 'user'), ('Bekzod', 'moderator'), ('Sherzod', '')]

for role in roles:
    match role:
        case (admin, 'admin'):
            print(f"{admin} da barcha huquqlar mavjud.")
        case (moderator, 'moderator'):
            print(f"{moderator} da bazi huquqlar mavjud.")
        case (user, 'user'):
            print(f"{user} oddiy foydalanuvchi")
        case _:
            print("Nomalum rol.")

Natija:

Sardor da barcha huquqlar mavjud.
Akmal oddiy foydalanuvchi
Bekzod da bazi huquqlar mavjud.
Nomalum rol.

Bir nechta shartlarni birlashtirish


| operatori bilan bir nechta holatni bitta case ga birlashtirish mumkin. Bu if role == admin or role == moderator ga o'xshaydi.

6-misol.


match_case.py
1
2
3
4
5
6
7
8
9
role = input('Kiriting: ')

match role:
    case 'admin' | 'manager':
        print("Assalomu alaykum!")
    case 'user':
        print("Assalomu alaykum user!")
    case _:
        print("Bunday rol mavjud emas.")

Nozik joyi

match-case operatorida bilishimiz shart bo'lgan nozik bir jihat bor uni o'tkazib yuborsak kelajakda tushunarsiz holatlar keltirib chiqarishi mumkin. match-case ning vazifasi faqat qiymatlarni solishtirib tekshirish emas, balki tekshirib kerak bo'lganda boshqa o'zgaruvchiga qiymatni belgilab ham qo'yish. Quyida bunga misol ko'ramiz:

7-misol.


capture_pattern.py
1
2
3
4
5
6
role = input('Kiriting: ')
ADMIN = 'admin'

match role:
    case ADMIN:
        print(ADMIN)

Natija:

Kiriting: user
user

Yuqoridagi misolda bir qarashda case ADMIN qiymatni admin bilan solishtirgandek ko'rinadi aslida esa Python buni boshqacha talqin qiladi case ADMIN bu yerda yangi o'zgaruvchi deb qabul qilinadi. Ya'ni ADMIN = role ga teng bo'ladi bu har doim True bo'ladi va ADMIN ga role dagi qiymat yoziladi. Bu jarayon Capture pattern deb ataladi. Ya'ni match-case ichida qiymatni tekshirish emas, balki uni o'zgaruvchiga biriktirish (assign qilish).

Capture pattern muamosiga duch kelmaslik uchun quyidagilarni eslab qolish maqsadga muvofiq bo'ladi:

  • case name: ko'rinishda ishlatish yangi name o'zgaruvchi hosil qiladi va match da berilgan qiymatni name o'zgaruvchisiga biriktiradi.
  • case "name": ko'rinishi solishtirish bo'lib match da berilgan qiymat bilan "name" matnini solishtiradi.
  • case A.B: ko'rinishi esa har qanday class, modul ichidagi o'zgarmaslar (dotted name) bilan ishlaydi. Python match-caseda A.B (dotted name) ni solishtiriladigan qiymat deb qabul qiladi.

Yuqoridagi Capture pattern muamosida odatda Enumdan foydalanish tavfsiya qilinadi. Bu aniq qiymat bilan ishlashni ta'minlaydi va xatolarni kamaytiradi.

8-misol. Enum bilan.


Enum bilan tanish bo'lmasangiz bu maqola bilan tanishib chiqing.

match_enum.py
from enum import Enum

class Role(Enum):
    ADMIN = "admin"
    USER = "user"

role = Role(input('Kiriting: '))

match role:
    case Role.ADMIN:
        print('Admin')
    case Role.USER:
        print('User')

Kiritiladigan qiymat str, tekshiriladigan qiymat esa Enum turida bo'lganiligi uchun ikkalasini bir xil turga o'tkazish maqsadida Role(input('Kiriting: ')) qismi type casting qilindi. Aks holda har doim noto'g'ri natija olinishi mumkin edi.

Yuqoridagi misolda kichik bir kamchilik bor. Agar ekrandan kiritilgan qiymat Role turi atributlariga mos kelmasa xatolik sodir bo'ladi. Bu xatolikni try/except bilan quyida xal qilamiz:

9-misol. Enum.


match_enum.py
from enum import Enum


class Role(Enum):
    ADMIN = "admin"
    USER = "user"

try:
    role = Role(input('Kiriting: '))
except ValueError:
    role = None

match role:
    case Role.ADMIN:
        print('Admin')
    case Role.USER:
        print('User')
    case _:
        print('Noma`lum')

Tip

Bu yerda type castingni match ichida match Role(role): ko'rinishida ham qo'llash mumkin.

Xulosa


match-case Python 3.10 dan boshlab qo'shilgan kuchli imkoniyatlardan biri. if-elif-else ga nisbatan tozaroq, o'qilishi oson va strukturali kod yozish imkonini beradi. Pattern matching orqali esa murakkab ma'lumotlar (dict, tuple, ichma-ich strukturalar) bilan ishlash qulay. Qisqa qilib aytganda murakkab shartlar va strukturalar bilan ishlaganda kodni yanada aniq va ixcham qiladi.