Ачааллж байна...
Түвшин бүр өөрийн оргилтой: Түвшин 1-ийнх тоо таах тоглоом, Түвшин 2-ынх харилцагчийн дэвтэр байсан — өнөөдөр Түвшин 3-ынхыг барина: Хийх ажлын жагсаалт (to-do list) — ажил нэмдэг, жагсаадаг, хийж дуусгасныг хасдаг, тэгээд — энэ Түвшний гол бэлэг — бүгдийг файлд хадгалдаг тул программ хаагдсан ч, компьютер унтарсан ч жагсаалт чинь хэвээр байдаг программ. Өмнөх хоёр оргилоос юугаараа өөр вэ: тоглоом зугаацуулдаг, дэвтэр нь "мартдаг" байсан — энэ бол таны өдөр бүр жинхэнээсээ хэрэглэж болох анхны бүрэн хэрэгсэл: маргаашийн ажлаа орой нь бичээд, өглөө нь нээхэд хүлээж байдаг. Материалын тооллого — энэ төсөлд Түвшин 3-ын гурван том чадвар бүгд ажилд орно: traceback-аас айдаггүй байдал (барилгын явцад алдаа гарвал — мөрдөгчөөр нь угтана), try/except (файлын анхны гүйлтийн тор), файл (унших, бичих — хоёул!), дээр нь Түвшин 2-ын list, loop, function бүрэн бүрэлдэхүүнээрээ.
Нэг шинэ инженерийн санаа энэ барилгад бий — тэмдэглэлийн дэвтрээс ялгарах гол цэг нь: дэвтэр файл руугаа зөвхөн нэмдэг байсан ("a" горим — залгаад л явдаг); харин хийх ажлын жагсаалтаас хасдаг — "a"-гаар хасаж болохгүй биз дээ! Тиймээс өнөөдрийн архитектур өөр: жагсаалтыг санах ойд (list-д) авч ажиллаад, өөрчлөлт бүрийн дараа файл руу бүхэлд нь дахин бичнэ ("w" — тэглээд бичигч энд л зөв ажилдаа орно!): ширээн дээрээ ажиллаад, өөрчлөх бүрдээ шүүгээндээ бүтэн хувь хадгалдаг ажилтан. Энэ "ачааллах — ажиллах — хадгалах" гурвал бол Word-оос эхлээд бараг бүх бодит программын амьдралын хэв маяг: өнөөдөр та түүнийг дотроос нь барина.
Файл: ajil.py, өгөгдлийн файл: ajluud.txt — мөр бүр нэг ажил. Дөрвөн үйлдэл: нэмэх, харуулах, дуусгах (хасах), гарах. Function-ууд: ажлын гурав дээр нэмээд хоёр туслах — uншигч (файлаас list рүү) ба хадгалагч (list-ээс файл руу): яагаад туслахууд тусдаа вэ — уншилт программ эхлэхэд нэг удаа, хадгалалт өөрчлөлт бүрийн дараа хэрэгтэй: хоёул олон газраас дуудагдана — DRY зарчим function нэхэж байна.
python
# Хийх ажлын жагсаалт — Түвшин 3-ын төсөл
FILE_NER = "ajluud.txt"
def unshih():
try:
with open(FILE_NER, "r") as f:
aguulga = f.read()
except FileNotFoundError:
return []
ajluud = []
for mur in aguulga.split("\n"):
if len(mur) > 0:
ajluud.append(mur)
return ajluud
def hadgalah(ajluud):
with open(FILE_NER, "w") as f:
for ajil in ajluud:
f.write(ajil + "\n")unshih() — шүүгээнээс ширээнд: тортой уншилт (анхны гүйлтэд файл байхгүй — FileNotFoundError-т хоосон list гардуулна: return [] — "дэвтэр шинэ, жагсаалт хоосон" гэсэн утга: тор энд алдааг мэдэгдэл ч биш — утга болгож хувиргаж байна: эрт буцалтын хамгийн боловсронгуй дүр); дараа нь танил цуглуулагч — split("\n") + хоосон-мөрийн шүүлт + append: мөрүүд цэвэрхэн list болж гардуулагдана. Тэмдэглэлийн дэвтрийн уншигчтай харьцуулаарай: тэнд шууд хэвлэдэг байсан — энд гардуулдаг: Бүлэг 8-ын "return хоёр замыг нээдэг" зарчим — гардуулсан list-ийг хэвлэж ч, өөрчилж ч, тоолж ч болно: uншигч маань "харуулагч"-аас салж цэвэр зөөвөрлөгч болсноор олон ажилд хэрэглэгдэх боломжтой боллоо. hadgalah(ajluud) — урвуу зөөвөрлөгч: parameter-ээр list авч (энэ хоёр function-ыг parameter/return-тэй нь "цэвэр" барьж байгаагаа ажигла), "w"-гээр нээж — тэглээд — гишүүн бүрийг \n-тэй нь бичнэ: файл үргэлж "list-ийн яг одоогийн байдлын" толь болж шинэчлэгдэнэ: "w"-гийн арчигч зан энд аюул биш — зорилго.
python
def nemeh(ajluud):
ajil = input("Ямар ажил нэмэх вэ? ").strip()
if len(ajil) == 0:
print("Хоосон ажил нэмэхгүй")
return
ajluud.append(ajil)
hadgalah(ajluud)
print(f"Нэмэгдлээ: {ajil}")
def haruulah(ajluud):
if len(ajluud) == 0:
print("Жагсаалт хоосон байна — амарч болно!")
return
print(f"\n--- Хийх ажлууд ({len(ajluud)}) ---")
dugaar = 1
for ajil in ajluud:
print(f"{dugaar}. {ajil}")
dugaar = dugaar + 1
def duusgah(ajluud):
haruulah(ajluud)
if len(ajluud) == 0:
return
try:
dugaar = int(input("Хэддүгээр ажлыг дуусгав? "))
except ValueError:
print("Тоо оруулна уу")
return
if dugaar < 1 or dugaar > len(ajluud):
print(f"1-{len(ajluud)} хооронд сонгоно уу")
return
duussan = ajluud[dugaar - 1]
ajluud.remove(duussan)
hadgalah(ajluud)
print(f"Баяр хүргэе! Дууссан: {duussan}")Гурван function — гурван түүх. nemeh: хоосны эрт буцалт (дэвтрийн дадал), append, тэгээд шууд hadgalah — "өөрчлөлт бүрийн дараа хадгал" зарчмын анхны илрэл: программ хэзээ унтарсан ч хамаагүй — файл үргэлж сүүлийн байдалтайгаа. haruulah: хоосны халамжтай мэдэгдэл + дугаартай жагсаалт — танил тоолуур (энд "хоосон-мөрийн шүүлт" байхгүйг ажигла: unshih аль хэдийн цэвэрлэчихсэн list өгдөг — ажил хуваарилалтын үр шим: цэвэрлэгээ нэг л газар). duusgah — өнөөдрийн хамгийн "олон давхаргат" function: эхлээд haruulah-ыг дуудаж жагсаалтаа үзүүлнэ (function function-оо дуудаж байна — хэрэглэгч дугаар сонгохын тулд юу байгааг харах ёстой биз!); дараа нь давхар хамгаалалт: int()-ийн тор (Бүлэг 11-ийн стандарт — үсэг бичвэл унахгүй) + хүрээний if-шалгалт (list-ийн хичээлийн "шалгаагүй дугаар IndexError руу" сургамж — 1-ээс len хүртэл); тэгээд гүүр: ajluud[dugaar - 1] — хүний "1-ээс" тоолол ба индексийн "0-ээс" хоёрын хооронд -1 гүүр (цэсний жишээний танил тохируулга); remove + hadgalah + баяр хүргэсэн мэдэгдэл. Хоёр эрт буцалтын дараалал нарийн: тор эхэлж (тоо мөн үү?), хүрээ дараа нь (тоо нь таарах уу?) — асуултууд логик дарааллаараа.
python
ajluud = unshih()
print(f"Тавтай морил! Танд {len(ajluud)} ажил хүлээгдэж байна")
while True:
print("\n--- ХИЙХ АЖЛЫН ЖАГСААЛТ ---")
print("1 - Ажил нэмэх")
print("2 - Жагсаалт харах")
print("3 - Ажил дуусгах")
print("4 - Гарах")
songolt = input("Сонголт: ")
if songolt == "1":
nemeh(ajluud)
elif songolt == "2":
haruulah(ajluud)
elif songolt == "3":
duusgah(ajluud)
elif songolt == "4":
print("Амжилт хүсье!")
break
else:
print("1-4 хооронд сонгоно уу")Эхний мөр бол энэ архитектурын түлхүүр: ajluud = unshih() — программ эхлэх агшинд шүүгээнээс ширээнд бүх ажил ачаалагдана: unshih-ийн гардуулалт ажлын гол list болов — тэгээд түүнийг гурван function-д parameter-аар дамжуулж байна (харилцагчийн дэвтрээс сахилга нэг шат ахисан хэлбэр: function бүр "юун дээр ажиллахаа" гаднаас авдаг — уншихад ч, хожим өөрчлөхөд ч тодорхой). Мэндчилгээний мөр len-тэй f-string — тэмдэглэлийн дэвтрийн "өргөтгөл 2"-ын санаа энд суурилагдчихсан ирлээ. List function дотор append/remove-оор өөрчлөгдөхөд гаднах ajluud өөрөө өөрчлөгддөг (давталтын variable-ийн "хуулбар" урхитай андуурч болохгүй: тэнд гишүүний хуулбар байсан — энд савыг өөрийг нь дамжуулж байгаа: сав нэг л — нэрс нь хоёр газар) — энэ нарийн ялгааны гүн онол Бүлэг 14-ийн нутаг: өнөөдөртөө "ажиллаж байгаа" баримт хангалттай.
Ажиллуулж шалгая — ёслолын бүрэн тойрог: Run → "Танд 0 ажил хүлээгдэж байна" (тор ажиллав — файл байхгүй, хоосноос эхлэв) → 1-ээр гурван ажил нэм → 2 — гурвуулаа дугаартай жагсана → 3 — хоёрдугаарыг дуусга → 2 — хоёр үлдэв → 4-өөр гар. Одоо гол мөч: дахин Run — "Танд 2 ажил хүлээгдэж байна." Тэнд байна. Хасагдсан нь хасагдсан хэвээрээ, үлдсэн нь хүлээж байгаа хэвээрээ — программ чинь бүрэн утгаараа амьдралтай хамт явдаг хэрэгсэл боллоо.
(Дээрх гурван хэсгийг дарааллаар нь нэг файлд: FILE_NER + хоёр туслах → гурван ажлын function → ачаалалт + цэс. Бүтэн эх нь таны гурван хэсгийн яг нийлбэр тул энд дахин хэвлэхгүй — өөрөө угсарч байгаа нь ч энэ түвшний танд зохих даалгавар: угсраад Run — дээрх ёслолын тойргоо давт.)
Жаран мөр — Түвшин 3-ын толь: тор хоёр газар хоёр өөр дүрээр (FileNotFoundError → хоосон list болгож "утгажуулсан" нь, ValueError → эелдэг мэдэгдэл болгосон нь), файлын гурван горимын хоёр нь ("r" уншигчид, "w" хадгалагчид — "a" энд зориуд байхгүй: бүтэн-бичилтийн архитектур), Түвшин 2-ын list-loop-function бүрэн хүчээрээ. Тэгээд харилцагчийн дэвтрийн өр: түүнийг "мартдаггүй" болгох бүх арга одоо гарт чинь бий — unshih/hadgalah хосыг дэвтэрт буулгахад ганц бэрхшээл нь dictionary-г мөрүүд болгох арга (жишээ нь "нэр|дугаар" гэж нэг тэмдэгтээр зааглаад split("|")-ээр буцааж задлах) — тэр гүүрийг барих нь доорх өргөтгөлүүдийн "том" нь.
Нэг: Огноотой ажил. Өмнөх хичээлийн datetime — nemeh-ийн append-д f"{datetime.date.today()} — {ajil}" гэж нүхэлбэл ажил бүр бүртгэгдсэн өдөртэйгөө: "энэ ажил хэзээнээс хойш намайг хүлээгээд байгаа юм бэ" гэдэг үнэн нүүрээ харуулдаг болно.
Хоёр: random-той урам. Ажил дуусгах бүрд random.choice(["Мундаг!", "Гайхалтай!", "Дараагийнх нь хүлээж байна!", "Өнөөдөр бүтээмжтэй өдөр!"]) — магтаалын уутнаас санамсаргүй урам сугалж хэвлэ: randint-ийн list-хамаатан ажилдаа орж, программ чинь "амьтай" болно.
Гурав: Харилцагчийн дэвтрийн амлалт — жинхэнэ дипломын нэмэлт. Дээр дурдсан гүүрийг барь: devter.py-даа unshih/hadgalah хос нэмж, dictionary-гээ "нэр|дугаар" мөрүүд болгон хадгалдаг болго (бичихдээ for ner in harilzagchid: дотор f"{ner}|{harilzagchid[ner]}\n"; уншихдаа мөр бүрийг split("|") хийгээд hos[0], hos[1]-ээр толио сэргээ) — амжилттай бол та хоёр өөр өгөгдлийн бүтцийг файлтай гүүрдэж чаддаг боллоо гэсэн үг: Түвшин 3-ыг давсны биш эзэмшсэний гэрчилгээ.
Түвшин 3-ын дипломын ажил хамгаалагдав: файлд хадгалдаг, өдөр бүр хэрэглэж болох бүрэн хэрэгсэл — "ачааллах (эхлэхэд нэг удаа) — ажиллах (санах ойн list) — хадгалах (өөрчлөлт бүрд бүтэн бичилт)" гэсэн бодит программын архитектур.
"a" ба "w"-гийн хуваарь тодров: зөвхөн нэмдэг өгөгдөлд — "a" (тэмдэглэлийн дэвтэр); нэмж-хасдаг өгөгдөлд — санах ойд ажиллаад "w"-гээр бүтэн шинэчил (энэ төсөл).
Тор хоёр дүртэй ажиллав: FileNotFoundError → return [] (алдааг утга болгох), ValueError → мэдэгдэл + эрт буцалт; давхар хамгаалалтын дараалал: төрөл эхэлж, хүрээ дараа нь.
Туслах function-ууд (unshih/hadgalah) parameter/return-тэй "цэвэр" зөөвөрлөгчид — олон газраас дуудагдаж DRY-г хангана; ажлын function-ууд list-ээ гаднаас авна.
Хүний тоолол ба индексийн -1 гүүр, in/хүрээний шалгалтууд, strip-угаалга — гурван Түвшний дадлууд нэг барилгад нийлэв.
Ингээд Түвшин 3 бүрэн өндөрлөлөө — таны программууд одоо алдаанаас айдаггүй, унадаггүй, мартдаггүй боллоо. Өмнө чинь сүүлчийн Түвшин байна: Түвшин 4 — Том зураг: Python-ы хамгийн гүн бөгөөд хамгийн үзэсгэлэнтэй санаа — class ба object — таны string-ийн "авдар", огнооны "цэгэн асуултууд", бүр list өөрөө хаанаас ирдгийн нууц тэнд тайлагдана. Дараагийн хичээл кодгүй, цэвэр санааны хичээл байх болно — энэ сургалтын хамгийн "гүн ухааны" аялал: амрчихаад ирээрэй.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.