Ачааллж байна...
Өмнөх хичээлд бид функцийг өөр функцэд утга мэт дамжуулах санааг map ба filter-ээр дамжуулан ашигласан. Энэ хичээлд тэр санаа Python-д хамгийн их хэрэглэгддэг газраа очно: key= argument. sorted(), min(), max() функцүүд болон list-ийн .sort() method бүгд энэ argument-ийг хүлээн авдаг. Энэ нь "элементүүдийг юугаар нь харьцуулах вэ" гэдгийг Python-д хэлэх арга юм. Сурагчдыг оноогоор эрэмбэлэх, хамгийн сүүлд нэвтэрсэн хэрэглэгчийг олох, бүтээгдэхүүнийг үнээр, дараа нь нэрээр эрэмбэлэх зэрэг өдөр тутмын олон ажил key функцээр шийдэгддэг.
key=-гүйгээр Python элементүүдийг шууд хооронд нь харьцуулдаг: тоог тоогоор, string-ийг үсгийн дарааллаар. Энэ нь энгийн жагсаалтад хангалттай, гэхдээ элементүүд dict эсвэл объект болоход Python тэдгээрийг яаж харьцуулахаа мэдэхгүй. Мөн string-ийг уртаар нь эсвэл том жижиг үсэг ялгахгүйгээр эрэмбэлэх зэрэг "өөр шалгуураар" эрэмбэлэх шаардлага гарна. key= функц элемент бүрийг харьцуулах утга руу хөрвүүлдэг. Python тэр утгуудыг харьцуулж эрэмбэлэх боловч эцсийн үр дүнд анхны элементүүд үлдэнэ.
Энэ хичээлийн хамгийн гүн хэсэг нь олон түвшний эрэмбэлэлт: "эхлээд оноогоор, оноо ижил бол нэрээр". Үүнийг tuple key-ээр шийддэг бөгөөд Python хоёр tuple-ийг хэрхэн харьцуулдгийг бид trace-ээр алхам алхмаар дагана. Мөн монгол хэлтэй ажилладаг хөгжүүлэгч бүрийн тулгардаг бодит асуудлыг шийднэ: Python-ий анхдагч эрэмбэлэлт Ө, Ү, Ё үсгүүдийг монгол цагаан толгойн буруу байранд тавьдаг. Key функц энэ асуудлыг цэвэрхэн засна.
Ангийн сурагчдыг биеийн жингээр нь эгнээнд жагсаах хэрэгтэй гэж төсөөлөөд үзээрэй. Багш сурагч хоёрыг дагалдуулж "чи түүнээс хүнд үү?" гэж харьцуулж болох ч жинг нүдээр тааж харьцуулах нь найдваргүй, удаан. Илүү ухаалаг арга бий: багш эхлээд сурагч бүрийг жинлээд, жинг нь жижиг карт дээр бичээд, тэр картыг сурагчийн гарт өгнө. Дараа нь сурагчдыг харьцуулахдаа хүн биш, картыг хардаг: "энэ картанд 42, тэр картанд 38". Эгнээ жагсаж дууссаны дараа картуудыг хураана. Эгнээнд хүмүүс зогсож байгаа, картууд биш.
key функц бол тэр жинлүүр. Python элемент бүрийн хувьд key функцийг нэг удаа дуудаж, үр дүнг карт мэт хадгална. Эрэмбэлэх явцад хэдэн ч харьцуулалт хийгдсэн, сурагчийг дахин жинлэхгүй, зөвхөн картыг харна. Эцэст нь картууд хаягдаж, эрэмбэлэгдсэн анхны элементүүд буцна.
Одоо картанд хоёр тоо бичигдсэн гэж бодъё: эхнийх нь анги, хоёр дахь нь жин. Багш эхлээд анги харьцуулна: 5-р анги 6-р ангиас өмнө. Хэрэв анги ижил бол л жинг харна. Энэ бол tuple key: Python эхний утгыг харьцуулж, ижил бол л дараагийнх руу шилждэг. Толь бичиг үгсийг яг ийм зарчмаар эрэмбэлдэг: эхний үсэг, ижил бол хоёр дахь үсэг, гэх мэт.
Нэрсийг анхдагч байдлаар ба уртаар нь эрэмбэлье.
python
names = ["Тэмүүлэн", "Бат", "Сараа", "Ган"]
print(sorted(names))
print(sorted(names, key=len))['Бат', 'Ган', 'Сараа', 'Тэмүүлэн']
['Бат', 'Ган', 'Сараа', 'Тэмүүлэн']Энэ жишээнд хоёр үр дүн санамсаргүй давхцлаа, тиймээс жагсаалтыг бага зэрэг өөрчилье:
python
names = ["Тэмүүлэн", "Ган", "Сараа", "Бат", "Ану"]
print(sorted(names))
print(sorted(names, key=len))['Ану', 'Бат', 'Ган', 'Сараа', 'Тэмүүлэн']
['Ган', 'Бат', 'Ану', 'Сараа', 'Тэмүүлэн']Эхний мөр үсгийн дарааллаар эрэмбэлэгдсэн. Хоёр дахь мөрөнд key=len өгсөн тул Python нэр бүрийн уртыг харьцуулав: 3 үсэгтэй гурван нэр эхэнд, 5 үсэгтэй "Сараа", 8 үсэгтэй "Тэмүүлэн" төгсгөлд. len-ийг хаалтгүйгээр өгснийг анзаараарай. Өмнөх хичээлийн map-тай адил бид функцийг дуудаагүй, нэрээр нь дамжуулсан.
Хоёр дахь мөрөнд нэг сонирхолтой зүйл бий. "Ган", "Бат", "Ану" гурвуулаа 3 үсэгтэй, тэдгээрийн картууд ижил. Python тэднийг хооронд нь хэрхэн эрэмбэлсэн бэ? Тэд анхны жагсаалтад ямар дарааллаар байсан, яг тэр дарааллаар үлдсэн: "Ган" хоёр дахь, "Бат" дөрөв дэх, "Ану" тав дахь байрлалд байсан. Энэ шинж чанарыг stability буюу тогтвортой байдал гэдэг: картууд ижил элементүүд хоорондоо анхны дарааллаа хадгалдаг. Python-ий эрэмбэлэлт үргэлж тогтвортой бөгөөд энэ баталгааг бид хичээлийн дунд ашиглана.
Trace: key функц хэдэн удаа дуудагддаг вэ
Жинлүүрийн зүйрлэлд "нэг удаа жинлэнэ" гэж хэлсэн. Үүнийг чагнуураар шалгая.
python
def name_length(name):
print(f" [{name}-ийн уртыг хэмжиж байна]")
return len(name)
names = ["Тэмүүлэн", "Ган", "Сараа", "Бат", "Ану"]
result = sorted(names, key=name_length)
print(result) [Тэмүүлэн-ийн уртыг хэмжиж байна]
[Ган-ийн уртыг хэмжиж байна]
[Сараа-ийн уртыг хэмжиж байна]
[Бат-ийн уртыг хэмжиж байна]
[Ану-ийн уртыг хэмжиж байна]
['Ган', 'Бат', 'Ану', 'Сараа', 'Тэмүүлэн']Алхам 1 (key тооцоолох шат). sorted() эхлээд элемент бүрийн хувьд name_length-ийг дарааллаар нь яг нэг удаа дуудна. Таван элемент, таван дуудлага. Санах ойд одоо таван "карт" бий: Тэмүүлэн → 8, Ган → 3, Сараа → 5, Бат → 3, Ану → 3.
Алхам 2 (эрэмбэлэх шат). Python картуудыг хооронд нь харьцуулж эрэмбэлнэ. Таван элементийг эрэмбэлэхэд хэд хэдэн харьцуулалт хийгддэг ч name_length дахин нэг ч удаа дуудагдахгүй, чагнуур юу ч хэвлээгүй нь үүнийг баталж байна. 3 картууд тогтвортой байдлын дүрмээр анхны дарааллаа хадгална.
Алхам 3 (картуудыг хаях шат). Картууд хаягдаж, эрэмбэлэгдсэн анхны string-үүд шинэ list-д буцна.
Энэ нь практикт чухал. Хэрэв таны key функц хүнд тооцоолол хийдэг бол, жишээлбэл файлын хэмжээг дискнээс уншдаг бол, тэр нь элемент бүрт нэг л удаа ажиллана. Харьцуулалтын тоо элементийн тооноос хамаагүй их байж болох ч key тооцоолол хэзээ ч давтагдахгүй.
Жишээ 1: dict-уудыг нэртэй функц ба lambda-аар эрэмбэлэх
Бодит өгөгдөл ихэвчлэн dict эсвэл объектын жагсаалт хэлбэртэй байдаг. Python dict-уудыг хооронд нь шууд харьцуулж чадахгүй тул key заавал хэрэгтэй.
python
students = [
{"name": "Сараа", "score": 88},
{"name": "Бат", "score": 95},
{"name": "Дорж", "score": 72},
]
def get_score(student):
return student["score"]
by_score = sorted(students, key=get_score, reverse=True)
for s in by_score:
print(s["name"], s["score"])Бат 95
Сараа 88
Дорж 72get_score бол dict-ээс оноог гаргадаг энгийн функц, жинлүүр маань. reverse=True нь буурах дарааллаар эрэмбэлэхийг заана. reverse key-тэй хамт хэрэглэгдэх бөгөөд key утгуудын харьцуулалтыг эсрэгээр нь хийдэг.
get_score шиг ганц мөр функцийг тусад нь тодорхойлох нь заримдаа илүүдэл санагдана. Энд lambda маш тохиромжтой:
python
by_score = sorted(students, key=lambda s: s["score"], reverse=True)Өмнөх хичээлд бид lambda-тай map-аас зайлсхийж, comprehension-ийг сонгосон. Тэгвэл key-д lambda яагаад зүгээр вэ? Учир нь map-д comprehension гэсэн илүү тод хувилбар байсан бол sorted-д тийм хувилбар байхгүй. key-д ямар нэг функц өгөх нь гарцаагүй бөгөөд түүнийг нэг удаа л хэрэглэх бол lambda хамгийн товч, хамгийн тод хэлбэр. key=lambda s: s["score"] нь “s бүрийг оноогоор нь” гэж шууд уншигддаг тул Python кодонд маш түгээмэл загвар юм.
Нэг шударга тэмдэглэл: стандарт сангийн operator модульд энэ ажлыг хийдэг бэлэн хэрэгсэл бий. from operator import itemgetter хийгээд key=itemgetter("score") гэж бичиж болно. Энэ нь lambda-тай яг ижил ажилладаг. Бусдын кодонд та үүнийг харж магадгүй тул нэрийг мэдэж байхад хангалттай. Lambda эсвэл itemgetter, аль нь ч зөв сонголт.
Жишээ 2: min ба max — хамгийнхийг олох
key= нь sorted-ээс гадна min ба max-д ч ажилладаг. Эдгээр нь бүх жагсаалтыг эрэмбэлэхгүйгээр зөвхөн хамгийн бага эсвэл хамгийн их элементийг олно.
python
users = [
{"name": "bat", "last_login": "2026-10-07 09:14"},
{"name": "saraa", "last_login": "2026-10-09 13:02"},
{"name": "dorj", "last_login": "2026-09-28 18:45"},
]
latest = max(users, key=lambda u: u["last_login"])
earliest = min(users, key=lambda u: u["last_login"])
print("Хамгийн сүүлд:", latest["name"])
print("Хамгийн удаан нэвтрээгүй:", earliest["name"])Хамгийн сүүлд: saraa
Хамгийн удаан нэвтрээгүй: dorjmax ба min бүтэн dict-ийг буцаасан, зөвхөн огноог биш. Энэ нь key-ийн ерөнхий дүрэм: key харьцуулах утгыг тодорхойлдог, үр дүн нь үргэлж анхны элемент. Хэрэв бид max(u["last_login"] for u in users) гэж бичсэн бол хамгийн сүүлийн огноо string-ийг л авах байсан, хэн гэдгийг алдах байсан.
Огноонуудыг string хэлбэрээр харьцуулсан нь зөв ажилласныг анзаараарай. Энэ нь огноо "он-сар-өдөр цаг:минут" гэсэн том нэгжээс жижиг рүү чиглэсэн, тэг дүүргэлттэй хэлбэрээр бичигдсэнтэй холбоотой. Ийм хэлбэрийн string-үүдийг тэмдэгт тэмдэгтээр нь харьцуулахад цаг хугацааны дараалалтай давхцдаг. Хэрэв огноо “9/10/2026” гэх мэт хэлбэрээр бичигдсэн бол string харьцуулалт буруу үр дүн өгнө, тийм үед key функц дотор огноо болгон хөрвүүлэх хэрэгтэй.
Хоосон жагсаалтад min ба max алдаа өгдөг. Үүнийг default= argument-аар урьдчилан сэргийлж болно: max(users, key=lambda u: u["last_login"], default=None) хоосон жагсаалтад None буцаана. Алдааны мессежийг Түгээмэл алдаанууд хэсэгт уншина.
Жишээ 3: монгол цагаан толгойн дарааллаар эрэмбэлэх
Одоо монгол хэлтэй ажилладаг хүн бүрт хэрэгтэй жишээ. Нэрсийн жагсаалтыг Python-ий анхдагч аргаар эрэмбэлье:
python
names = ["Өлзий", "Бат", "Үүрцайх", "Ган", "Ёндон", "Отгон"]
print(sorted(names))['Ёндон', 'Бат', 'Ган', 'Отгон', 'Үүрцайх', 'Өлзий']Энэ үр дүн монгол цагаан толгойн хувьд гурван газар буруу. "Ёндон" хамгийн эхэнд гарсан ч Ё нь Е-ийн дараа байх ёстой. "Өлзий" О-ийн дараа, "Отгон"-ы дараа шууд байх ёстой. "Үүрцайх" У-гийн дараа, хамгийн төгсгөлд биш. Мөн "Үүрцайх" ба "Өлзий" хоорондоо ч буруу дарааллаар байна.
Шалтгаан нь Python string-ийг тэмдэгт бүрийн Unicode дугаараар харьцуулдагт оршино. Unicode-д орос хэлний үндсэн 32 үсэг А-аас Я хүртэл дараалсан дугаартай. Харин Ё, Ө, Ү үсгүүд тэр мужийн гадна байрладаг: Ё нь А-аас өмнө, Ү ба Ө нь Я-гийн дараа, Ү нь Ө-өөс өмнө. Python-д алдаа байхгүй, тэр зүгээр л дугаараар харьцуулж байна. Гэвч монгол хэрэглэгчдэд энэ дараалал буруу харагдана.
Шийдэл нь key функц: үсэг бүрийг монгол цагаан толгой дахь байрлалаар нь сольж, тэр байрлалуудыг харьцуулах.
python
MN_ALPHABET = "АБВГДЕЁЖЗИЙКЛМНОӨПРСТУҮФХЦЧШЩЪЫЬЭЮЯ"
POSITION = {letter: index for index, letter in enumerate(MN_ALPHABET)}
def mongolian_key(word):
return [POSITION.get(ch, 99) for ch in word.upper()]
names = ["Өлзий", "Бат", "Үүрцайх", "Ган", "Ёндон", "Отгон"]
print(sorted(names, key=mongolian_key))['Бат', 'Ган', 'Ёндон', 'Отгон', 'Өлзий', 'Үүрцайх']Одоо дараалал зөв. Кодыг алхам алхмаар задалъя. MN_ALPHABET бол монгол кирилл цагаан толгойн 35 үсэг зөв дарааллаараа. POSITION бол dict comprehension-оор бүтээсэн хүснэгт бөгөөд үсэг бүрийг дугаартай нь холбоно: "А" → 0, "Б" → 1, ..., "Ё" → 6, ..., "О" → 15, "Ө" → 16, ..., "У" → 21, "Ү" → 22. mongolian_key функц үгийг эхлээд upper()-ээр том үсэг болгоно, ингэснээр "ө" ба "Ө" ижил байрлалтай болно. Дараа нь үсэг бүрийн байрлалыг list болгон буцаана. POSITION.get(ch, 99) нь цагаан толгойд байхгүй тэмдэгт, жишээлбэл зай, зураас, латин үсэг тааралдвал 99 гэсэн "хамгийн сүүлд" утга өгч, алдаа гаргахгүй.
Жишээлбэл "Отгон" → [15, 19, 3, 15, 14], "Өлзий" → [16, 12, 8, 9, 10]. Эхний тоонуудыг харьцуулахад 15 < 16 тул "Отгон" өмнө. Python list-уудыг хэрхэн харьцуулдаг вэ? Яг дараагийн жишээн дэх tuple-тэй адил: эхний элементээс эхлэн, ялгаатай элемент олдох хүртэл. Энэ key функц таны монгол хэлтэй бүх төсөлд дахин хэрэглэгдэх бодит хэрэгсэл юм.
Жишээ 4: олон түвшний эрэмбэлэлт tuple key-ээр
Одоо хичээлийн хамгийн чухал загвар. Сурагчдыг оноогоор буурах дарааллаар эрэмбэлэх, оноо ижил бол нэрээр өсөх дарааллаар.
python
students = [
{"name": "Сараа", "score": 88},
{"name": "Бат", "score": 95},
{"name": "Дорж", "score": 72},
{"name": "Ану", "score": 95},
{"name": "Ган", "score": 88},
]
ranked = sorted(students, key=lambda s: (-s["score"], s["name"]))
for s in ranked:
print(s["name"], s["score"])Ану 95
Бат 95
Ган 88
Сараа 88
Дорж 72key функц элемент бүрт хоёр утгатай tuple буцааж байна: хасах тэмдэгтэй оноо ба нэр. Хасах тэмдэг яагаад? Бид оноог буурах, нэрийг өсөх дарааллаар хүсэж байна. reverse=True бүх tuple-ийг эсрэгээр нь эргүүлэх тул нэр ч мөн буурах болно. Тоог сөрөг болгох нь зөвхөн тэр хэсгийг эргүүлнэ: 95 > 88, харин −95 < −88, тиймээс өсөх эрэмбэлэлтэд −95 эхэлж ирнэ.
Trace: tuple-уудыг харьцуулах нь
Алхам 1 (картууд бүтээгдэх). key функц таван удаа дуудагдаж, таван tuple үүснэ:
Сараа → (−88, "Сараа")
Бат → (−95, "Бат")
Дорж → (−72, "Дорж")
Ану → (−95, "Ану")
Ган → (−88, "Ган")
Алхам 2 (Бат ба Ану-г харьцуулах). (−95, "Бат") ба (−95, "Ану"). Python эхний элементүүдийг харьцуулна: −95 ба −95 ижил. Ялгаа олдоогүй тул хоёр дахь элемент рүү шилжинэ: "Бат" ба "Ану". "А" нь "Б"-ээс өмнө тул "Ану" < "Бат". Иймээс (−95, "Ану") нь бага, Ану өмнө зогсоно.
Алхам 3 (Ану ба Сараа-г харьцуулах). (−95, "Ану") ба (−88, "Сараа"). Эхний элементүүд: −95 ба −88. −95 бага тул шийдвэр энд гарна: Ану өмнө. Хоёр дахь элемент огт харагдсангүй. Энэ нь чухал: tuple харьцуулалт эхний ялгаа олдмогц зогсдог тул хоёр дахь түвшин зөвхөн тэнцэх үед л ач холбогдолтой.
Алхам 4 (Ган ба Сараа-г харьцуулах). (−88, "Ган") ба (−88, "Сараа"). Эхний элементүүд ижил, хоёр дахь руу: "Г" нь "С"-ээс өмнө. Ган өмнө.
Алхам 5 (Дорж). (−72, "Дорж")-ийн эхний элемент хамгийн их тул хамгийн сүүлд зогсоно.
Эцсийн дараалал: (−95, "Ану"), (−95, "Бат"), (−88, "Ган"), (−88, "Сараа"), (−72, "Дорж"). Картууд хаягдаж, анхны dict-ууд энэ дарааллаар буцна. Энэ бол яг жинлүүрийн зүйрлэлийн "анги, дараа нь жин" картын зарчим.
Хоёр дахь арга: тогтвортой байдлыг ашиглах
Хасах тэмдгийн арга зөвхөн тоонд ажилладаг, string-ийг сөрөг болгох боломжгүй. Хэрэв бид нэрээр буурах, дараа нь оноогоор өсөх дарааллаар эрэмбэлэх шаардлагатай бол яах вэ? Энд Анхны жишээний тогтвортой байдал хэрэг болно. Эрэмбэлэлтийг хоёр удаа хийнэ: эхлээд хоёр дахь шалгуураар, дараа нь эхний шалгуураар.
python
step1 = sorted(students, key=lambda s: s["name"])
ranked = sorted(step1, key=lambda s: s["score"], reverse=True)
for s in ranked:
print(s["name"], s["score"])Ану 95
Бат 95
Ган 88
Сараа 88
Дорж 72Үр дүн ижил. Эхний sorted нэрээр эрэмбэлсэн: Ану, Бат, Ган, Дорж, Сараа. Хоёр дахь sorted оноогоор эрэмбэлэхэд оноо ижил элементүүд, тухайлбал Ану ба Бат, тогтвортой байдлын дүрмээр өмнөх дарааллаа, нэрийн дарааллаа хадгалсан. reverse=True тогтвортой байдлыг эвддэггүй: Python оноо ижил элементүүдийг reverse үед ч анхны дарааллаар нь үлдээдэг. Энэ аргаар түвшин бүрт өөрийн reverse өгч болно. Ерөнхий дүрэм: олон шалгуураар эрэмбэлэхдээ хамгийн бага ач холбогдолтойгоос эхэлж, хамгийн чухлаар төгсгө. Шалгуур бүгд тоо эсвэл чиглэл нь ижил бол tuple key нэг мөрт, илүү товч. Чиглэл холимог, string буурах шаардлагатай бол олон шатлалт эрэмбэлэлт.
Хүсвэл mongolian_key-ийг өөрийн найз нөхөд, гэр бүлийн нэрсийн жагсаалт дээр туршиж, анхдагч sorted()-ийн үр дүнтэй харьцуулж үзээрэй. Ө, Ү, Ё-тэй хэдэн нэр байна, тэдгээр нь хаашаа шилжих вэ? Сонирхвол Жишээ 4-т гурав дахь түвшин нэмж болно, жишээлбэл оноо, нэр ижил бол бүртгэлийн дугаараар. Мөн mongolian_key-ийг Жишээ 4-ийн tuple key-тэй хослуулж key=lambda s: (-s["score"], mongolian_key(s["name"])) гэж бичвэл юу болохыг шалгах нь хичээлийн хоёр гол санааг нэгтгэх сонирхолтой туршилт. Эдгээр бүгд санал бөгөөд дараагийн хичээлүүд үүнийг хийсэн гэж үзэхгүй.
TypeError: ‘<’ not supported between instances of ‘dict’ and ‘dict’. “dict ба dict төрлийн объектуудын хооронд ‘<’ үйлдэл дэмжигдэхгүй” гэсэн утгатай. dict-уудын жагсаалтыг key-гүйгээр эрэмбэлэхэд гарна: sorted(students). Python хоёр dict-ийн аль нь "бага" болохыг мэдэхгүй. Шийдэл нь key өгч, харьцуулах утгыг заах: sorted(students, key=lambda s: s["score"]). Ижил мессеж таны өөрийн class-ийн объектууд дээр ч гарна. Түвшин 3-т бид class-уудыг өөрсдөө харьцуулагддаг болгох аргыг сурна.
TypeError: bad operand type for unary -: ‘str’. "Нэг талт хасах үйлдэлд ‘str’ буруу төрөл" гэсэн утгатай. Tuple key-д string утгыг хасах тэмдгээр эргүүлэх гэж оролдоход гарна: key=lambda s: (-s["name"], s["score"]). String-ийг сөрөг болгох боломжгүй. Шийдэл нь хичээлийн "хоёр дахь арга": тогтвортой эрэмбэлэлтийг хоёр шатаар хийх.
ValueError: max() iterable argument is empty. “max()-д өгсөн iterable хоосон байна” гэсэн утгатай. min()-ийн хувьд “min() iterable argument is empty”. Хоосон жагсаалтаас хамгийн их элементийг олох гэж оролдоход гарна. Ихэвчлэн өмнөх шүүлтүүр бүх элементийг хаясан, эсвэл generator аль хэдийн хоосорсон үед. Шийдэл нь default= argument: max(users, key=..., default=None). Ингэвэл хоосон үед None буцаж, та түүнийг if-ээр шалгаж болно.
TypeError: ‘<’ not supported between instances of ‘NoneType’ and ‘int’. “NoneType ба int төрлийн хооронд ‘<’ үйлдэл дэмжигдэхгүй” гэсэн утгатай. Нэг элементийн key утга None байхад гарна, жишээлбэл нэг сурагчийн оноо бүртгэгдээгүй. Python 3 None-ыг тоотой харьцуулахыг хориглодог. Шийдэл нь key функц дотор None-ыг шийдэх: key=lambda s: s["score"] if s["score"] is not None else -1 эсвэл эрэмбэлэхээс өмнө ийм элементүүдийг шүүх.
students = students.sort(...) хийсний дараа None болох. list-ийн .sort() method жагсаалтыг газар дээр нь эрэмбэлж, None буцаадаг. Харин sorted() шинэ list буцааж, анхныг өөрчлөхгүй. Хэрэв та .sort()-ийн үр дүнг хувьсагчид оноовол тэр хувьсагч None болно. Дараа нь түүн дээр давтахад “TypeError: ‘NoneType’ object is not iterable” гарна. Дүрэм: students.sort(key=...)-ийг ганцаар нь бич, эсвэл ranked = sorted(students, key=...). Хоёр хэлбэр хоёулаа key= ба reverse= хүлээн авдаг.
key= argument элемент бүрийг харьцуулах утга руу хөрвүүлдэг функц хүлээн авдаг бөгөөд sorted(), min(), max(), list.sort() бүгд түүнийг дэмждэг. key функц элемент бүрт яг нэг удаа дуудагдаж, үр дүн нь "карт" мэт хадгалагдана, эцсийн үр дүнд анхны элементүүд үлдэнэ. key-д lambda ашиглах нь Python-ий хэвийн загвар, учир нь тодорхой comprehension хувилбар байхгүй. Python-ий эрэмбэлэлт тогтвортой: key ижил элементүүд анхны дарааллаа хадгалдаг. Олон түвшний эрэмбэлэлтийг tuple key-ээр хийнэ: Python эхний элементээс эхлэн харьцуулж, эхний ялгаа дээр зогсдог. Тоон утгыг хасах тэмдгээр эргүүлж, string буурах шаардлагатай бол тогтвортой эрэмбэлэлтийг хамгийн бага ач холбогдолтой шалгуураас эхлэн олон шатаар хийнэ. Монгол нэрсийг зөв эрэмбэлэхэд цагаан толгойн байрлалын key функц хэрэгтэй, учир нь Unicode дугаарлалт Ё, Ө, Ү-г буруу байранд тавьдаг.
Энэ хичээлийн key функцүүд элемент бүрт нэг л удаа ажилладаг байсан. Харин зарим функцийг ижил argument-аар олон удаа дуудах шаардлага гардаг бөгөөд тэр бүрт дахин тооцоолох нь дэмий ажил. Дараагийн хичээлд бид стандарт сангийн functools модулийг нээж, гурван хэрэгсэлтэй танилцана: argument-ийн нэг хэсгийг урьдчилан бэхэлдэг partial, бүх элементийг нэг утга болгон эвхдэг reduce, мөн энэ модулийн од болох lru_cache. Сүүлийнх нь функцийн үр дүнг санаж, давтан тооцоолохоос сэргийлдэг. Түүний нөлөөг бид рекурсив Fibonacci функц дээр хэмжиж, гайхалтай үр дүнг тоогоор харах болно.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.