6.2. ה-ndarray¶
ה-ndarray הוא הסוג שמחזיק נתונים מספריים ב-numpy. הוא שני דברים באחד: בלוק נתונים אחד דחוס ומתאר קטן לפניו שאומר כיצד לקרוא אותו.
6.2.1. בתוך הקופסה¶
בלוק הנתונים מחזיק את כל איברי המערך קצה אל קצה, ללא דבר נוסף ביניהם. כל איבר תופס את אותו מספר בתים – אחד עבור מערך של ערכי uint8, שניים עבור uint16, ארבעה עבור float. מערך uint8 בן 256 איברים הוא בדיוק 256 בתים של נתונים; אותם 256 מספרים ב-list של Python תופסים קילובייט – חריץ אחד בן 32 סיביות לכל איבר, ללא קשר לכמה מעט סיביות הערך באמת זקוק.
המתאר רושם מה הבלוק אומר. חמישה ערכים מספיקים לתאר כל מערך מלבני, ללא קשר לכמה ממדים יש לו:
dtype– סוג האיבר. מכריע כמה בתים תופס כל איבר ואיזה טווח ערכים הוא יכול להחזיק (מכוסה ב-Dtypes).itemsize– רוחב הבתים של איבר אחד, נגזר מה-dtype.ndim– מספר הממדים (1 עבור וקטור, 2 עבור מטריצה, 3 עבור נפח, עד 4).shape– הגודל לאורך כל ממד בתור tuple.strides– כיצד לפסוע דרך בלוק הנתונים כדי לעבור על כל ציר. מכוסה ב-צורה וצעדים (strides).
זה הכול. כל מסלול מהיר ב-numpy – אריתמטיקה, רדוקציות, broadcasting, חיתוך – עובד ישירות מחמשת הערכים האלה בתוספת מצביע הנתונים, ללא תקורת Python לכל איבר.
6.2.2. מה התכנון קונה¶
שלוש תכונות נובעות מ“בלוק דחוס + מתאר קטן“ ומגדירות כיצד שאר הפרק מתנהג.
מתמטיקה איבר-איבר רצה כקריאה אחת. a + b בין שני מערכים בעלי צורה תואמת מחבר את שני החוצצים וכותב שלישי, הכול בתוך קריאת ספרייה אחת. np.sin(a) עושה את אותו דבר עבור הסינוס של כל איבר. האופרטורים האריתמטיים, ההשוואתיים, והסיבייתיים כולם עובדים בדרך זו.
הסתכלות על אותם נתונים מזווית אחרת היא חינמית. בקשה לתת-אזור של מערך, או לאותם נתונים בפריסת צורה אחרת, אינה מזיזה אף בית. הפעולה מחזירה מתאר חדש המצביע על אותו בלוק נתונים. התוצאה נקראת view – חלון שני אל אותו חוצץ בסיסי. כתיבה דרך view כותבת אל המקור.
צורות מעורבות עדיין עובדות. מערך קצר כנגד ארוך יותר, שורה כנגד מטריצה, עמודה כנגד שורה – numpy מיישר אותם באמצעות broadcasting, קבוצה קטנה של כללים שמכריעים איזה ציר קצר נמתח להתאים לארוך. המתיחה היא וירטואלית; שום נתונים אינם משוכפלים.
6.2.3. מה התכנון עולה¶
שתי הגבלות נובעות מאותו תכנון.
לכל איבר יש את אותו סוג. רשימה יכולה להחזיק int ליד str ליד רשימה של שלושה ערכי int נוספים; ndarray אינו יכול. ה-dtype קבוע בזמן הבנייה. עמוד ה-Dtypes מכסה את הקבוצה הקטנה של סוגים ש-numpy תומך בהם ואת הכללים הנובעים מקיבוע אחד.
הגדלת מערך אינה חינמית. רשימה שומרת חריצים רזרביים בסוף ותומכת ב-.append בזול. ndarray הוא בדיוק בגודל שהוא צריך להיות; הוספה תהיה כרוכה בהקצאת חוצץ חדש וגדול יותר והעתקת התוכן הישן לתוכו. אין שיטת append(), במכוון. הדפוס הנכון על המצלמה הוא להקצות את היעד מראש בגודלו הסופי ולמלא אותו; ביצועים מכסה את הטכניקה.
עם חוצץ ממוין דחוס לנתונים, מתאר קטן למטא-נתונים, ושלוש הבטחות התנהגותיות (מתמטיקה איבר-איבר מהירה, views חלופיים ללא העתקה של אותם נתונים, וצורות שמתפזרות ב-broadcasting), ה-ndarray הוא היסוד שעליו נשען שאר הפרק. איך מערך באמת בא לעולם – מתוך ליטרל, מתוך הקצאה מלאה מראש, מתוך חוצץ של התקן היקפי – היא השאלה המעשית הבאה.