Python'da bir nechta qiymat qaytarish: 4 usul va misollar
Python'da bir nechta qiymat qaytarishning 4 usulini o'rganing: tuple'lar, named tuple'lar, dataclass'lar va dict'lar. Kod misollari va tezkor taqqoslash jadvali bilan.
Muallif: Kimberly Fessel
Dasturlash tillari bizga foydalanuvchi tomonidan aniqlanadigan funksiyalar yozish orqali takrorlanuvchi vazifalarni kichik o'zgarishlar bilan bajarishdek ajoyib imkoniyat beradi. Bunday funksiyalarni Python'da yaratishingiz va ular nol, bitta, ikkita yoki undan ko'proq qiymat qaytaradigan qilib loyihalashingiz mumkin.
Ushbu maqolada Python funksiyasidan bir nechta qiymat olishning bir qancha turli usullarini ko'rsatamiz. Har birining afzalliklarini taqqoslaymiz va oldini olish kerak bo'lgan bir nechta keng tarqalgan "tuzoq"lar haqida ogohlantiramiz. Keling, tezkor namoyishdan boshlaymiz.
Funksiyadan bir nechta qiymat qaytarish
Python'da funksiya aniqlash juda oddiy: def keyword'ini yozasiz va funksiyangizga nom berasiz. So'ng funksiyangiz nima qilishi kerakligi haqidagi ko'rsatmalardan iborat kod yozasiz, xohlasangiz esa return statement'i yordamida funksiyangiz ma'lumotni qaytaradigan qilishingiz mumkin. Quyida ikkita argument qabul qilib, chaqirilganda ularning yig'indisini qaytaradigan funksiyaning kod misoli keltirilgan:
def add_two(x, y):
total = x + y
return total
print(add_two(2, 3))
# Expected result:
# 5
Agar funksiyangiz bittadan ko'p natija qaytarishini istasangiz, return statement'ida qiymatlarni vergul bilan ajrating. Masalan, bu funksiya kiruvchi qiymatlarning ham yig'indisini, ham ko'paytmasini hisoblaydi:
def add_multiply_two(x, y):
total = x + y
product = x * y
return total, product
print(add_multiply_two(2, 3))
# Expected result:
# (5, 6)
Python qaytarilgan qiymatlarni avtomatik ravishda tuple'ga joylaydi. Bu tuple ikkala natijani ham siz ularni return'da sanab o'tgan tartibda saqlaydi. Agar qiymat faqat chaqiruvlar orasida saqlanib qolishi kerak bo'lsa, uni qaytarishdan ko'ra nonlocal keyword'i ko'pincha ma'qulroq bo'ladi.
Tuple bittadan ko'p qiymat qaytarishning standart va umuman olganda eng Pythonic usuli, ammo eslatib o'tishga arziydigan yana bir nechta yechim ham bor.

1-variant — Tuple
Python funksiyalari aynan bitta obyekt qaytaradi, shuning uchun bittadan ko'p qiymat olish uchun ularni kattaroq kolleksiyaga joylashingiz kerak bo'ladi. Ko'pincha bir nechta qiymat tuple sifatida qaytarilganini ko'rasiz. Built-in divmod() ham shunday ishlaydi: u bo'linma va qoldiqni bitta tuple sifatida qaytaradi. Tuple data type'i immutable bo'lib, elementlarning yaratilishda belgilangan tartibini saqlaydi — bu esa o'zaro bog'liq qiymatlarni birga joylash uchun juda mos keladi.
Bir nechta qiymat qaytarish uchun return statement'idan foydalaning
return'ga vergul bilan ajratilgan bir nechta qiymat yozishingiz mumkin. Python barcha qaytariladigan elementlaringizni o'z ichiga olgan tuple'ni siz uchun yashirin tarzda yaratadi, shuning uchun bu qiymatlarni qavslarga olishingiz mumkin, lekin shart emas.
Quyidagi analyze_text() nomli funksiya kiruvchi matn string'ining uzunligini, so'zlar sonini va katta harflardagi versiyasini qaytaradi:
def analyze_text(text):
length = len(text)
word_count = len(text.split())
upper = text.upper()
return length, word_count, upper
print(analyze_text("Now returning multiple values."))
# Expected result:
# (30, 4, 'NOW RETURNING MULTIPLE VALUES.')
Qaytarilgan tuple'ni bir nechta o'zgaruvchiga unpack qilish
Python qiymatlaringizni avtomatik ravishda tuple'ga joylagani uchun alohida qiymatlarga index pozitsiyasi orqali murojaat qilishingiz yoki ularga to'g'ridan-to'g'ri kirish uchun unpack qilishingiz mumkin. Har bir variantning kodi quyida:
- Natijaviy tuple'ni bitta o'zgaruvchiga saqlang va alohida elementlarga index pozitsiyasi orqali murojaat qiling.
# Option 1 - Save as a single item
summary = analyze_text("Now returning multiple values.")
print(f"There are {summary[1]} words in the string.")
# Expected result:
# There are 4 words in the string
- Darhol foydalanish uchun har bir qiymatni alohida saqlang.
# Option 2 - Save individuals
length, word_count, upper = analyze_text("Now returning multiple values.")
print(f"There are {word_count} words in the string.")
# Expected result:
# There are 4 words in the string
Bu variant sodda, tuzilmasi qat'iy bo'lgan qaytariladigan qiymatlar uchun yaxshi ishlaydi. Biroq yodda tuting: chap tomondagi vergul bilan ajratilgan o'zgaruvchilar soni qaytarilgan qiymatlar soniga teng bo'lishi kerak, aks holda Python ValueError ko'taradi. Bu yerda tartib muhimligiga ham e'tibor bering. Qaytarilgan tuple'da hech qanday yorliq bo'lmaydi. Xatolarning oldini olish uchun birinchi qiymatda uzunlik saqlanishini va hokazolarni eslab qolishingiz kerak bo'ladi.
2-variant — Named tuple
O'qilishini yaxshilash uchun bir nechta qiymatni named tuple ko'rinishida qaytarishni o'ylab ko'ring. namedtuple data type'i built-in collections module'idan keladi. U oddiy tuple'lar kabi immutable va tartibni saqlaydi, lekin shu bilan birga elementlarni dot notation orqali nomi bo'yicha topish imkonini ham beradi.
Bir nechta qiymatni named tuple'da saqlab, funksiyangiz uni bitta Python obyekti sifatida qaytaradigan qilishingiz mumkin. Quyida yana matn string'ini tahlil qiladigan kod keltirilgan, biroq endi natijalar named tuple'da saqlanadi:
from collections import namedtuple
Analysis = namedtuple("Analysis", ["length", "word_count", "upper"])
def analyze_text(text):
return Analysis(
len(text),
len(text.split()),
text.upper()
)
summary = analyze_text("Now returning multiple values.")
print(summary)
print(summary.length)
print(summary.word_count)
# Expected result:
# Analysis(length=30, word_count=4, upper='NOW RETURNING MULTIPLE VALUES.')
# 30
# 4
Named tuple'lar aniqlik muhim bo'lgan, tuzilmasi qat'iy vaziyatlar uchun yaxshi. Endi har bir elementning aniq pozitsiyasini eslab qolishingiz shart emas, chunki unga nomi orqali murojaat qila olasiz. Ular oddiy tuple'lar (tez, lekin pozitsiyaga asoslangan) va to'liq sinflar (moslashuvchan, lekin murakkabroq) o'rtasidagi yaxshi oraliq yechimdir.
3-variant — Murakkab qaytariladigan qiymatlar uchun dataclass
Tuple'lardan keyingi bosqichda dataclass'lar bir nechta qiymat qaytarishda kattaroq moslashuvchanlik beradi. Ular dataclasses module'idan keladi va ularni oddiy @dataclass decorator'i bilan aniqlashingiz mumkin. Ular tuzilmali obyektlar uchun mo'ljallangan, ammo named tuple'larga qaraganda ko'proq imkoniyat taqdim etadi.
Dataclass bilan analyze_text() mana bunday ko'rinishga ega bo'ladi:
from dataclasses import dataclass
@dataclass
class Analysis:
length: int
word_count: int
upper: str
def analyze_text(text):
return Analysis(
length=len(text),
word_count=len(text.split()),
upper=text.upper()
)
summary = analyze_text("Now returning multiple values.")
print(summary)
print(summary.length)
print(summary.word_count)
# Expected result:
# Analysis(length=30, word_count=4, upper='NOW RETURNING MULTIPLE VALUES.')
# 30
# 4
Tuple'lardan farqli o'laroq, dataclass obyektlari default holatda mutable, ya'ni ularning qiymatlarini yaratilgandan keyin o'zgartirishingiz mumkin.
summary.word_count = 10
print(summary)
# Expected result:
# Analysis(length=30, word_count=10, upper='NOW RETURNING MULTIPLE VALUES.')
Shuningdek, default qiymatlar kiritishingiz va hatto yanada murakkabroq xatti-harakat uchun method'lar qo'shishingiz ham mumkin.
4-variant — Dictionary
Dictionary'lar bitta funksiya chaqiruvidan bir nechta natija qaytarish uchun yana bir yechim beradi. Ular ma'lumotni key-value juftliklarida saqlaydi, shuning uchun ma'lumotni pozitsiya bo'yicha emas, balki tushunarli key'lar bo'yicha topishingiz mumkin. Dictionary'lar mutable, shuning uchun field'larni bemalol qo'shishingiz, o'chirishingiz yoki o'zgartirishingiz mumkin.
Masalan, analyze_text() funksiyasi chaqirilganda hisoblangan qiymatlar bilan ma'lumotlardan iborat dictionary qaytarishi mumkin:
def analyze_text(text):
return {
"length": len(text),
"word_count": len(text.split()),
"upper": text.upper()
}
summary = analyze_text("Now returning multiple values.")
print(summary)
print(summary["length"])
print(summary["word_count"])
# Expected result:
# {'length': 30, 'word_count': 4, 'upper': 'NOW RETURNING MULTIPLE VALUES.'}
# 30
# 4
Agar qaytariladigan tuzilmangiz qat'iy bo'lmasa yoki vaqt o'tishi bilan o'zgarishi mumkin bo'lsa, dictionary'larni sinab ko'ring. Ular ma'lumotlarni qayta ishlash vazifalarida va API'larda keng qo'llaniladi, chunki JSON'ga o'xshash natijaga tabiiy ravishda mos keladi.
Tezkor ma'lumotnoma: taqqoslash jadvali
Python'da bir nechta qiymat qaytarish uchun biz ko'rib chiqqan usullarni taqqoslash va farqlash uchun qulay jadval:
| Usul | Mutable/Immutable | Elementga murojaat | O'qilishi | Qo'llanish holati | Tuzoqlar |
|---|---|---|---|---|---|
| Tuple | Immutable | Pozitsiya | O'rtacha | Sodda, qat'iy qaytariladigan qiymatlar | Qiymatlarni ajratib olishda tartibni adashtirib yuborish oson |
| Named tuple | Immutable | Nomi bo'yicha (dot notation) yoki pozitsiya | Yuqori | Aniqlik muhim bo'lgan qat'iy tuzilma | Baribir qat'iy; tuzilmani oson o'zgartirib bo'lmaydi |
| Dataclass | Mutable (default holatda) | Nomi bo'yicha (dot notation) | Yuqori | Tuzilmali, o'zgarib boradigan qaytariladigan ma'lumotlar | Biroz ko'proq overhead |
| Dictionary | Mutable | Key bo'yicha (kvadrat qavslar) | Yuqori | Moslashuvchan yoki ixtiyoriy qaytariladigan qiymatlar, API uslubidagi ma'lumotlar | Key'larni noto'g'ri yozib qo'yish mumkin; tuzilma majburiy emas |
AI Tutor: Menga list'lar va generator'lar yordamida funksiyadan bittadan ko'p qiymat olishga oid Python misollarini ko'rsat.
Python funksiyalaridagi keng tarqalgan xatolar va best practice'lar
Natijalarni joylashning bunchalik ko'p usuli bo'lganda, kodingizda e'tibor berish kerak bo'lgan bir nechta jihat albatta topiladi. Xatolardan qochish va ma'lumotlar tuzilmalaringizdan maksimal foydalanish uchun quyidagi maslahatlarni yodda tuting. Return statement'i bo'lmagan funksiya None qaytaradi va uni unpack qilganda tuple o'rniga TypeError hosil bo'ladi.
Qaytarilgan qiymatlarni unpack qilishdagi nomuvofiqlik
Ehtimol, bu mavzudagi eng keng tarqalgan xato — qaytarilgan natijalarni unpack qilishga urinayotganda vergul bilan ajratilgan o'zgaruvchilarni juda kam yoki juda ko'p yozib qo'yish. Masalan, agar quyidagini yozsangiz:
a, b = func()
Python ikkita o'zgaruvchi — a va b uchun aynan ikkita qaytariladigan qiymat kutadi. Kutilganidan ko'p yoki kam bo'lsa, xato olasiz.
Funksiya aslida siz unpack qilganingizdan ko'proq qiymat qaytarsa, ValueError olasiz:
def func():
return 1, 2, 3
a, b = func()
# Expected result:
# ValueError: too many values to unpack (expected 2)
Xuddi shuningdek, funksiya juda kam natija qaytarsa ham xato olasiz:
def func():
return (1,)
a, b = func()
# Expected result:
# ValueError: not enough values to unpack (expected 2, got 1)
Agar ValueError olsangiz, o'zgaruvchilar soni qaytarilgan qiymatlar soniga tengligini qayta tekshiring.
Natijalarni o'tkazib yuborish uchun _ dan foydalanish
Agar qiymatlarni ajratib olishni tanlasangiz, funksiya qaytaradigan natijalar sonini aynan o'shancha o'zgaruvchiga tayinlashingiz kerak bo'ladi, ammo biror natija sizga kerak bo'lmasa, uni tashlab yuboriladigan _ o'zgaruvchisiga tayinlashingiz mumkin. Dasturchilar yakka pastki chiziqni sizni qiziqtirmaydigan qiymat uchun placeholder deb tushunadi.
Buni sinab ko'rish uchun, agar analyze_text() qaytargan matnimizning katta harfli versiyasi kerak bo'lmasa, uni _ ga tayinlashimiz mumkin:
def analyze_text(text):
length = len(text)
word_count = len(text.split())
upper = text.upper()
return length, word_count, upper
length, word_count, _ = analyze_text("You don't need this uppercase.")
print(word_count)
print(_)
# Expected result:
# 5
# "YOU DON'T NEED THIS UPPERCASE."
Ishlaydigan eng sodda tuzilmani tanlash
Taqqoslash jadvaliga qaramay, bu maqolada ko'rib chiqilgan variantlarning har birini qachon tanlash kerakligi haqida hali ham o'ylanib qolishingiz mumkin. Oxir-oqibat, loyihangizga mos keladigan eng sodda usulni tanlaganingiz ma'qul. Oddiy tuple'dan boshlang va kerak bo'lganda murakkablikni oshiring. Aniqroq aytganda:
-
Sodda, qat'iy natijalar uchun tuple'dan foydalaning
-
O'qilishi muhim bo'lganda named tuple'dan foydalaning
-
Keyinchalik field'lar yoki method'lar qo'shishni kutsangiz, tuzilmali ma'lumotlar uchun dataclass'dan foydalaning
-
Field'lar ixtiyoriy yoki dinamik bo'lganda dictionary'dan foydalaning
Xulosa
Bir nechta qiymat qaytarish kerak bo'lganda, Python bir qancha turli usullarni taklif qiladi. Yodda tuting: funksiyalar aynan bitta obyekt qaytaradi, shuning uchun qiymatlaringizni qandaydir kolleksiyaga joylashingiz kerak bo'ladi. Return statement'ida qiymatlaringizni vergul bilan ajrating, Python esa ularni avtomatik ravishda tuple'ga o'raydi. Qo'shimcha o'qiluvchanlik yoki moslashuvchanlik kerak bo'lsa, named tuple'lar yoki dataclass'larni ko'rib chiqing, field'lar ixtiyoriy bo'lganda yoki vaqt o'tishi bilan o'zgarishi mumkin bo'lganda esa dictionary'larga o'ting.
Qaytariladigan qiymatlaringizni qaysi usulda joylashga qaror qilmang, AI Tutor bilan muloqot qilib ko'proq narsa o'rganishingiz mumkin. Ushbu prompt sizga boshlash uchun yordam beradi: