Python filter'ni puxta o'rganing: sintaksis, misollar va best practice'lar
Ushbu batafsil qo'llanma bilan Python'ning filter() funksiyasini puxta o'zlashtiring. To'g'ri sintaksisni o'rganing, amaliy misollarni ko'ring va toza, samaraliroq kod yozish uchun keng tarqalgan tuzoqlardan qoching.
Muallif: Kimberly Fessel
Bugungi kunda onlayn ma'lumotlar shu qadar ko'pki, shovqin ichidan foydali signalni ajratib olish har qachongidan ham muhimroq bo'lib qoldi. Xo'sh, faqat sifatli ma'lumotlar o'tishini ta'minlash uchun o'sha VIP ro'yxatni qanday yaratib, unga qanday rioya qildirasiz? Python'ning built-in filter() funksiyasi xuddi qo'riqchidek ishlaydi: u eshik oldida har bir elementni tekshiradi va faqat shartingizda True deb baholanganlarini o'tkazadi.
Ushbu maqolada filter() nima ekanini va qanday ishlashini tushuntiramiz. Uni amalda ko'rish uchun ko'plab oddiy va murakkabroq misollar olasiz, shuningdek, uni list comprehension'lar kabi boshqa Pythonic filtrlash variantlari bilan taqqoslaymiz. Maqola oxirida bir nechta keng tarqalgan tuzoqlar haqida ham bilib olasiz, shunda kodingizdagi xatolarni filter() qilib tashlay olasiz.
Python'da filter() nima?
filter() — siz bergan shart asosida iterable'dan, ya'ni ustida loop qilish mumkin bo'lgan istalgan obyektdan elementlarni tanlab olish uchun mo'ljallangan built-in Python funksiyasi. U har bir elementga bir xil tekshiruvni qo'llaydi va faqat shartga mos keladiganlarini qoldiradi. filter()'ni ko'pincha data cleaning va boshqa ma'lumot tanlash vazifalarida uchratasiz.
Sintaksis va qaytariladigan qiymat
filter()'dan foydalanganda ikkita majburiy kiruvchi qiymat bor: shart funksiyasi va iterable. Sintaksisi jihatidan filter() quyidagicha ko'rinadi:
filter(function, iterable)
Shart funksiyasi iterable'ingizdagi har bir element uchun True yoki False qaytarishi kerak, filter() esa faqat True qaytargan elementlarni qoldiradi.
filter() funksiyasi filter obyektini qaytaradi. Bu lazy iterator. Ya'ni Python iterable'ning har bir elementini darhol tekshirmaydi. Buning o'rniga u elementlarni faqat siz so'raganingizda, birma-bir baholaydi. Qaytarilgan obyekt ustida iterate qilmaguningizcha hech qanday filtrlash amalda sodir bo'lmaydi. Uning ustida loop qilishingiz, uni list'ga aylantirishingiz yoki iterator qabul qiladigan boshqa funksiyaga uzatishingiz mumkin.
Shuni ham yodda tutingki, filter() asl iterable'ingizni o'zgartirmaydi. U faqat shartni qanoatlantiradigan elementlarni yield qiladigan yangi obyekt yaratadi.
Oddiy misollar
Endi filter() funksiyasining asoslarini o'rganib olganingizdan so'ng, uni amalda ko'rish vaqti keldi. Quyida filter()'ning amaliy qo'llanishlarini ko'rsatuvchi bir nechta qulay misollar keltirilgan.
Python'ning filter() funksiyasini custom funksiya bilan ishlatish
filter() ikkita kiruvchi qiymatni kutadi: shart funksiyangiz va u qo'llaniladigan iterable. Funksiyangiz har bir element uchun True yoki False qaytarsa bo'ldi, filter() uchun o'zingizning custom funksiyangizni yozishingiz mumkin.
Aytaylik, sizda so'zlar list'i bor va siz faqat besh yoki undan kam belgidan iborat qisqa so'zlarni qoldirmoqchisiz. Funksiyangiz so'zda besh yoki undan kam belgi bor-yo'qligini tekshiradi, filter() esa natijalardan foydalanib list'ingizni qisqartiradi.
def is_short_word(word):
return len(word) <= 5
words = ["computer", "apple", "dog", "ceiling", "mail"]
short_words = filter(is_short_word, words)
print(list(short_words))
# Expected result:
# ['apple', 'dog', 'mail']
E'tibor bering, natijalarni chop etishdan oldin short_words'ni list'ga aylantirdik.
Lambda funksiyalar
Agar shart funksiyangiz juda oddiy bo'lsa, alohida funksiya aniqlash o'rniga uni filter() ichida to'g'ridan-to'g'ri bir qatorli lambda funksiya sifatida yozishingiz mumkin. Lambda'lar xuddi oddiy user-defined funksiyalar kabi ishlaydi, lekin ular anonymous va ixcham bo'lgani uchun qisqa, bir martalik shartlar uchun qulay tanlovdir.
Qisqa so'zlarni topish bo'yicha oldingi misolni custom is_short_word() funksiyasi o'rniga lambda bilan qayta yozish mumkin:
words = ["computer", "apple", "dog", "ceiling", "mail"]
short_words = filter(lambda x: len(x) <= 5, words)
print(list(short_words))
# Expected result:
# ['apple', 'dog', 'mail']
filter()'ga uzatiladigan funksiya argumenti sifatida user-defined funksiyalarni ham, lambda'larni ham tez-tez uchratasiz. Umuman olganda, lambda'lar oddiy shartlar uchun yaxshi ishlaydi, nomlangan funksiyalarni esa murakkabroq mantiq uchun o'qish va qayta ishlatish odatda osonroq.
Juft sonlar misoli
filter() funksiyasi string'lar bilan qanchalik yaxshi ishlasa, sonlar to'plamlari bilan ham shunchalik yaxshi ishlaydi. filter()'ning klassik misollaridan biri qiymatlar list'idan faqat juft sonlarni tanlab oladi:
numbers = [0, 1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens))
# Expected result:
# [0, 2, 4, 6]
Bo'sh string'lar va falsy qiymatlarni olib tashlash
Truthiness — Boolean g'oyasini faqat True va False doirasidan tashqariga kengaytiradigan Python tushunchasi. Qiymatlar yo "truthy", yo "falsy" deb hisoblanadi. Keng tarqalgan falsy qiymatlar quyidagilar:
-
False
-
None
-
0 yoki 0.0
-
'' (bo'sh string)
-
[], {}, () yoki set() (bo'sh to'plamlar)
filter() funksiyasi bilan ana shu tabiiy truthiness'dan foydalanishingiz mumkin. Esda tuting, filter() faqat shart funksiyasi True deb baholagan qiymatlarni qoldiradi. Agar shart funksiyasi sifatida None uzatsangiz, filter() tekshiruv sifatida har bir elementning o'zini ishlatadi va faqat truthy qiymatlarni qoldiradi.
Ismlar list'idan bo'sh string'larni quyidagicha olib tashlashingiz mumkin:
names = ["Stacey", "Yasmin", "", "", "Todd", "", "Raj"]
valid_names = filter(None, names)
print(list(valid_names))
# Expected result:
# ['Stacey', 'Yasmin', 'Todd', 'Raj']
Bu yerda filter() har bir ismning truthiness'ini tekshiradi va bo'sh string'larni chiqarib tashlaydi. filter() yangi iterable yaratib, asl list'ga tegmagani uchun, u list ustida loop qilayotganda list'dan elementlarni olib tashlashdan ko'ra xavfsizroq tanlovdir.
filter(), list comprehension'lar va generator expression'lar taqqoslanishi
filter() funksiyasi Python'dagi yagona filtrlash mexanizmi emas. List comprehension'lar va generator expression'lar ham shunga o'xshash vazifalarni bajaradi, ammo o'qilishi, moslashuvchanligi va xotiradan foydalanishi bo'yicha turli tradeoff'larga ega.
Juft sonlar misoli har bir usulda quyidagicha ko'rinadi:
numbers = [0, 1, 2, 3, 4, 5, 6]
# filter()
evens_filter = filter(lambda x: x % 2 == 0, numbers)
# comprehension
evens_list_comp = [x for x in numbers if x % 2 == 0]
# generator
evens_generator_exp = (x for x in numbers if x % 2 == 0)
print(list(evens_filter))
print(evens_list_comp)
print(list(evens_generator_exp))
# Expected result:
# [0, 2, 4, 6]
# [0, 2, 4, 6]
# [0, 2, 4, 6]
Har bir usul oxir-oqibat bir xil qiymatlarni beradi. E'tibor bering, comprehension allaqachon list qaytaradi, filter() va generator esa lazy iterator'lar hosil qiladi va ularning barcha qiymatlarini ko'rsatish uchun ularni consume qilishimiz (masalan, list() bilan) kerak.
Quyida har bir usulni batafsilroq taqqoslash keltirilgan:
| filter() | List comprehension | Generator expression | |
|---|---|---|---|
| Eng mos keladigan holat | Oddiy funksiyalar | Pythonic sintaksis | Data pipeline'lar |
| Qaytaradi | filter obyekti | list | Generator |
| Lazy | Ha | Yo'q | Ha |
| Funksiya talab qiladi | Ha | Yo'q | Yo'q |
| Bir nechta shart | Kamroq o'qiladi | O'qiladi | O'qiladi |
| Xotirani tejaydi | Ha | Yo'q | Ha |
Amalda, agar shart funksiyangiz allaqachon aniqlangan bo'lsa yoki lazy tarzda ishlamoqchi bo'lsangiz, ehtimol filter()'ga murojaat qilasiz. Comprehension'larni yaratish va tushunish oson bo'lgani uchun ular kundalik ishda ko'proq uchraydi. Generator'lar comprehension'larga o'xshash sintaksisdan foydalanadi, lekin lazy tarzda baholanadi, bu esa ularni katta dataset'lar yoki streaming ma'lumotlar uchun ajoyib tanlovga aylantiradi.
Filter funksiyasi haqiqatan ham tezroqmi?
Ko'plab real hayotiy masalalarda filter(), list comprehension'lar va generator'lar o'rtasidagi performance farqi kichik. Comprehension'lar ko'pincha filter() bilan bir xil tezlikda yoki hatto biroz tezroq ishlaydi; biroq ular darhol baholanadi, bu esa katta dataset'lar uchun xotiradan samarasiz foydalanishga olib kelishi mumkin.
filter()'ni tezlik uchun tanlashdan ko'ra, kodingizni eng toza qiladigan yondashuvni tanlang. Agar shart funksiyangiz allaqachon aniqlangan bo'lsa, uni iterable'ga qo'llash uchun osongina filter()'ga qo'yib yuborishingiz mumkin. Aks holda, oddiy filtrlash uchun odatda list comprehension'lar Pythonic tanlov hisoblanadi.
filter()'ni map() va reduce() bilan birlashtirish
filter(), map() va reduce() ko'pincha uchlik sifatida birga keladi, chunki ular Python va boshqa tillardagi functional programming'ning asosini tashkil etadi. Har bir funksiyaning o'ziga xos vazifasi bor:
-
filter() elementlarni tanlaydi
-
map() elementlarni o'zgartiradi
-
reduce() elementlarni bitta qiymatga jamlaydi
Aytaylik, siz barcha juft sonlarni tanlab, ularni kvadratga ko'tarib, kvadratlarining yig'indisini olmoqchisiz. Python standart kutubxonasining bir qismi bo'lgan functools'dan reduce()'ni import qilgandan so'ng, quyidagi kod filter(), map() va reduce()'ni yagona umumiy pipeline'ga birlashtiradi:
from functools import reduce
numbers = [0, 1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers) # [0, 2, 4, 6]
squares = map(lambda x: x**2, evens) # [0, 4, 16, 36]
total = reduce(lambda x, y: x + y, squares) # 56
print(total)
# Expected result:
# 56
filter(), map() va reduce() ko'pincha birga o'rgatilsa-da, zamonaviy Python kodi map() va reduce() o'rniga ko'proq comprehension'lar va sum() kabi built-in funksiyalarga tayanadi. Shunga qaramay, bu component'lar qanday birga ishlashi mumkinligini bilish foydali, ayniqsa functional uslubdagi kodni o'qiyotganda.
Data analysis'da list'lardan tashqari filtrlash
Maqoladagi hozirgacha ko'rsatilgan misollar Python list'larini filtrlashga qaratilgan edi, ammo filter()'dan boshqa ko'plab ma'lumotlar tuzilmalari uchun ham foydalanishingiz mumkin. Data analyst'lar va data scientist'lar ko'pincha generator'lar, fayl obyektlari, dictionary'lar va boshqa iterable obyektlarga tayanadi; filter() bularning barchasi ustida ishlay oladi.
Aytaylik, sizda 0 dan 99 gacha bo'lgan qiymatlar generator'i bor. Quyidagi kod faqat 95 dan qat'iy katta bo'lgan katta sonlarni filtrlab oladi:
my_generator = (x for x in range(100))
high_values = filter(lambda x: x > 95, my_generator)
for value in high_values:
print(value)
# Expected result:
# 96
# 97
# 98
# 99
Bu holatda natijaviy iterator'ni consume qilish va har bir qiymatni chop etish uchun loop'dan foydalandik. Oldingi misollardagidek, high_values'ni osongina list'ga aylantirishimiz ham mumkin edi.
Ma'lumotlar bilan ishlovchi mutaxassislarga ko'pincha flat fayllardan ma'lumot o'qishga to'g'ri keladi; ularda tahlilga aloqasi yo'q ortiqcha satrlar bo'lishi mumkin. Faylingizdagi ma'lumotlarni qayta ishlashda bu satrlarni o'tkazib yuborish uchun filter()'dan foydalanishingiz mumkin:
with open("sales.csv") as f:
valid_rows = filter(is_valid_row, f)
for row in valid_rows:
process_row(row)
Bu yerda is_valid_row() va process_row() user-defined funksiyalarni ifodalaydi. is_valid_row() funksiyasi satr to'g'riligini tasdiqlash uchun yaroqli belgilarni, mantiqiy qiymatlarni yoki boshqa har qanday kerakli tekshiruvni amalga oshirishi mumkin. Xuddi shunday, process_row() funksiyasi ham zarurat bo'yicha ma'lumotni o'zgartirishi, tozalashi, tahlil qilishi yoki jamlashi mumkin.
Ma'lumotlarni tahlil qilishda filter() faqat list'lar bilan cheklanmaydi. Obyektingiz iterable bo'lsa bo'ldi, faqat vazifangizga tegishli elementlarni qayta ishlash uchun xuddi shu filtrlash mantig'ini qo'llashingiz mumkin. Biroq filter()'ning yangi Python dasturchilarini ko'pincha hayron qoldiradigan bir nechta xatti-harakati bor. filter() muammolaridan qochishingizga yordam berish uchun keyingi bo'limda keng tarqalgan "tuzoq"larni ko'rib chiqamiz.
Keng tarqalgan tuzoqlar
Python'ning filter() funksiyasi elementlarni shart funksiyasi asosida sodda tarzda tanlaydi, ammo filter() bilan ishlashda bir nechta keng tarqalgan xato manbalari bor. filter() kodingiz bug'lardan xoli bo'lib qolishi uchun ushbu asosiy tuzoqlarni ko'rib chiqing.
Iterator'ning tugab qolishi
filter obyektlari iterator'lardir. Ya'ni ularni faqat bir marta to'liq consume qilishingiz mumkin. Buni qayta qilishga urinish hech qanday ma'lumot bermaydi va bu ko'pincha iterator'lar bilan endi tanishayotganlarni hayron qoldiradi.
Quyidagi kodda ismlari "K" harfi bilan boshlanadigan odamlarni qidiramiz:
people = ["Kamila", "Ken", "Nola", "Monika", "Kristen"]
k_names = filter(lambda name: name[0].upper() == "K", people)
print(list(k_names))
print(list(k_names))
# Expected result:
# ['Kamila', 'Ken', 'Kristen']
# []
"K" bilan boshlanadigan ismlar birinchi print() statement'ida kutilganidek chiqadi. k_names'ni ikkinchi marta list'ga aylantirishga uringanimizda, u allaqachon tugab qolgan bo'ladi va biz bo'sh list'ni chop etamiz. Bunday bo'lishining sababi — filter() filtrlangan natijalarni saqlamaydi; u har bir qiymatni faqat so'ralganda hosil qiladi. Bu qiymatlarni bir marta consume qilganingizdan so'ng, ular endi mavjud bo'lmaydi.
Agar natijalardan bir necha marta foydalanishingiz kerak bo'lsa, ularni albatta saqlab qo'ying. Qaytarilgan obyektni consume qilganingizdan so'ng, qiymatlar ustida qayta iterate qilish uchun uni qaytadan yaratishingiz kerak bo'ladi.
list() bilan o'rashni unutish
filter() funksiyasi list emas, iterator qaytaradi. Natijalaringizni ko'rish uchun o'sha natijaviy obyektni list'ga aylantirish, uning ustida loop qilish yoki iterable qabul qiladigan funksiyaga uzatish orqali consume qilishingiz kerak bo'ladi.
Agar filter() qaytargan obyektni to'g'ridan-to'g'ri chop etishga ursangiz, qiymatlarning o'zini emas, balki obyekt ko'rinishini ko'rasiz.
numbers = [0, 1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x%2 == 0, numbers)
print(evens)
# Expected result:
# <filter object at 0x103438430>
Agar barcha qiymatlarni ko'zdan kechirish yoki saqlash kerak bo'lsa, natijaviy obyektni list() bilan o'rashni unutmang. Muqobil ravishda, elementlarni birma-bir qayta ishlash va ayniqsa katta dataset'lar bilan ishlaganda hamma narsani xotirada saqlashdan qochish uchun uning ustida to'g'ridan-to'g'ri iterate qiling.
Murakkab lambda'lardan foydalanish
Lambda funksiyalar qisqa, oddiy funksiyalar uchun juda mos. Uzun yoki boshqa jihatdan murakkab lambda'larni o'qish va debugging qilish qiyin bo'ladi.
Lambda'laringizni ixcham saqlash uchun quyidagilardan qochishga harakat qiling:
-
Bir nechta uzun shartlar (
and,or) -
Ichma-ich joylashgan mantiq
-
Murakkab string manipulyatsiyasi
-
Type conversion'lar
-
Error handling
-
Filtr shartiga aloqasi yo'q yon hisob-kitoblar
Agar filter() funksiyangizdagi lambda yuqoridagi xususiyatlardan birortasini talab qilsa, uni alohida, nomlangan user-defined funksiya sifatida qayta yozishni o'ylab ko'ring. Unda bir nechta qatordan, izohlardan va chuqur mantiqdan iborat funksiya yaratishingiz mumkin; bu funksiyani hatto kodingizning boshqa joylarida ham ishlata olasiz. Nomlangan funksiyalarni debugging qilish odatda osonroq, chunki oraliq qiymatlarni chop etishingiz va funksiyani filter()'dan mustaqil ravishda testlashingiz mumkin.
Xulosa
Python'ning filter() funksiyasi har bir elementni shart funksiyasi bo'yicha tekshirib, list yoki boshqa iterable'ni filtrlash imkonini beradi. Uni filter(function, iterable) sintaksisi yordamida chaqiring, bu yerda function user-defined funksiya yoki lambda bo'lishi mumkin. List comprehension'dan farqli o'laroq, filter() lazy tarzda baholaydi. Uning natijaviy iterator'i qiymatlarni saqlamaydi; buning o'rniga ularni talab bo'yicha, masalan, natijalarni list'ga aylantirganingizda hosil qiladi.
Bilimlaringizni filter() qilib ko'rish uchun AI Tutor'ni sinab ko'ring. Quyidagi boshlang'ich prompt sizni to'g'ri yo'lga solib yuboradi: