Ачааллж байна...
Өмнөх хичээлд бид pipeline-ий бүх шатыг өөрсдөө бичсэн. Мөр уншдаг, цэвэрлэдэг, задалдаг, шүүдэг generator-ууд бидний асуудалд тусгайлан зориулагдсан байсан. Гэвч iterator-уудтай ажиллах зарим ажил ямар ч асуудалд дахин дахин гарч ирдэг. "Эхний арван элементийг ав", "хоёр жагсаалтыг нэг урсгал болгон залга", “1-ээс эхлэн хязгааргүй тоол” гэх мэт. Ийм ажил бүрт өөрийн generator бичих боломжтой, гэхдээ шаардлагагүй. Python эдгээр түгээмэл ажлын бэлэн, сайн шалгагдсан, хурдан хувилбаруудыг стандарт сандаа itertools нэртэй модуль болгон агуулдаг.
itertools бол “iterator tools” буюу “iterator-ийн хэрэгслүүд” гэсэн үгийн товчлол. Түүний бүх хэрэгсэл энэ бүлгийн гол зарчмыг дагадаг: тэд lazy, өөрөөр хэлбэл асуухад л ажилладаг, үр дүнгээ iterator хэлбэрээр буцаадаг. Тиймээс тэд бидний бичсэн generator-уудтай, generator expression-уудтай, файлтай, ямар ч iterable-тай саадгүй холбогдож, pipeline-ий шат болж чадна. Модуль нь C хэл дээр бичигдсэн тул ихэнх тохиолдолд бидний ижил үүрэгтэй Python generator-оос хурдан ажилладаг, гэхдээ энэ хичээлд бидний сонирхол хурд биш, тодорхой байдал.
Энэ хичээлийн хамрах хүрээг шударгаар хэлье. itertools-д хорь орчим хэрэгсэл бий бөгөөд тэдгээрийн зарим нь, тухайлбал groupby, product, combinations, тусдаа хичээл шаардахуйц нарийн. Бид гурвыг л судална: count, islice, chain. Эдгээр нь хамгийн их хэрэглэгддэг, бүлгийн өмнөх хичээлүүдтэй шууд холбогддог, мөн бусад хэрэгслийг ойлгох суурь болно. Зорилго нь "уншиж, хэрэглэж чаддаг" түвшин: бусдын кодонд эдгээрийг хараад ойлгох, өөрийн кодонд зөв газар хэрэглэх. Хичээлийн төгсгөлд бусад хэрэгслүүдийн нэрийг, хаана сурахыг заана.
Өмнөх хичээлийн талх нарийн боовны үйлдвэр рүүгээ буцъя. Одоог хүртэл бид конвейерийн ажилчин бүрийг өөрсдөө хөлсөлж, сургаж байсан. Гэтэл үйлдвэрийн салбарт зарим ажил хаа сайгүй давтагддаг: бүтээгдэхүүнд серийн дугаар дараалан наах, тодорхой тооны бүтээгдэхүүн тоолоод шугамыг зогсоох, хоёр өөр агуулахаас ирсэн гурилыг нэг туузанд нийлүүлэх. Тиймээс тоног төхөөрөмжийн компаниуд ийм ажлыг хийдэг бэлэн машинуудыг үйлдвэрлэдэг. Та тэр машиныг худалдаж аваад, туузан замынхаа хүссэн газарт залгахад л хангалттай.
itertools бол яг ийм бэлэн машинуудын каталог. count бол серийн дугаар наагч: хязгааргүй дараалсан тоо гаргадаг. islice бол тоологч хаалга: тодорхой тооны бүтээгдэхүүн өнгөрүүлээд хаагддаг. chain бол нийлүүлэгч: хэд хэдэн туузыг дараалан нэг туузанд нийлүүлдэг. Эдгээр машинууд таны конвейерийн бусад ажилчдын адил "төгсгөлөөс татах" зарчмаар ажилладаг тул тэдгээрийг хаана ч залгаж болно.
Хичээл 2.1-д бид хязгааргүй дугаар гаргадаг generator бичсэн, түүнийг while True дотор yield хийдэг байсан. Тэр үед бид хязгааргүй generator-ийг for loop-д шууд өгвөл хэзээ ч дуусахгүй гэдгийг хэлж, islice энэ асуудлыг цэвэрхэн шийддэг гэж амласан. Одоо тэр амлалтаа биелүүлье. Эхлээд count-тай танилцъя:
python
from itertools import count
ids = count(1001)
print(next(ids))
print(next(ids))
print(next(ids))
print(ids)1001
1002
1003
count(1004)count(1001) нь 1001-ээс эхлэн нэгээр нэмэгдэж, хязгааргүй тоолох iterator үүсгэнэ. Энэ бол Хичээл 2.1-ийн numbered generator-ийн тоолох хэсгийг яг давтдаг, зөвхөн бэлэн байдаг. Сүүлийн мөр сонирхолтой: count объект хэвлэгдэхдээ дараагийн гаргах утгаа харуулж байна. Энэ нь itertools-ийн бусад объектоос ялгаатай. Ихэнх нь <itertools.islice object at 0x...> гэх мэт ерөнхий бичлэгээр хэвлэгддэг. count хоёр дахь argument болгон алхам авдаг: count(0, 5) нь 0, 5, 10, 15, ... гэж тоолно. Алхам сөрөг эсвэл бутархай тоо ч байж болно.
Одоо islice. Энэ нь list-ийн slice буюу items[2:5] бичлэгийн lazy хувилбар бөгөөд ямар ч iterable дээр, тэр дундаа хязгааргүй iterator дээр ажилладаг. Хамгийн энгийн хэлбэр нь islice(iterable, n): эхний n элементийг өгөөд зогсоно.
python
from itertools import count, islice
first_five = islice(count(1001), 5)
print(list(first_five))[1001, 1002, 1003, 1004, 1005]count(1001) хязгааргүй ч islice тав дахь элементийн дараа StopIteration шидэж, list() зогсов. Хэрэв бид islice-гүйгээр list(count(1001)) гэж бичсэн бол програм гацаж, санах ой дүүрэх хүртэл тоо цуглуулсаар байх байсан. islice-ийн бүрэн хэлбэр нь list-ийн slice-тай ижил гурван тоо авдаг: islice(iterable, start, stop, step). Жишээлбэл islice(count(), 10, 20, 2) нь 10, 12, 14, 16, 18-ыг өгнө.
Trace: islice эх сурвалжаасаа хэдийг татдаг вэ
islice-ийн нэг нарийн чанарыг trace-ээр харъя. Хичээл 2.1-ийн numbered generator-ийг эх сурвалж болгоё.
python
from itertools import islice
def numbered(prefix):
n = 1
while True:
yield f"{prefix}-{n}"
n += 1
orders = numbered("ЗАХ")
first_three = islice(orders, 3)
print(list(first_three))
print(next(orders))['ЗАХ-1', 'ЗАХ-2', 'ЗАХ-3']
ЗАХ-4Алхам 1 (orders = numbered("ЗАХ")). Машин үүснэ, эхэндээ зогссон. prefix = "ЗАХ", n хараахан алга.
Алхам 2 (first_three = islice(orders, 3)). islice объект үүснэ. Түүний дотор орон зай хоёр зүйлийг санана: эх сурвалж нь orders, өгөх ёстой үлдсэн тоо нь 3. orders огт хөдлөөгүй. Энэ мөчид нэг ч дугаар үүсээгүй.
Алхам 3 (list() islice-ээс эхний удаа асуух). islice orders-оос асууна. orders сэрж, n = 1, "ЗАХ-1"-ийг гаргаад хөлдөнө. islice түүнийг дамжуулж, үлдсэн тоогоо 2 болгоно.
Алхам 4 (хоёр ба гурав дахь асуулт). Ижил замаар "ЗАХ-2", "ЗАХ-3" дамжина. orders n = 3 дээр yield мөрөнд хөлдсөн. islice-ийн үлдсэн тоо 0.
Алхам 5 (list() дөрөв дэх удаа асуух). islice үлдсэн тоо 0 гэдгийг харж, orders-оос асуухгүйгээр шууд StopIteration шиднэ. list() зогсоно. orders n = 3 дээр хөлдсөн хэвээр, "ЗАХ-4" хараахан үүсээгүй.
Алхам 6 (next(orders)). orders сэрж, n = 4 болоод "ЗАХ-4"-ийг гаргана.
Энэ trace хоёр чухал зүйлийг харуулж байна. Нэгдүгээрт, islice яг хэрэгтэй тоогоороо л асуудаг: гурван элемент хүссэн бол эх сурвалжаас гурвыг л татна, дөрөв дэхийг "нөөцөд" авдаггүй. Хоёрдугаарт, islice эх сурвалжаа хуваалцдаг: orders-ийн хөлдсөн төлөв islice дууссаны дараа ч хэвээр бөгөөд түүнийг дараа нь шууд ашиглахад яг тасарсан газраасаа үргэлжилсэн. Энэ бол Хичээл 1.3-т файлын гарчгийг next()-ээр уншаад, for loop үлдсэнийг уншсантай ижил санаа. islice бол iterator-ийн нэг хэсгийг "хэрчиж аваад", үлдсэнийг нь эзэнд нь буцаадаг хэрэгсэл.
Жишээ 1: count-ыг дугаарлагч болгох
count-ийн хамгийн түгээмэл бодит хэрэглээ бол өөр iterable-ийн элементүүдийг дугаарлах. Хичээл 1.2-оос танил zip() хоёр iterable-ийг хос хосоор нийлүүлдэг бөгөөд нэгнийх нь дуусахад зогсдог. Тэгэхээр хязгаартай жагсаалтыг хязгааргүй count-тай zip хийхэд count хэзээ ч асуудал үүсгэхгүй: жагсаалт дуусахад zip зогсоно.
python
from itertools import count
new_students = ["Бат", "Сараа", "Тэмүүлэн"]
for student_id, name in zip(count(2026001), new_students):
print(student_id, name)2026001 Бат
2026002 Сараа
2026003 ТэмүүлэнЭнэ нь Course 2-оос танил enumerate()-тэй төстэй харагдаж байгаа нь зөв. enumerate(new_students, start=2026001) ижил үр дүн өгнө, тэр нь бүр илүү уншигдахуйц. Тэгвэл count яагаад хэрэгтэй вэ? Ялгаа нь count-ыг нэг удаа үүсгээд олон газар хуваалцаж болдогт оршино. Өнөөдөр гурван оюутан, маргааш өөр жагсаалтаас дахиад хоёр оюутан бүртгэгдэхэд дугаар 2026001-ээс дахин эхлэх ёсгүй, 2026004-өөс үргэлжлэх ёстой:
python
from itertools import count
next_id = count(2026001)
for name in ["Бат", "Сараа", "Тэмүүлэн"]:
print(next(next_id), name)
for name in ["Нараа", "Болд"]:
print(next(next_id), name)2026001 Бат
2026002 Сараа
2026003 Тэмүүлэн
2026004 Нараа
2026005 Болдnext_id нэг ширхэг count объект бөгөөд хоёр loop түүнийг ээлжлэн ашигласан. Хоёр дахь loop дугаарыг тасарсан газраас нь үргэлжлүүлсэн нь өмнөх trace-ийн хуваалцах санаатай ижил. enumerate() loop бүрт шинээр эхэлдэг тул ийм хуваалцах ажлыг хийж чадахгүй.
Жишээ 2: chain — хэд хэдэн эх сурвалжийг нэг урсгал болгох
Өмнөх хичээлийн log pipeline ганц app.log файлтай ажилласан. Бодит системд log өдөр бүр шинэ файлд бичигддэг: app-2026-10-08.log, app-2026-10-09.log гэх мэт. Хоёр өдрийн алдааг шалгахын тулд хоёр файлыг нэг урсгал мэт уншмаар байна. chain яг үүнийг хийдэг: хэд хэдэн iterable авч, эхнийхийг дуустал гаргаад, дараа нь хоёр дахийг, гэх мэтээр үргэлжилнэ.
Lazy байдлыг харахын тулд өмнөх хичээлийн read_lines-д файл нээх, хаах үед чагнуур нэмье.
python
from itertools import chain
def read_lines(path):
print(f" [{path} нээлээ]")
with open(path, encoding="utf-8") as f:
for line in f:
yield line.rstrip("\n")
print(f" [{path} дууслаа]")
all_lines = chain(
read_lines("app-2026-10-08.log"),
read_lines("app-2026-10-09.log"),
)
print("chain бэлэн боллоо")
for line in all_lines:
print(line[:30])Файл бүр хоёр мөртэй гэж үзвэл гаралт иймэрхүү байна:
chain бэлэн боллоо
[app-2026-10-08.log нээлээ]
2026-10-08 17:42:10 INFO user=
2026-10-08 18:05:33 ERROR user
[app-2026-10-08.log дууслаа]
[app-2026-10-09.log нээлээ]
2026-10-09 08:15:02 INFO user=
2026-10-09 08:15:40 ERROR user
[app-2026-10-09.log дууслаа]line[:30] нь мөр бүрийн эхний 30 тэмдэгтийг л хэвлэж, гаралтыг товч байлгасан. Гаралтын дарааллыг анхааралтай харъя. “chain бэлэн боллоо” эхэнд хэвлэгдсэн: chain() дуудагдахад ямар ч файл нээгдээгүй. Хоёр read_lines машин үүссэн ч эхэндээ зогссон, chain тэдгээрийг зөвхөн дарааллаар нь санасан. for loop асуухад chain эхний машинаас асууж, тэр анх удаа сэрж файлаа нээв. Эхний файлын хоёр мөр дамжиж, эхний машин дуусахад chain түүний StopIteration-ийг гадагш гаргалгүй барьж, хоёр дахь машин руу шилжив. Тэр мөчид л хоёр дахь файл нээгдэв. Хоёр дахь машин дуусахад chain-д өөр эх сурвалж үлдээгүй тул StopIteration гадагш гарч, for loop зогсов.
Энэ нь chain хэзээ ч хоёр файлыг зэрэг нээлттэй байлгадаггүй гэсэн үг. Арван өдрийн log-ийг chain хийвэл аль ч мөчид ганцхан файл нээлттэй байна. Одоо chain-ийг өмнөх хичээлийн pipeline-ий эхний шат болгон залгахад бүх үлдсэн шатууд өөрчлөгдөхгүй:
python
all_lines = chain(
read_lines("app-2026-10-08.log"),
read_lines("app-2026-10-09.log"),
)
clean = (line for line in all_lines if line.strip())
records = (parse_line(line) for line in clean)
errors = (r for r in records if r["level"] == "ERROR")Үлдсэн гурван шат app.log-ийг уншиж байсантай яг адил, тэдгээр эх сурвалж нь нэг файл уу, хоёр файл уу, огт мэдэхгүй. Өмнөх хичээлд хэлсэн "шат бүр эх сурвалжаа мэддэггүй" гэсэн чанар энд бодит үр шимээ өгч байна.
Файлын нэрс жагсаалтад байгаа, тэдгээрийн тоо урьдчилан мэдэгдэхгүй үед chain-ийн хамтрагч chain.from_iterable хэрэгтэй. Энэ нь iterable-уудыг argument бүрт тусад нь биш, нэг iterable дотор хүлээн авдаг:
python
from itertools import chain
files = ["app-2026-10-07.log", "app-2026-10-08.log", "app-2026-10-09.log"]
all_lines = chain.from_iterable(read_lines(path) for path in files)Энд chain.from_iterable-д generator expression өгсөн. Файл бүрийн read_lines машин ч мөн chain хэрэгтэй үед л үүснэ. Гурван файл байна уу, гурван зуун файл байна уу, код ижил хэвээр, нэг удаад нэг л файл нээлттэй.
Жишээ 3: гурвууланг нэг pipeline-д
Одоо гурван хэрэгслийг нэг дор хэрэглэе. Хоёр өдрийн log-оос эхний хоёр алдааг олж, тус бүрт тайлангийн дугаар өгье.
python
from itertools import chain, count, islice
files = ["app-2026-10-08.log", "app-2026-10-09.log"]
all_lines = chain.from_iterable(read_lines(path) for path in files)
clean = (line for line in all_lines if line.strip())
records = (parse_line(line) for line in clean)
errors = (r for r in records if r["level"] == "ERROR")
first_two = islice(errors, 2)
for report_id, r in zip(count(1), first_two):
print(f"Тайлан #{report_id}: {r['time']} {r['message']}") [app-2026-10-08.log нээлээ]
Тайлан #1: 18:05:33 user=oyun action=export
[app-2026-10-08.log дууслаа]
[app-2026-10-09.log нээлээ]
Тайлан #2: 08:15:40 user=saraa action=paymentЭнэ pipeline-ий шат бүрийн үүргийг дээрээс доош уншъя. chain.from_iterable хоёр файлыг нэг мөрийн урсгал болгоно. Дараагийн гурван шат өмнөх хичээлээс танил. islice(errors, 2) нь хоёр алдааны дараа урсгалыг таслана. zip(count(1), ...) нь тайлан бүрт 1-ээс эхэлсэн дугаар өгнө. Мөр бүрийн тайлбартай эх сурвалжийн өгөгдөл таны файлаас хамаарч өөр гарна.
Гаралтын сүүлийн хэсгийг анзаараарай: хоёр дахь файлын “[... дууслаа]” мөр алга. islice хоёр алдааг өгсний дараа errors-оос дахин асуугаагүй тул хоёр дахь файлын үлдсэн мөрүүд уншигдаагүй, машин хөлдсөн хэвээр орхигдсон. Өмнөх хичээлийн Жишээ 2-ын эрт зогсолт энд ч бүхэл pipeline-д нэгэн зэрэг ажилласан. islice нь эрт зогсолтыг тодорхой тоогоор илэрхийлэх хамгийн цэвэр арга юм.
Бусад хэрэгслүүд, шударгаар
itertools-ийн үлдсэн хэрэгслүүдийн заримыг нэрээр нь мэдэж байх нь бусдын код уншихад тусална. cycle iterable-ийг хязгааргүй давтдаг, жишээлбэл ээлжийн хуваарьт. repeat нэг утгыг давтдаг. takewhile ба dropwhile нөхцөл үнэн байх хүртэл авдаг эсвэл алгасдаг. accumulate хуримтлагдсан нийлбэрийг гаргадаг, бидний Хичээл 2.1-ийн running_total-ын бэлэн хувилбар. pairwise хөрш хоёр элементийг хос болгодог. groupby дараалсан ижил элементүүдийг бүлэглэдэг, гэхдээ энэ нь өгөгдөл урьдчилан эрэмбэлэгдсэн байхыг шаарддаг нарийн хэрэгсэл. product, permutations, combinations нь хослол үүсгэдэг.
Мөн нэг онцгой нэр: Python 3.12-оос хойш itertools-д batched нэмэгдсэн бөгөөд энэ нь Хичээл 1.4-т бидний бичсэн Batches class-ийн ажлыг хийдэг. batched(students, 3) гэж бичвэл гурав гурваар нь багцлагдана, гэхдээ багц бүр list биш tuple байна. Тэгвэл бид яагаад тэр class-ийг бичсэн бэ? Учир нь зорилго нь багцлах биш, iterator протоколыг ойлгох байсан. Одоо та batched-ийн ард юу ажилладгийг мэдэж байна. Хэрэв таны Python 3.11 эсвэл түүнээс хуучин бол batched байхгүй, Python-ий хувилбараа python --version-оор шалгаж болно.
Бүх хэрэгслийн бүрэн тайлбар Python-ий албан ёсны баримт бичгийн itertools хуудсанд бий. Тэр хуудасны доод хэсэгт “Itertools Recipes” гэсэн хэсэг байдаг бөгөөд тэнд эдгээр хэрэгслийг хослуулан бүтээсэн олон хэрэгтэй жор жишээ бий. Энэ бүлгийн дараа та тэдгээрийг уншиж ойлгох бүрэн мэдлэгтэй боллоо.
Хүсвэл count-ийн алхмыг өөрчилж туршиж болно: count(10, -2), count(0.5, 0.25) зэргийг islice-тэй хамт хэрэглэж, эхний таван утгыг хараарай. Сонирхвол Жишээ 3-ын islice(errors, 2)-ийг islice(errors, 1, 3) болгож, эхний алдааг алгасаад дараагийн хоёрыг авч үзээрэй. Тэр тохиолдолд хэдэн файл нээгдэх вэ гэдгийг урьдчилан таамаглах нь сайн дасгал. Python 3.12 эсвэл түүнээс шинэ хувилбартай бол list(batched(range(7), 3))-ийг ажиллуулж, Хичээл 1.4-ийн Batches-ийн үр дүнтэй харьцуулж болно. Эдгээр бүгд санал бөгөөд дараагийн хичээлүүд үүнийг хийсэн гэж үзэхгүй.
Програм гацах ба KeyboardInterrupt. Хязгааргүй count-ыг хязгаарлагчгүйгээр хоослоход гарна: list(count(1)), sum(count()), эсвэл break-гүй for n in count():. Алдааны мессеж гарахгүй, програм зүгээр л зогсохгүй, санах ой аажмаар дүүрнэ. Ctrl+C дарахад traceback-ийн сүүлд “KeyboardInterrupt” гарна, энэ нь "гарын товчлуураар тасалсан" гэсэн утгатай, програмыг та өөрөө зогсоосон гэсэн мэдээ. Шийдэл нь хязгааргүй iterator-ийг үргэлж islice, zip-ийн хязгаартай хамтрагч, эсвэл break-тэй хамт хэрэглэх.
ValueError: Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize. “islice()-ийн индекс None эсвэл 0-ээс sys.maxsize хүртэлх бүхэл тоо байх ёстой” гэсэн утгатай. list-ийн slice-аас ялгаатай нь islice сөрөг индекс хүлээн авдаггүй: islice(gen, -3, None) ажиллахгүй. Шалтгаан нь логик: "төгсгөлөөс гурав дахь" гэдгийг мэдэхийн тулд төгсгөлийг мэдэх хэрэгтэй, гэтэл iterator хаана дуусахаа өөрөө ч мэддэггүй, хязгааргүй ч байж болно. Сүүлийн хэдэн элемент хэрэгтэй бол эхлээд list() болгох, эсвэл collections.deque(gen, maxlen=3) хэрэглэх нь сайн шийдэл.
islice дараа элемент алга болох. Мессежгүй алдаа. Trace-д бид islice эх сурвалжийг хуваалцдагийг харсан. Энэ нь эх сурвалж generator бол islice-ийн авсан элементүүд түүнээс бүрмөсөн гарна гэсэн үг. Хэрэв та preview = list(islice(records, 3)) гэж эхний гурвыг "харчихаад", дараа нь records-ийг бүхэлд нь боловсруулахыг оролдвол эхний гурав алга болсон байна. Эх сурвалж list бол энэ асуудал гарахгүй, учир нь islice list-ээс шинэ түгээгч авдаг. Хичээл 1.2-ын хайрцаг ба түгээгчийн ялгаа энд дахин чухал болж байна.
TypeError: ‘int’ object is not iterable, оройтож гарах. chain-д iterable биш зүйл өгвөл, жишээлбэл chain(names, 5), алдаа chain() дуудагдах мөчид биш, урсгал тэр argument-д хүрэх үед л гарна. Names-ийн бүх элемент амжилттай хэвлэгдсэний дараа гэнэт traceback гарах нь төөрөгдүүлж болно. Энэ бол lazy байдлын сөрөг тал: алдаа ч мөн "асуухад нь л" илэрдэг. Traceback-ийн мөрийн дугаар chain-ийг үүсгэсэн газрыг биш, давталтын газрыг заах тул chain-д өгсөн бүх argument-ийг шалгаарай.
NameError: name ‘islice’ is not defined. “islice гэдэг нэр тодорхойлогдоогүй” гэсэн утгатай. itertools-ийн хэрэгслүүд суурь нэрс биш тул импорт хийх шаардлагатай: from itertools import count, islice, chain. Эсвэл import itertools гэж модулиар импортлоод itertools.islice(...) гэж бичиж болно. Хоёр хэлбэр хоёулаа түгээмэл.
itertools бол iterator-уудтай ажиллах бэлэн, lazy хэрэгслүүдийн стандарт сан юм. count хязгааргүй дараалсан тоо гаргадаг бөгөөд нэг объектыг хуваалцаж олон газар тасралтгүй дугаар өгч болно. islice бол slice-ийн lazy хувилбар: ямар ч iterable, тэр дундаа хязгааргүйг таслах боломжтой, эх сурвалжаас яг хэрэгтэй тоогоор татаж, үлдсэнийг хөлдсөн хэвээр орхидог, сөрөг индекс хүлээн авдаггүй. chain хэд хэдэн iterable-ийг дараалан нэг урсгал болгодог бөгөөд эх сурвалж бүрийг зөвхөн ээлж нь ирэхэд л нээдэг. chain.from_iterable нь эх сурвалжуудын тоо урьдчилан мэдэгдэхгүй үед хэрэгтэй. Эдгээр хэрэгсэл бидний бичсэн generator-уудтай саадгүй холбогдож, pipeline-ий шат болдог. Ингээд Бүлэг 2 дуусч, generator бидний хувьд ид шид биш, бүрэн ойлгогдсон хэрэгсэл боллоо.
Дараагийн бүлэгт бид Түвшин 1-ийн сүүлийн хэсэг болох functional хэрэгслүүд рүү шилжинэ. Эхний хичээлд Python-ий хоёр сонгодог функц map ба filter-ийг судална. Бид тэдгээрийг Хичээл 1.2-т iterator буцаадаг гэдгээр нь л товч харсан. Одоо тэдгээрийг өнөөдрийн generator expression-тэй шударгаар харьцуулж, аль нь хэзээ илүү уншигдахуйц байдгийг хоёр чиглэлд нь харуулна. Энэ бол хурдны биш, кодын тодорхой байдлын тухай хичээл болно.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.