NumPy nima va nega kerak
Sahna: bir million son
Sizga do'konning bir yillik savdosi berildi: bir million chek, har birida summa. Birinchi savol oddiy — o'rtacha chek qancha?
Python bilan buni allaqachon bilasiz: sum(summalar) / len(summalar). Ishlaydi. Lekin keyin savollar ko'payadi: har chekdan QQS ni ayiring, chegirmani qo'llang, eng katta 10 tasini toping, bir oyni boshqasi bilan solishtiring. Har biri — yana bir sikl, yana bir million qadam.
NumPy (Numerical Python) — aynan shu ish uchun yaratilgan kutubxona: ko'p sonlar ustida bir xil amalni tez bajarish. pandas ham, Matplotlib ham, scikit-learn ham, PyTorch ham ichida NumPy array lardan foydalanadi. Shuning uchun bu kitob undan boshlanadi: keyingi ikki qism shu poydevorga quriladi.
NumPy ni chaqirish
import numpy as np print(np.__version__)
2.2.6
np — butun dunyo ishlatadigan qisqartma. Boshqa nom bersangiz ham kod ishlaydi, lekin hujjatlar, kitoblar va savol-javob saytlaridagi har bir misol np. bilan yozilgan — o'qishda adashmaslik uchun shu nomni ishlating.
Avval o'lchaymiz: list va array
Gapga ishonmaymiz — o'lchaymiz. Bir xil bir million sonni Python list da va NumPy array da saqlab, ikkalasining yig'indisini hisoblaymiz va vaqtni yozib boramiz.
import time rng = np.random.default_rng(0) summalar = rng.integers(5_000, 500_000, size=1_000_000) royxat = summalar.tolist() def olchov(ish, takror=5): eng_tez = float("inf") for _ in range(takror): boshi = time.perf_counter() ish() eng_tez = min(eng_tez, time.perf_counter() - boshi) return eng_tez * 1000 natija = { "yig'indi — list": olchov(lambda: sum(royxat)), "yig'indi — array": olchov(lambda: summalar.sum()), "* 0.88 — list": olchov(lambda: [s * 0.88 for s in royxat]), "* 0.88 — array": olchov(lambda: summalar * 0.88), } for nom, ms in natija.items(): print(f"{nom:<17} {ms:8.2f} ms") print(f"\nyig'indi bir xilmi: {sum(royxat) == summalar.sum()}")
yig'indi — list 3.27 ms yig'indi — array 0.15 ms * 0.88 — list 24.85 ms * 0.88 — array 0.87 ms yig'indi bir xilmi: True
Har ish 5 marta takrorlandi va eng tezi olindi — kompyuter boshqa ish bilan band bo'lgan bir lahzalik sekinlashuv natijani buzmasligi uchun. Aniq millisekundlar sizning kompyuteringizda boshqacha chiqadi; muhimi — farqning yo'nalishi va kattaligi. Rasmda ko'rinadi (jigarrang — list, ko'k — array; vaqt shu kitob qurilgan kompyuterda o'lchangan):
fig, ax = plt.subplots(figsize=(8, 3.2)) nomlar = list(natija) ranglar = ["#b06000", "#1a73e8", "#b06000", "#1a73e8"] ax.barh(nomlar, list(natija.values()), color=ranglar) ax.invert_yaxis() ax.set_xlabel("millisekund (kamroq — yaxshiroq)") ax.set_title("Bir million son: list va NumPy array") for i, ms in enumerate(natija.values()): ax.text(ms, i, f" {ms:.1f}", va="center") plt.show()

Ikkala ish ham bir xil natija beradi (yig'indi tengligini tekshirdik), lekin array ko'p barobar tezroq — bu kitob qurilgan kompyuterda o'nlab barobar. Ko'paytirishdagi farq ayniqsa katta: list bilan Python har bir son uchun alohida amal bajaradi, array bilan esa bitta buyruq bir million sonni birdan ko'paytiradi.
Nega array tez: xotira ichida nima bor
Farqning sababi — sonlar xotirada qanday turishida.

List xotirada ko'rsatkichlar saqlaydi, array esa sonlarning o'zini ketma-ket saqlaydi
Python list sonning o'zini emas, unga ko'rsatkichni (adresni) saqlaydi. Har bir son — xotiraning qaysidir burchagidagi alohida obyekt: ichida turi, nechta joyda ishlatilayotgani (hisob) va qiymatning o'zi. Shuning uchun list ga bir vaqtning o'zida son, matn va boshqa list solsa bo'ladi — u moslashuvchan. Lekin moslashuvchanlikning narxi bor: har bir qo'shishda Python avval "bu nima, son mi, matn mi?" deb so'raydi.
NumPy array esa boshida bitta sarlavha saqlaydi — dtype (hamma elementning umumiy turi) va shape (o'lchami) — keyin sonlarning o'zini ketma-ket, bo'shliqsiz yozadi. Uchta natija chiqadi:
- Tur bitta — har element uchun "bu nima?" deb so'rash kerak emas.
- Joy ketma-ket — protsessor xotiradan bir martada bir nechta sonni o'qiydi.
- Sikl C tilida —
summalar * 0.88ni yozganingizda sikl Python da emas, NumPy ning C da yozilgan ichki qismida aylanadi.
Bu gapni ham o'lchab ko'ramiz — xotira hajmi bilan:
import sys bitta_son = sys.getsizeof(7) royxat_jami = sys.getsizeof(royxat) + sum(sys.getsizeof(s) for s in royxat) print(f"bitta Python int obyekti: {bitta_son} bayt") print(f"array ichida bitta son: {summalar.itemsize} bayt ({summalar.dtype})") print(f"list (ko'rsatkichlar + obyektlar): {royxat_jami / 1e6:.1f} MB") print(f"array (faqat sonlar): {summalar.nbytes / 1e6:.1f} MB")
bitta Python int obyekti: 28 bayt array ichida bitta son: 8 bayt (int64) list (ko'rsatkichlar + obyektlar): 36.0 MB array (faqat sonlar): 8.0 MB
Bir xil million son: list 36 MB, array 8 MB. List da har son uchun 28 baytlik obyekt va unga 8 baytlik ko'rsatkich kerak; array da esa faqat sonning o'zi — 8 bayt.
Bir xil belgi — boshqa ma'no
NumPy bilan ishlashda yangi boshlovchilar eng ko'p qoqiladigan joy: * va + list va array da butunlay boshqa ish qiladi.

list da * va + takrorlaydi va ulaydi, array da esa har element bilan hisoblaydi
royxat_kichik = [1, 2, 3] massiv = np.array([1, 2, 3]) print("list * 2: ", royxat_kichik * 2) print("array * 2:", massiv * 2) print("list + list: ", [1, 2] + [10, 20]) print("array + array:", np.array([1, 2]) + np.array([10, 20]))
list * 2: [1, 2, 3, 1, 2, 3] array * 2: [2 4 6] list + list: [1, 2, 10, 20] array + array: [11 22]
List matematikadan emas, ro'yxatdan o'ylaydi: "ikki marta" — ro'yxatni ikki marta yozish, "qo'shish" — ikki ro'yxatni ulash. Array esa sonlardan o'ylaydi: har amal har elementga qo'llanadi. Bu usul vectorization (vektorlashtirish) deyiladi — sikl yozmasdan butun ma'lumotga bitta amal.
Bitta tur — bitta qoida
Array ichidagi hamma element bir turda bo'lishi shart. Har xil turdagi qiymatlar bersangiz, NumPy xato bermaydi — hammasini sig'diradigan bitta turni o'zi tanlaydi. Bu ba'zan kutilmagan natija beradi:
print(np.array([1, 2, 3]).dtype) print(np.array([1, 2, 3.5]).dtype) aralash = np.array([1, 2, "3"]) print(aralash.dtype, aralash) print(aralash.astype(int) * 2)
int64 float64 <U21 ['1' '2' '3'] [2 4 6]
Bitta kasr son butun massivni float64 ga o'tkazdi. Bitta matn esa hamma sonni matnga aylantirdi (<U21 — Unicode matn): '1' endi son emas. Qaytarish uchun turni o'zingiz aytasiz — astype(int), shundan keyin * 2 yana ko'paytiradi. Real hayotda bu shunday ko'rinadi: CSV fayldagi bitta katakda "noma'lum" deb yozilgan — butun ustun son emas, matn bo'lib qoladi. 9-bobda pandas bilan aynan shu muammoni uchratamiz.
Qachon NumPy kerak emas
NumPy — bolg'a, lekin hamma narsa mix emas:
| Vaziyat | Nima ishlatiladi | Nega |
|---|---|---|
| Ko'p son, bir xil amal | NumPy array | tez va kam xotira |
| Har xil turdagi ustunli jadval (ism, sana, summa) | pandas DataFrame | har ustunning o'z turi bor (2-qism) |
| 10–20 ta qiymat, tez-tez qo'shish/o'chirish | Python list | array ga element qo'shish har safar yangi massiv yaratadi |
| Matnlar ro'yxati bilan murakkab ish | list yoki pandas .str |
NumPy matn uchun qurilmagan |
Xulosa
- NumPy — ko'p sonlar ustida bir xil amalni tez bajarish uchun; pandas, Matplotlib va ML kutubxonalari uning ustiga qurilgan.
- Array tez, chunki: bitta tur, ketma-ket joy, sikl C da.
- Array kam xotira oladi: har son o'z hajmida, ko'rsatkichsiz.
*va+array da har elementga qo'llanadi (vectorization); list da esa takrorlaydi va ulaydi.- Array da hamma element bir turda; aralash turlar eng "keng" turga — ba'zan matnga — o'tadi.
Mashqlar
np.array([True, 2, 3])ningdtypei qanday bo'ladi? Avval taxmin qiling, keyin tekshiring. Nega shunday?- Bir million sonning kvadratini list (sikl) va array bilan hisoblab, vaqtini o'lchang. Qaysi biri tezroq va necha barobar?
[0.1] * 3vanp.array([0.1]) * 3natijalarini solishtiring. Qaysi biri "takrorlash", qaysi biri "ko'paytirish"?
Javoblar
int64:Trueson sifatida 1 ga aylanadi, chunki butun sonboolni sig'diradi.- Array tezroq; aniq barobar kompyuteringizga bog'liq —
olchovfunksiyasidan foydalaning. - List —
[0.1, 0.1, 0.1](takrorlash), array —[0.3](ko'paytirish, bitta element).
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.