Python-д шинэ жагсаалт үүсгэхдээ жагсаалтын ойлголтын тэмдэглэгээг ашиглах нь энгийн зүйл юм.(List comprehensions
)
- 5. Data Structures — List Comprehensions — Python 3.10.0 Documentation
- 6. Expressions — Displays for lists, sets and dictionaries — Python 3.10.0 Documentation
Энэ нийтлэлд бид эхлээд дараах зүйлсийг хэлэлцэх болно
- Жагсаалтын ойлголтын тэмдэглэгээний үндсэн төрөл
- Ойлголтын тэмдэглэгээг if-ээр нөхцөлт салаагаар жагсаана
- Гуравдагч операторуудтай хослуулах (хэрэв өөр боловсруулалт хийвэл)
zip()
,enumerate()
Эдгээртэй хослуулсан- үүрлэсэн жагсаалт оруулах тэмдэглэгээ
Дараа нь бид жагсаалтын ойлголтын тэмдэглэгээг жишээ кодоор тайлбарлах болно.
- оруулах тэмдэглэгээг тохируулах(
Set comprehensions
) - толь бичгийн оруулах тэмдэглэгээ(
Dict comprehensions
) - генераторын төрөл(
Generator expressions
)
- Жагсаалтын ойлголтын тэмдэглэгээний үндсэн төрөл
- Ойлголтын тэмдэглэгээг if-ээр нөхцөлт салаагаар жагсаана
- Гуравдагч операторуудтай хослуулах (хэрэв өөр боловсруулалт хийвэл)
- zip() болон enumerate()-ын хослол
- үүрлэсэн жагсаалт оруулах тэмдэглэгээ
- оруулах тэмдэглэгээг тохируулах(Set comprehensions)
- толь бичгийн оруулах тэмдэглэгээ(Dict comprehensions)
- генераторын төрөл(Generator expressions)
Жагсаалтын ойлголтын тэмдэглэгээний үндсэн төрөл
Жагсаалтын ойлголтын тэмдэглэгээг дараах байдлаар бичнэ.
[Expression for Any Variable Name in Iterable Object]
Жагсаалт, хэлхээ эсвэл муж зэрэг давтагдах объектын элемент бүрийг дурын хувьсагчийн нэрээр авч, илэрхийллээр үнэлдэг. Үнэлгээний үр дүнг элемент болгон харуулсан шинэ жагсаалтыг буцаана.
Мэдэгдэлтэй дүйцэхүйц жишээг өгөв.
squares = [i**2 for i in range(5)]
print(squares)
# [0, 1, 4, 9, 16]
squares = []
for i in range(5):
squares.append(i**2)
print(squares)
# [0, 1, 4, 9, 16]
Үүнтэй ижил процессыг map() ашиглан хийж болох боловч энгийн, ойлгомжтой байдлаар жагсаалтын ойлголтын тэмдэглэгээг илүүд үздэг.
Ойлголтын тэмдэглэгээг if-ээр нөхцөлт салаагаар жагсаана
Хэрэв боломжтой бол нөхцөлт салбарлалт. Postfix-д if-г дараах байдлаар бичнэ үү.
[Expression for Any Variable Name in Iterable Object if Conditional Expression]
Зөвхөн давтагдах боломжтой объектын нөхцөлт илэрхийлэл нь үнэн элементүүдийг илэрхийллээр үнэлж, үр дүн болох шинэ жагсаалтыг буцаана.
Та нөхцөлт илэрхийлэлд ямар ч хувьсагчийн нэрийг ашиглаж болно.
Мэдэгдэлтэй дүйцэхүйц жишээг өгөв.
odds = [i for i in range(10) if i % 2 == 1]
print(odds)
# [1, 3, 5, 7, 9]
odds = []
for i in range(10):
if i % 2 == 1:
odds.append(i)
print(odds)
# [1, 3, 5, 7, 9]
Үүнтэй ижил процессыг filter() ашиглан хийж болох боловч энгийн бөгөөд ойлгомжтой байдлаар жагсаалтын ойлголтын тэмдэглэгээг илүүд үздэг.
Гуравдагч операторуудтай хослуулах (хэрэв өөр боловсруулалт хийвэл)
Дээрх жишээнд зөвхөн шалгуурыг хангасан элементүүдийг боловсруулж, шалгуурыг хангаагүй элементүүдийг шинэ жагсаалтаас хассан болно.
Хэрэв та нөхцөл байдлаас шалтгаалан процессыг солихыг хүсвэл эсвэл нөхцөлийг хангахгүй байгаа элементүүдийг өөрөөр боловсруулахыг хүсвэл, өөрөөр хэлбэл гурвалсан операторыг ашиглана уу.
Python хэл дээр гурвалсан операторыг дараах байдлаар бичиж болно
Value When True if Conditional Expression else Value When False
Үүнийг доор үзүүлсэн шиг жагсаалтын ойлголтын тэмдэглэгээний илэрхийлэл хэсэгт ашигладаг.
[Value When True if Conditional Expression else Value When False for Any Variable Name in Iterable Object]
Мэдэгдэлтэй дүйцэхүйц жишээг өгөв.
odd_even = ['odd' if i % 2 == 1 else 'even' for i in range(10)]
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
odd_even = []
for i in range(10):
if i % 2 == 1:
odd_even.append('odd')
else:
odd_even.append('even')
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
Мөн үнэн ба худал утгыг дурын хувьсагчийн нэр ашиглан илэрхийлэл бичих боломжтой.
Хэрэв нөхцөл хангагдсан бол зарим боловсруулалт хийгдэнэ, эс тэгвээс анхны давтагдах объектын утга өөрчлөгдөхгүй үлдэнэ.
odd10 = [i * 10 if i % 2 == 1 else i for i in range(10)]
print(odd10)
# [0, 10, 2, 30, 4, 50, 6, 70, 8, 90]
zip() болон enumerate()-ын хослол
For мэдэгдэлд ихэвчлэн ашиглагддаг ашигтай функцууд нь олон давтагдах боломжтой zip() ба индексийн хамт утгыг буцаадаг enumerate() функцуудыг агуулдаг.
Мэдээжийн хэрэг, zip() болон enumerate()-г жагсаалтыг ойлгох тэмдэглэгээг ашиглах боломжтой. Энэ нь тусгай синтакс биш бөгөөд хэрэв та for мэдэгдэлтэй захидал харилцааг авч үзвэл хэцүү биш юм.
zip()-ийн жишээ.
l_str1 = ['a', 'b', 'c']
l_str2 = ['x', 'y', 'z']
l_zip = [(s1, s2) for s1, s2 in zip(l_str1, l_str2)]
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]
l_zip = []
for s1, s2 in zip(l_str1, l_str2):
l_zip.append((s1, s2))
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]
enumerate()-ийн жишээ.
l_enu = [(i, s) for i, s in enumerate(l_str1)]
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]
l_enu = []
for i, s in enumerate(l_str1):
l_enu.append((i, s))
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]
If ашиглах үед санаа нь өмнөхтэй ижил байна.
l_zip_if = [(s1, s2) for s1, s2 in zip(l_str1, l_str2) if s1 != 'b']
print(l_zip_if)
# [('a', 'x'), ('c', 'z')]
Элемент бүрийг шинэ элементийг тооцоолоход ашиглаж болно.
l_int1 = [1, 2, 3]
l_int2 = [10, 20, 30]
l_sub = [i2 - i1 for i1, i2 in zip(l_int1, l_int2)]
print(l_sub)
# [9, 18, 27]
үүрлэсэн жагсаалт оруулах тэмдэглэгээ
“Нуурлах” давталтын нэгэн адил жагсаалтын ойлголтын тэмдэглэгээг мөн үүрлэж болно.
[Expression for Variable Name 1 in Iterable Object 1
for Variable Name 2 in Iterable Object 2
for Variable Name 3 in Iterable Object 3 ... ]
Тохиромжтой болгох үүднээс мөрийн завсарлага, догол мөр нэмсэн боловч дүрмийн хувьд шаардлагагүй; тэдгээрийг нэг мөрөнд үргэлжлүүлж болно.
Мэдэгдэлтэй дүйцэхүйц жишээг өгөв.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
flat = []
for row in matrix:
for x in row:
flat.append(x)
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Мөн олон хувьсагч ашиглах боломжтой.
cells = [(row, col) for row in range(3) for col in range(2)]
print(cells)
# [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
Та мөн нөхцөлт салаалалт хийж болно.
cells = [(row, col) for row in range(3)
for col in range(2) if col == row]
print(cells)
# [(0, 0), (1, 1)]
Мөн давтагдах боломжтой объект бүрийн хувьд нөхцөлт салбарлах боломжтой.
cells = [(row, col) for row in range(3) if row % 2 == 0
for col in range(2) if col % 2 == 0]
print(cells)
# [(0, 0), (2, 0)]
оруулах тэмдэглэгээг тохируулах(Set comprehensions)
Жагсаалтын ойлголтын тэмдэглэгээний дөрвөлжин хаалтыг [] буржгар хаалт {} болгон өөрчилснөөр олонлог (тогтоосон төрлийн объект) үүсгэнэ.
{Expression for Any Variable Name in Iterable Object}
s = {i**2 for i in range(5)}
print(s)
# {0, 1, 4, 9, 16}
толь бичгийн оруулах тэмдэглэгээ(Dict comprehensions)
Толь бичгүүдийг (dict төрлийн объект) мөн ойлгох тэмдэглэгээгээр үүсгэж болно.
{}, мөн илэрхийллийн хэсэгт түлхүүр болон утгыг түлхүүр: утга гэж зааж өгнө.
{Key: Value for Any Variable Name in Iterable Object}
Түлхүүр болон утгын хувьд дурын илэрхийллийг зааж өгч болно.
l = ['Alice', 'Bob', 'Charlie']
d = {s: len(s) for s in l}
print(d)
# {'Alice': 5, 'Bob': 3, 'Charlie': 7}
Түлхүүр болон утгуудын жагсаалтаас шинэ толь бичиг үүсгэхийн тулд zip() функцийг ашиглана уу.
keys = ['k1', 'k2', 'k3']
values = [1, 2, 3]
d = {k: v for k, v in zip(keys, values)}
print(d)
# {'k1': 1, 'k2': 2, 'k3': 3}
генераторын төрөл(Generator expressions)
Жагсаалтын ойлголтын тэмдэглэгээний дөрвөлжин хаалт []-ийг дугуй хаалт () болгон ашигласан бол үүсгүүрийн оронд үүсгүүрийг буцаана. Үүнийг генераторын илэрхийлэл гэж нэрлэдэг.
Жагсаалтыг ойлгох тэмдэглэгээний жишээ.
l = [i**2 for i in range(5)]
print(l)
# [0, 1, 4, 9, 16]
print(type(l))
# <class 'list'>
Генераторын илэрхийллийн жишээ. Хэрэв та генератор()-г байгаагаар нь хэвлэвэл агуулгыг нь хэвлэхгүй, харин for хэллэгээр ажиллуулбал агуулгыг нь авч болно.
g = (i**2 for i in range(5))
print(g)
# <generator object <genexpr> at 0x10af944f8>
print(type(g))
# <class 'generator'>
for i in g:
print(i)
# 0
# 1
# 4
# 9
# 16
Генераторын илэрхийллүүд нь мөн if ашиглан нөхцөлт салбарлах, үүрлэх, түүнчлэн жагсаалтын ойлгох тэмдэглэгээг зөвшөөрдөг.
g_cells = ((row, col) for row in range(0, 3)
for col in range(0, 2) if col == row)
print(type(g_cells))
# <class 'generator'>
for i in g_cells:
print(i)
# (0, 0)
# (1, 1)
Жишээлбэл, олон тооны элемент бүхий жагсаалтыг жагсаалтын ойлгох тэмдэглэгээг ашиглан үүсгэж, дараа нь for хэллэгээр давтвал жагсаалтын ойлгох тэмдэглэгээг ашигласан тохиолдолд бүх элементүүдийг агуулсан жагсаалт эхэнд үүснэ. Нөгөөтэйгүүр, хэрэв та генераторын илэрхийлэл ашигладаг бол давталт давтагдах бүрт элементүүдийг нэг нэгээр нь үүсгэдэг бөгөөд ингэснээр ашигласан санах ойн хэмжээг бууруулдаг.
Хэрэв генераторын илэрхийлэл нь функцийн цорын ганц аргумент бол дугуй хаалт () орхигдуулж болно.
print(sum([i**2 for i in range(5)]))
# 30
print(sum((i**2 for i in range(5))))
# 30
print(sum(i**2 for i in range(5)))
# 30
Боловсруулалтын хурдны хувьд, бүх элементүүдийг боловсруулах үед жагсаалтын ойлголтын тэмдэглэгээ нь генераторын тэмдэглэгээнээс илүү хурдан байдаг.
Гэсэн хэдий ч, жишээ нь all() эсвэл any()-ээр дүгнэх үед үр дүн нь худал эсвэл үнэн байх үед тодорхойлогддог тул генераторын илэрхийлэлүүдийг ашиглах нь жагсаалтын ойлгох тэмдэглэгээг ашиглахаас илүү хурдан байж болно.
Tuple ойлгох тэмдэглэгээ байхгүй, гэхдээ хэрэв та генераторын илэрхийллийг tuple()-ийн аргумент болгон ашиглавал ойлгох тэмдэглэгээнд tuple үүсгэж болно.
t = tuple(i**2 for i in range(5))
print(t)
# (0, 1, 4, 9, 16)
print(type(t))
# <class 'tuple'>