Ачааллж байна...
Өмнөх хичээлд та list-ийг нэг өгүүлбэрээр "захиалж" сурсан. Тэр санаа бол Python-ы гүн гүнзгий загвар бөгөөд зөвхөн list-ээр хязгаарлагдахгүй. Яг ижил бичлэгээр dictionary ч бас үүсгэж болно, түүнийг dictionary comprehension гэж нэрлэдэг (богиноор dict comprehension). Энэ хичээлийн сайхан тал нь: та шинэ санаа сурахгүй, зөвхөн мэддэг санаагаа шинэ бүтэц дээр хэрэглэнэ. Тиймээс энэ хичээл өмнөхөөсөө хөнгөн байх болно.
Курс 1-ээс dictionary-г товч сануулъя. Dictionary бол түлхүүр (key) ба утга (value) хосуудын цуглуулга юм: {"болд": 25, "сараа": 30}. Энд "болд" бол key, 25 бол value. Та dictionary["болд"] гэж бичээд утгыг нь авдаг байсан. List нь дугаараар (index) хандаж байсан бол dictionary нь НЭРЭЭР ханддаг — энэ бол хоёрын гол ялгаа. Курс 1-ийн харилцагчийн дэвтэр яг ийм бүтэц дээр баригдсан байсан.
Одоо асуулт: хэрэв та dictionary-г loop-оор дүүргэж байсан бол — тэр кодыг бас нэг мөр болгож чадах уу? Хариулт нь тийм, бүрэн чадна.
Өмнөх хичээлд бид зөөгчид "цэсэн дээрх бүх хоолыг чанаж авчир" гэж захиалсан. Тэгвэл одоо арай өөр захиалга өгье: "цэсэн дээрх хоол бүрийн НЭР болон ҮНИЙГ хамт бичээд надад жагсаалт өгөөч."
Ялгаа нь юунд байна вэ? Эхний захиалгад та нэг зүйл (чанасан хоол) хүсэж байсан. Хоёр дахь захиалгад та ХОС зүйл хүсэж байна — нэр нь юу, тэр нэрэнд харгалзах утга нь юу. Dictionary comprehension бол яг ийм хос захиалга юм: элемент бүрээс НЭГ биш, ХОЁР зүйл гаргаж ирэхийг шаарддаг — key нь юу байх, value нь юу байх.
Тиймээс бичлэгийн ялгаа ч гэсэн яг тэрхүү нэг зүйл нэмэгдсэнд л оршино: дөрвөлжин хаалт нь буржгар хаалт болж, зүүн талын нэг илэрхийлэл нь хоёр илэрхийлэл, хооронд нь цэгтэй таслал болно.
Бидэнд нэрсийн жагсаалт байна. Нэр бүрийн уртыг агуулсан dictionary үүсгэхийг хүсэж байна — key нь нэр, value нь тэр нэрэнд хэдэн үсэг байгаа.
Танил аргаар:
python
neres = ["болд", "сараа", "төмөр"]
urt = {}
for ner in neres:
urt[ner] = len(ner)
print(urt)Мөр мөрөөр нь уншъя. Гурав дахь мөрөнд бид urt нэртэй ХООСОН dictionary үүсгэсэн — анзаараарай, хоосон list нь [] байсан бол хоосон dictionary нь {} байна. Дөрөв дэх мөрөнд танил loop эхэлж, neres доторх нэр бүрийг ээлжлэн ner хувьсагчид хийж байна. Тав дахь мөр бол гол хэсэг: urt[ner] = len(ner) гэдэг нь "urt dictionary дотор ner гэсэн түлхүүр үүсгээд, түүний утгыг len(ner) буюу нэрний урт болго" гэсэн үг. len() бол Курс 1-ээс танил функц — string-ийн үсгийн тоог өгдөг.
Хэвлэгдэх үр дүн:
{'болд': 4, 'сараа': 5, 'төмөр': 5}Одоо яг ижил үр дүнг нэг мөрөөр:
python
neres = ["болд", "сараа", "төмөр"]
urt = {ner: len(ner) for ner in neres}
print(urt)Үр дүн яг ижил:
{'болд': 4, 'сараа': 5, 'төмөр': 5}Хоёр дахь мөрийг нарийвчлан задалъя, учир нь энэ бол хичээлийн зүрх.
Хамгийн гадна талд буржгар хаалт { } байна. Энэ хаалт нь "энд dictionary үүснэ" гэж хэлж байна — яг л та {"болд": 25} гэж dictionary бичихдээ ашигладаг хаалт. List comprehension дөрвөлжин хаалттай байсан бол энд буржгар. Энэ бол хамгийн эхний, хамгийн харагдахуйц ялгаа.
Хаалт дотор баруун талд for ner in neres байна — яг л list comprehension-той адилхан, ямар ч өөрчлөлтгүй. Loop-ийн хэсэг өөрчлөгдөөгүй.
Зүүн талд ner: len(ner) байна. Энд цэгтэй таслал нь бүх ялгааг үүсгэж байна. Түүний зүүн талд байгаа зүйл (ner) нь key болно. Баруун талд байгаа зүйл (len(ner)) нь value болно. Loop эргэх бүрд Python энэ хоёр илэрхийллийг тооцоолж, гарсан хосыг шинэ dictionary-д автоматаар нэмнэ.
Тэгэхээр бүхэл бүтэн ялгааг хоёр өгүүлбэрээр хэлж болно: дөрвөлжин хаалтыг буржгараар солино, зүүн талын нэг илэрхийллийг key: value хэлбэрээр хоёр болгоно. Өөр юу ч өөрчлөгдөөгүй. Уншлагын дараалал ч ижил хэвээр: эхлээд for-ыг, дараа нь зүүн талыг унших.
Курс 1-ийн харилцагчийн дэвтрийн санааг сэргээе. Бидэнд барааны нэр ба үнийн dictionary байна. Одоо бүх үнийг 10 хувиар нэмэгдүүлсэн ШИНЭ dictionary үүсгэхийг хүсэж байна.
Танил аргаар:
python
unes = {"ном": 15000, "утас": 800000, "харандаа": 500}
shine_unes = {}
for baraa, une in unes.items():
shine_unes[baraa] = int(une * 1.1)
print(shine_unes)Энд unes.items() гэдэг Курс 1-ийн method гарч ирлээ. Тэр нь dictionary-г loop-оор явахад key ба value-г ХОЁУЛАНГ нь нэг зэрэг өгдөг — тиймээс for baraa, une in ... гэж хоёр нэр бичиж байна. baraa нь key (барааны нэр), une нь value (үнэ) болно. int(une * 1.1) нь үнийг 1.1-ээр үржүүлж (10 хувь нэмэгдүүлж), гарсан бутархай тоог int()-ээр бүхэл тоо болгож байна.
Одоо comprehension-оор:
python
unes = {"ном": 15000, "утас": 800000, "харандаа": 500}
shine_unes = {baraa: int(une * 1.1) for baraa, une in unes.items()}
print(shine_unes)Үр дүн:
{'ном': 16500, 'утас': 880000, 'харандаа': 550}Энд чухал зүйл: comprehension-ы эх сурвалж нь list байх шаардлагагүй. Энд бид ӨӨР DICTIONARY-ээс уншиж, шинэ dictionary үүсгэж байна. for baraa, une in unes.items() гэсэн хэсэг нь loop-ийн ердийн бичлэгээс өчүүхэн ч ялгаагүй.
List comprehension-той яг адилхан, dict comprehension-д ч if нэмж шүүж болно. Жишээ нь: зөвхөн 10,000 төгрөгөөс дээш үнэтэй бараануудыг л агуулсан dictionary үүсгэе.
python
unes = {"ном": 15000, "утас": 800000, "харандаа": 500, "дэвтэр": 3000}
unetei = {baraa: une for baraa, une in unes.items() if une > 10000}
print(unetei)Үр дүн:
{'ном': 15000, 'утас': 800000}if une > 10000 нь comprehension-ы хамгийн төгсгөлд, for хэсгийн ард орж байна — яг л list comprehension-той адил байрлал. Утга нь ижил: нөхцөл худал байвал тэр хосыг бүрэн алгасаж, шинэ dictionary-д огт оруулахгүй. Зүүн талын baraa: une нь ямар ч хувиргалт хийхгүй, зөвхөн байгаагаар нь дамжуулж байна — энэ бол цэвэр шүүлт.
Энэ бичлэг нь Бүлэг 6-д JSON өгөгдөл шүүхэд шууд ашиглагдана. Тэр үед unes жижиг гар бичмэл dictionary биш, харин файлаас уншсан бодит өгөгдөл байх ч бичлэгийн хэлбэр яг ижилхэн байна.
Энэ бол практикт хамгийн олон тохиолддог хэрэглээний нэг. Танд зэрэгцээ хоёр list байгаа — нэг нь нэрс, нөгөө нь оноо. Тэдгээрийг нэгтгэж dictionary болгохыг хүсэж байна.
python
neres = ["болд", "сараа", "төмөр"]
onoo = [85, 92, 78]
duen = {ner: o for ner, o in zip(neres, onoo)}
print(duen)Үр дүн:
{'болд': 85, 'сараа': 92, 'төмөр': 78}zip нь өмнөх хичээлд ч товч гарч байсан бөгөөд дараагийн хичээлд бүрэн үзнэ. Одоохондоо түүнийг "хоёр жагсаалтыг зэрэгцүүлж, хос хосоор нь өгдөг" гэж ойлгоод өнгөрөөрэй. Comprehension дотор for ner, o in zip(...) гэж ХОЁР нэр авч байгаа нь items()-тэй яг ижил бүтэц юм.
Дашрамд хэлэхэд, энэ тодорхой ажлыг Python илүү богиноор ч хийж чаддаг: dict(zip(neres, onoo)). Гэхдээ би зориудаар comprehension-оор бичсэн, учир нь comprehension-д та ямар ч хувиргалт, ямар ч шүүлт нэмж чадна. Жишээ нь зөвхөн 80-аас дээш оноотой хүмүүсийг сонгож, оноог нь хувь болгож харуулъя:
python
neres = ["болд", "сараа", "төмөр"]
onoo = [85, 92, 78]
sain = {ner: f"{o}%" for ner, o in zip(neres, onoo) if o >= 80}
print(sain)Үр дүн:
{'болд': '85%', 'сараа': '92%'}Энд f"{o}%" бол Курс 1-ээс танил f-string — хувьсагчийн утгыг string дотор шууд оруулах бичлэг. Тэгэхээр энэ нэг мөрөнд гурван зүйл зэрэг болж байна: хоёр жагсаалтыг зэрэгцүүлэх, 80-аас доош оноог шүүх, үлдсэн оноог string болгож хувиргах.
Заримдаа танд байгаа dictionary-г "эргүүлэх" хэрэгтэй болдог — key нь value болж, value нь key болно.
python
kod = {"монгол": "MN", "хятад": "CN", "орос": "RU"}
esreg = {utga: tulkhuur for tulkhuur, utga in kod.items()}
print(esreg)Үр дүн:
{'MN': 'монгол', 'CN': 'хятад', 'RU': 'орос'}Зүүн талд utga: tulkhuur гэж бичсэнийг анзаараарай — цэгтэй таслалын хоёр талыг зориудаар СОЛЬСОН. for хэсэгт нэрс нь ердийн дарааллаараа (tulkhuur, utga) байгаа ч зүүн талд тэднийг эсрэгээр нь тавьсан. Энэ бол comprehension-ы уян хатан байдлын сайхан жишээ: зүүн тал нь юу key, юу value болохыг БҮРЭН таны шийдвэрээр тодорхойлдог.
Гэхдээ энд нэг анхааруулга: dictionary-д key давхардаж болохгүй. Хэрэв анхны dictionary-д хоёр өөр key ижил value-тай байсан бол эргүүлсний дараа тэдний нэг нь алдагдана — сүүлчийнх нь өмнөхийг дарж бичнэ. Энэ нь алдаа өгөхгүй, чимээгүй тохиолдоно. Тиймээс key-value солихдоо value-нууд тань өвөрмөц эсэхийг эхлээд бодоорой.
Хичээлийн төгсгөлд гурав дахь төрлийг товч танилцуулъя. Set (олонлог) гэдэг бол Python-ы өөр нэг бүтэц бөгөөд түүнийг Бүлэг 5-д бүрэн үзнэ. Одоохондоо гурван зүйл мэдэхэд хангалттай: set нь давхардсан утга агуулдаггүй, эрэмбэ хадгалдаггүй, буржгар хаалтаар бичигддэг.
Set comprehension нь dictionary comprehension-той бараг ижил харагддаг — ганц ялгаа нь зүүн талд цэгтэй таслал БАЙХГҮЙ:
python
neres = ["болд", "сараа", "төмөр", "цэцэг", "болд", "сараа"]
urt_olonlog = {len(ner) for ner in neres}
print(urt_olonlog)Үр дүн:
{4, 5}Анзаараарай: жагсаалтад зургаан нэр байсан ч үр дүнд зөвхөн ХОЁР тоо байна. Учир нь болд ба цэцэг хоёулаа 4 үсэгтэй, сараа, төмөр хоёулаа 5 үсэгтэй, мөн болд, сараа хоёр давхардсан. Set нь давхардлыг автоматаар устгадаг тул зөвхөн өвөрмөц уртууд л үлдсэн.
Тэгэхээр буржгар хаалт дотор:
{key: value for ...} — цэгтэй таслалтай → dictionary үүснэ
{utga for ...} — цэгтэй таслалгүй → set үүснэ
Энэ ялгааг санаж яваарай, учир нь хоёулаа ижил хаалт хэрэглэдэг тул эхэндээ будлиантай санагдаж болно. Set-ийг бид Бүлэг 5-д зохих ёсоор нь үзнэ; одоохондоо comprehension-ы гэр бүлд ийм гишүүн байдгийг л мэдэж авахад хангалттай.
Хэрэв сонирхвол: neres = ["болд", "сараа", "төмөр"] жагсаалтаас {ner: ner.upper() for ner in neres} гэсэн dictionary үүсгээд хэвлээд үзээрэй. Гарах үр дүнг эхлээд толгойдоо таамаглаж бичээд, дараа нь ажиллуулж шалгах нь хамгийн үр дүнтэй арга.
Мөн хүсвэл: өөрийн Курс 1-д бичсэн харилцагчийн дэвтрийн кодыг нээгээд, тэндээс "хоосон dictionary үүсгээд loop-оор дүүргэсэн" хэсэг байвал comprehension болгож хувиргаад үзээрэй.
1. Цэгтэй таслал мартах
python
urt = {ner len(ner) for ner in neres} File "main.py", line 3
urt = {ner len(ner) for ner in neres}
^^^
SyntaxError: invalid syntaxSyntaxError: invalid syntax гэдэг нь "бичлэг буруу байна" гэсэн үг. Энд key ба value-г тусгаарлах цэгтэй таслал : дутуу байна. Dictionary comprehension-д тэр цэгтэй таслал ЗААВАЛ байх ёстой, эс тэгвээс Python таны бичсэн зүйлийг ойлгохгүй.
2. Санамсаргүйгээр set үүсгэх
python
urt = {len(ner) for ner in neres}
print(urt["болд"])Traceback (most recent call last):
File "main.py", line 4, in <module>
print(urt["болд"])
TypeError: 'set' object is not subscriptableTypeError: 'set' object is not subscriptable гэдэг нь "set объектод хаалтаар хандаж болохгүй" гэсэн үг. Шалтгаан нь: та цэгтэй таслал бичээгүй тул dictionary биш, SET үүссэн байна. Set-д key байхгүй тул urt["болд"] гэж хандах боломжгүй. Засвар: зүүн талдаа ner: len(ner) гэж key-value хос бичнэ.
3. items() мартах
python
shine = {baraa: une for baraa, une in unes}Traceback (most recent call last):
File "main.py", line 3, in <module>
shine = {baraa: une for baraa, une in unes}
ValueError: too many values to unpack (expected 2)ValueError: too many values to unpack (expected 2) гэдэг нь "хоёр утга авахыг хүлээж байсан ч илүү олон утга ирлээ" гэсэн үг. Шалтгаан нь: dictionary дээр шууд loop хийвэл Python зөвхөн KEY-үүдийг л өгдөг, key-value хосыг өгдөггүй. Тэгэхээр baraa, une гэж хоёр нэр авах гэж оролдоход key болох string-ийг үсэг үсгээр нь салгах гэж үзээд бүтэлгүйтэж байна. Засвар: unes.items() гэж бичнэ.
4. Key давхардах
python
neres = ["болд", "сараа", "болд"]
urt = {ner: len(ner) for ner in neres}
print(urt){'болд': 4, 'сараа': 5}Алдааны мессеж гарахгүй, гэхдээ гурван элементээс хоёр л үлдлээ. Dictionary-д key давхардаж чаддаггүй тул хоёр дахь болд нь эхнийхийг ЧИМЭЭГҮЙ дарж бичсэн. Ихэнх тохиолдолд энэ нь яг таны хүссэн зан төлөв, гэхдээ мэдэж байх нь чухал — comprehension таны өгөгдлийн тоог "нууцаар" цөөрүүлж болно.
Dictionary comprehension нь list comprehension-той яг ижил санаа, зөвхөн хоёр өөрчлөлттэй: дөрвөлжин хаалт → буржгар хаалт, нэг илэрхийлэл → key: value хос.
Үндсэн хэлбэр: {key: value for элемент in эх_сурвалж}.
Шүүхийн тулд төгсгөлд if нэмнэ, яг list comprehension шиг.
Dictionary-ээс уншихдаа .items() ашиглаж key ба value-г хамт авна.
Буржгар хаалт дотор цэгтэй таслалтай бол dictionary, цэгтэй таслалгүй бол set үүснэ.
Key давхардвал сүүлчийнх нь өмнөхийг чимээгүй дарж бичнэ.
Дараагийн хичээлд бид энэ хичээлд хоёр удаа гарч ирсэн zip-ийг зохих ёсоор нь үзнэ. Мөн enumerate гэдэг функцийг үзэх бөгөөд тэр нь Курс 1-д та ашиглаж байсан "тоолуур хувьсагч" гэдэг зуршлыг бүрмөсөн орлуулна. Хоёулаа loop бичих аргыг тань бүрмөсөн өөрчилнө.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.