fbpx

01. מחלקות

הקדמה

היי חברים, ברוכים הבאים לקורס פייתון למתקדמים
ההנחה היא שאנחנו כבר יודעים איך קוד נראה, מהם משתנים, מערכים, לולאות, תנאים, ואפילו פונקציות. בהחלט הספקנו הרבה.

בקורס זה, אנו ניקח את כל הידע שצברנו, ונלמד להשתמש בו עם כלים נוספים.

בשיעור זה, אנו נלמד על מחלקות. באנגלית – Classes.

מהי מחלקה?

מחלקה היא תבנית קוד, שמיצגת לוגיקה כלשהי. מהתבנית הזו ניתן ליצור אובייקטים.

בואו נדמה זאת למכולת.

ובכן, בואו נחשוב שאנו כותבים תוכנה, שמטרתה היא לנהל מוצרים במכולת.
ברור לנו כמנהלי המכולת, שלמרות שישנם הרבה מוצרים, עדיין לכל מוצר יש:

  • שם המוצר
  • ברקוד
  • עלות (למוכר)
  • מחיר (לצרכן)
  • תאריך ייצור
    וכן הלאה…

בשביל לכתוב תוכנה שיהיה לנו קל לכתוב ולעבוד איתה, אנו נרצה להמציא איזושהי תבנית שתייצג מוצר.

תדמיינו שאנו בונים את רשימת המוצרים באקסל, ברור שבראש הטבלה אנו ניצור עמודות שכל עמודה תציין שם של מאפיין, כמו “שם המוצר”, “מחיר המוצר” וכן הלאה.

אז בתכנות, אנו נגדיר “מחלקה” בשם מוצר, המאפיינים של המחלקה יהיו השם, המחיר הברקוד וכו’.

לאחר שנגדיר מחלקה, שזה רק אפיון כללי למוצר (כמו ראש העמודות שבאקסל), אנו נוכל להתחיל ליצור מוצרים “אמיתיים”, שהם יהיו ה”מופעים” של המחלקה. (כמו השורות באקסל, שכל שורה תייצג בעצם מוצר).

כאשר בעל המכולת ירצה להכניס מוצר חדש למכולת, הוא יוכל להשתמש בתבנית (במחלקה) בצורה קלה.

בואו נראה איך עושים זאת.

מחלקה – הגדרה:

מחלקה היא המסגרת הבסיסית של תכנות מונחה עצמים. זהו אוסף של משתנים (הנקראים שדות), מאפיינים ופונקציות (הנקראות שיטות) המאוגדים למבנה לוגי אחד ופועלים יחד. (ויקיפדיה)

בואו נצלול לכתיבה, ותוך כדי נבין טוב יותר.

הבה נגדיר מחלקה בשם מוצר.

הגדרת המחלקה תהיה כך:

				
					class Product():
     name = None
				
			

נשים לב לפרטים:
תחילה השתמשנו במילה השמורה class (מלשון מחלקה…)
אחר כך בחרנו את שם המחלקה Product (כמובן שיכולנו לבחור כל שם אחר).
בצמוד, הוספנו סוגריים עגולות, ולאחריהן נקודותיים.

בשורה הבאה, (תחת הזחה) יצרנו “מאפיין” או “משתנה” של המחלקה. קראנו לו name. הוא ייצג כמובן את השם של המוצר. רק שכעת אין לנו עדיין מוצר, זה רק טיפוס נתונים פוטנציאלי – תבנית.
ולכן גם את השם של המוצר אנו לא רוצים לבחור כעת, ולכן פשוט נאתחל אותו ב None – בכלום.

נוכל לדמיין את מה שעשינו כגיליון אקסל בשם product, שציינו בו “עמודה” בשם name. עדיין אין לנו שורות כלל.

מחוץ להגדרת המחלקה, נוכל ליצור מוצרים (“מופעים”) של המחלקה. (כמו שורות בטבלת האקסל)

היצירה תיעשה באופן שמזכיר קריאה לפונקציה… אנו ניצור משתנה חדש, לדוגמא X, שיכיל “עותק” או יותר נכון “מופע” של המחלקה. באופן הבא:

				
					x = Product() 

				
			

כעת X הוא מופע של המחלקה.
כרגע אין ל X שום מאפיין מעניין… (זה כאילו יצרנו שורה חדשה בטבלת האקסל, אך עוד מילאנו את הפרטים שלה)
מכיון שאנו יודעים שהמחלקה מכילה גם משתנה בשם name, זה אומר שזה מאפשר לנו להגדיר “שם” לכל מופע של המחלקה.
בשביל לעשות זאת, אנו ניגש לשדה name באמצעות X, באופן הבא:

				
					x.name = "Sugar"
				
			

כעת X הוא מופע של המחלקה “מוצר”, וגם יש לו שם – סוכר. (שורה באקסל, שתחת העמודה name ציינו “סוכר”)
אם נרצה להדפיס את “שם המוצר” של המופע X, נעשה זאת בקלות כך:

				
					print(x.name) 
				
			

כשהגדרנו את המחלקה, יצרנו רק שדה אחד בשם name. כמובן שבדרך כלל יהיו לנו יותר משדה בודד…

בשביל לעשות זאת, אנו נוכל ליצור עוד משתנים. כך:

				
					class Product():
     name = None
     barcode = None
     price = None 
				
			
כעת נוכל ליצור “מופעים” שונים של המחלקה מוצר, ולציין את המאפיינים שלהם:
				
					sugar = Product()
sugar.name = "Sugar"
sugar.barkod = "345824"
sugar.price = 1.5

salt = Product()
salt.name = "Salt"
salt.barkod = "930043"
salt.price = 4.99 
				
			

כעת יש לנו שני מוצרים (מופעים), שניהם “שייכים” לאותה מחלקה “מוצר”, אך לכל אחד נתונים שונים בשדות המאפיינים אותם.

אם נחזור לדוגמת האקסל, אז זה כאילו יצרנו שתי שורות חדשות, כל שורה מייצגת מוצר אחר. וכמובן שבכל שורה שמנו נתונים תחת העמודות הרלוונטיות..

תרגיל:

צור מחלקה בשם person אשר מייצגת “אדם”. בשביל לייצג ‘אדם’ אנו נרצה שיהיו לו את השדות הבאים:

  •  שם
  •  מגדר
  •  גיל
  •  תעודת זהות

לאחר מכן, צור פונקציה אשר מקבלת את הפרמטרים: שם, מגדר, גיל, ות.ז,
הפונקציה יוצרת ‘מופע’ של המחלקה “אדם”, וכמובן מחזירה אותו…
לאחר מכן, השתמשו בפונקציה ליצירת ‘אדם’.

הפתרון בסרטון:

אנו נוכל להגדיר פונקציה שתהיה פונקציה של המחלקה.
פונקציה של מחלקה, זו “פעולה” ששייכת למחלקה.

מה זאת אומרת?

נמשיך עם הדוגמה של מחלקה המייצגת מוצר.
נניח שאנו רוצים ליצור פונקציה, אשר מחזירה את המחיר של המוצר בתוספת המע”מ.
ברור שמה שעל הפונקציה לעשות זה לקחת את המחיר של המוצר מתוך השדה price, ולהכפיל אותו ב 1.18 (בהנחה שהמע”מ הוא 18%)
בעיקרון פונקציה כזו אמורה לדעת לעבוד אך ורק בעולמם של ה”מוצרים”, ולכן במקום להגדיר סתם פונקציה כללית, נוכל להגדיר את הפונקציה בצורה כזו שהיא תהיה שייכת למחלקה.

איך עושים זאת?

אז בקוד הבא יצרנו שוב את המחלקה Product, עם השדות “שם” ו”מחיר”, אלא שהפעם הוספנו למחלקה גם “פונקציה” משלה:

				
					class Product():
     name = None
     price = None
     def plus_maam(self):
        print("Calculation Taxes..")
        result = self.price * 1.18   # Ma'am = 18%
        return result 
				
			

נשים לב מה עשינו:

  • בתוך השורות המוזחות של המחלקה, יצרנו פונקציה בצורה הרגילה שאנו מכירים, בעזרת המילה השמורה def לאחריה ציון השם – קראנו לה בשם “פלוס-מעמ”.
  • אח”כ הוספנו סוגריים עגולות ונקודותיים, כמו בכל פונקציה.
  • החלק המוזר הוא: בתוך הסוגריים העגולות הגדרנו משתנה בשם self.
    המשתנה self שציינו, הוא יהיה ה “מופע” שעליו הפונקציה תבצע את החישוב.
    ואכן בשורות לאחר מכן, בשביל לחשב את המע”מ, הפונקציה פנתה דרך המופע self לשדה price.

אוקי, זה טוב ויפה.
איך כעת נוכל להשתמש בפונקציה הזו?
אז בשביל להשתמש בפונקציה של המחלקה, אנו חייבים שיהיה לנו קודם כל מופע שלה.

אז נניח שיש לנו מוצר (מופע) בשם salt, ואנו רוצים לדעת מה מחירו כולל מע”מ, אנו לכאורה נצטרך לקרוא לפונקציה, ולשלוח לה את המופע בעל השם salt (שיכנס לתוך ה-self)

				
					salt = Product()
salt.name = "Salt"
salt.price = 4.99
final_price = plus_maam(salt) 
				
			

אך לא, אם נעשה זאת אנו נקבל שגיאה.
הסיבה היא שהפונקציה plus_maam לא מוכרת למחשב. בשביל שהיא תהיה מוכרת למחשב, היא חייבת להופיע בהקשר של המחלקה.
כיוון שיש לנו ‘מופע’ של המחלקה, אנו נוכל באמצעות המופע salt לגשת לפונקציה:

				
					final_price = salt.plus_maam(salt) 
				
			

הסבר:
מכיוון שהפונקציה plus_maam לא מופיע בפני עצמה, אלא בהקשר של המופע (על ידי ציון שם המופע ואז נקודה), אז המחשב מכיר את הפונקציה ומבין למה הייתה כוונתנו.

אך לא, גם צורה זו איננה לגמרי תקינה, למה?
כיוון שאנו ניגשים לפונקציה דרך המשתנה salt, אנו לא צריכים יותר לשלוח את המשתנה salt בצורה מפורשת לפונקציה. הוא יעבור לשם אוטומאטית 🙂
ואם כך, כל מה שנצטרך לעשות זה פשוט:

				
					final_price = salt.plus_maam() 
				
			

כעת בתוך הפונקציה, המשתנה self יקבל את המופע salt. אך בצורה מרומזת.
מרומז – implicit באנגלית, ולא explicit – מפורש.
מונחים שכדאי שנכיר… הם חלק מהסלנג המקצועי בעולם התכנות.

אז שוב, מה עשינו?
יצרנו פונקציה ברמת המחלקה, ובשביל להשתמש בה, תחילה יצרנו מופע, ואז דרך המופע ביצענו קריאה לפונקציה.
מכיוון שהפונקציה הוגדרה לקבל רק פרמטר אחד – את המופע עצמו, אז בעת הקריאה לא נדרשנו לשלוח לה כלום. למה? כי המופע נשלח לפונקציה בצורה מרומזת בגלל עצם זה שהקריאה לפונקציה נעשתה דרכו.

אם נרצה שהפונקציה תקבל פרמטרים נוספים, למשל אם נרצה שהמע”מ שהפונקציה שלנו מחשבת, יהיה גם כן ארגומנט שישלח לפונקציה (ולא יהיה קבוע 18% כמו שעשינו), נוכל להגדיר את הפונקציה plus_maam באופן כזה:

				
					def plus_maam(self, maam):
     return self.price * (1 + maam) 
				
			

מה עשינו? פשוט הוספנו בהגדרת הפונקציה פרמטר נוסף, בדיוק באותו אופן שעשינו זאת בפונקציות רגילות (שאינם חלק ממחלקה) בחלק הראשון של הקורס.

כעת, כאשר נשתמש במופע salt כדי לחשב את מחירו כולל המע”מ, נצטרך לשלוח לפונקציה רק את הערך של המע”מ, כי המשתנה עצמו כידוע, נשלח בצורה מרומזת.
אז בקיצור, נעשה כך:

				
					final_price = salt.plus_maam(0.18) 
				
			

הערה: אולי יהיה חכם מצידנו להגדיר ערך ברירת מחדל עבור המע”מ בדיוק כמו שלמדנו בעולם הפונקציות:

				
					def plus_maam(self, maam=0.18):
     . . . 
				
			
תרגיל: Box

צור מחלקה המייצגת “תיבה”.
המאפיינים של תיבה הם המידות שלה…
ולכן, תצטרך ליצור למחלקה שדות בשם: גובה, רוחב ואורך.
כמו כן דאג שלמחלקה תהיינה הפונקציות הבאות:

א. פונקציה המחשבת (ומחזירה) את השטח של הקוביה (רוחב כפול אורך)
ב. פונקציה המחשבת את הנפח של הקוביה (רוחב * גובה * אורך)
ג. פונקציה המדפיסה את כל הנתונים של הקוביה.
על פונקציה זו להדפיס את הרוחב הגובה והאורך, אך פרמטר אופציונאלי שיתקבל לפונקציה, עשוי לבקש ממנה להדפיס גם את הנפח שלה. (בעזרת הפונקציה הקודמת..)

הערה: כמו שניגשנו לשדות (משתנים) של מחלקה בתוך פונקציה באמצעות המשתנה self, אנו ניגש באופן דומה גם לפונקציות של המחלקה.

בנאי

פונקצית איתחול – בנאי (באנגלית: constructor – מילה חשובה)

כאשר יצרנו אובייקט (או ‘מופע’) של מחלקה, ונתנו ערכים לשדות שלו, עשינו זאת בכמה שורות.
שורת יצירת האובייקט:

				
					salt = Product() 
				
			
ואז שורת הצבת ערך:
				
					salt.name = "Salt" 
				
			

למעשה, ישנה דרך קצרה ונעימה יותר, שתאפשר לנו לקבוע את שם המוצר כבר בעת יצירתו. 
באופן הבא:

				
					salt = Product(name="Salt") 
				
			

מה עשינו?
בתוך הסוגריים העגולות שאנו כותבים בעת יצירת מופע, הוספנו שם של שדה וערך.

נכון דרך מגניבה?
נוכל גם “לאתחל” כמה שדות, למשל:

				
					salt = Product(name="Salt", price=5.5) 
				
			

אבל כדי שכל הטוב הזה יקרה, אנו נהיה חייבים קודם להגדיר את המחלקה בצורה שתתמוך בכך.
איך עושים זאת?
אנו נצטרך ליצור פונקצית אתחול.
הפונקציה נראית כך:

				
					class Product():
     def __init__(self, name, price):
        self.name = name
        self.price = price
        self.barkod = None 
				
			

נשים לב לכמה דברים:

  • שם הפונקציה הוא קצת מוזר, והוא חייב להיות כך: __init__
  • הפונקציה מקבלת את המופע self, וגם את הפרמטרים שנרצה לאפשר “לאתחל” בעת יצירת המופע.
  • שמות המשתנים שהתקבלו לפונקציה הם name ו-price, אבל כמובן שיכולנו סתם לקרוא להם x ו-y. רק שאם היינו עושים כך, שורת היצירה של המופע לא תוכל להיות יותר:
				
					salt = Product(name="Salt", price=5.5) 
				
			
אלא
				
					salt = Product(x="Salt", y=5.5) 
				
			

אני מקווה שברור לכם למה, אם לא, חזרו לפרק של הפונקציות 🙂

  • אם עד כה, בשביל “להצהיר” על כך שלמחלקה ישנם שדות כאלו או אחרות רשמנו אותם ישירות תחת הצהרת המחלקה, כעת נוכל להצהיר על קיומם בפונקציה __init__ עצמה. אך נצטרך להוסיף את המילה self לפני. כמו שעשינו בדוגמה.

תרגיל:

צור מחלקה המייצגת שולחן.
עליך ליצור לשולחן את השדות:

  • אורך
  • רוחב
  • מחיר

השולחנות שהמחלקה מייצגת, כולם מתוצרת איקאה, כך שלמחלקה גם יהיה שדה בשם company שיאותחל תמיד בשם IKEA.

כמו כן, צור למחלקה פונקצית איתחול (בנאי), שתאתחל את השדות אורך ורוחב ומחיר.
לשדה מחיר עליך לציין ערך ברירת מחדל של 100.

בנוסף, למחלקה תהיינה הפונקציות הבאות:

  • פונקצית חישוב שטח השולחן (רוחב * אורך)
  • פונקציה בשם is_worth, המקבלת מספר כלשהו X, ויודעת להדפיס האם “כדאי” לקנות שולחן זה או לא.
    הבדיקה תהיה כך: אם המחיר חלקי השטח של השולחן גדול מ X (הפרמטר שהתקבל לפונקציה) אז התשובה תהיה “אמת”, אחרת – False.

לסיום, צור קוד היוצר שני שולחנות, אחד עם מחיר “כדאי”, ואחד עם מחיר “לא כדאי”. (כאשר ה X לבדיקת כדאיות שווה 50)
השתמש בפונקציות של המחלקה בשביל להראות את הכדאיות…

פתרון:
				
					class Table():
    def __init__(self, length, width, price=100):  # בנאי
        self.company = 'IKEA'
        self.length = length
        self.width = width
        self.price = price
    def get_size(self):
        return self.length * self.width
    def is_worth(self, x):
        size = self.get_size()
        piece_price = self.price / size
        return piece_price < x   # return a Boolean value

# Testing class code:
table1 = Table(3, 2, 10)
table2 = Table(3, 2, 8000)
print(table1.is_worth(50))
print(table2.is_worth(50)) 
				
			

הערה: כתיבה מקצועית תיעשה על ידי ציון שם של מחלקה כך שיתחיל באות גדולה.
בנוסף, אם שם המחלקה מכיל יותר ממילה אחת, אנו נכתוב אותם בצפיפות, באופן הבא:  MyClass

ולא על ידי קו תחתון (כמו פונקציות או משתנים) My_class.

ואם במנהגים עסקינן…
גם השימוש שלנו במילה self בשביל לציין את שם המשתנה המכיל את המופע, הוא מנהג… יכולנו להשתמש בשם אחר לכך.

אם אנו מתעניינים ואוהבים את ה “מנהגים” הללו, אנו נרצה להציץ במסמך הזה.

אעיר ואוסיף, שהמנהגים הללו הם אחד ההבדלים בין מתכנת מקצועי לשאינו כזה…

חבר’ה, יש לי עוד הרבה דברים לספר לכם על מחלקות.
יש מלא דברים שאפשר לעשות עם מחלקות שלא דיברנו עליהם, אני אנסה להכיר לכם את העיקריים שבהם שלא ציינו.

אז ראינו שמחלקה יכולה להכיל שדות, כמו “שם”, “מחיר” וכדומה.
למעשה, מחלקה מסוגלת להכיל גם “מילון” או “רשימה”.
למשל, מחלקה שמייצגת “חנות”, תוכל להכיל גם רשימה של מחרוזות, שמייצגת את שמות העובדים בחנות.

ומעבר לכך, מחלקה גם מסוגלת להכיל כשדה, גם “מופעים” של מחלקות אחרות.
למשל, נניח שאנו בונים תוכנית לניהול קניון.
אנו ניצור מחלקה בשם “איש” וכן מחלקה בשם “חנות”, אחד השדות של המחלקה “חנות” ניצור שדה בשם “מנהל”, וכך נוכל להציב בתוך המשתנה “מנהל”, מופע של המחלקה “איש”.

				
					class Person:
    def __init__(self, name, age):
        self.name = age
    self.age = name
class Store:
    def __init__(self, name, manager):
        self.manager = manager
        self.name = name 
				
			

עכשיו ניצור מופע של “איש”:

				
					dave = Person(name=’Dave’, age=30) 
				
			
וכעת נוכל “להוסיף” את המופע, למופע חדש של “חנות”:
				
					zara = Store(name=’Zara’, manager=dave) 
				
			

וכמו שמחלקה יכולה להכיל “מופע” של מחלקה אחרת, כך היא יכולה להחזיק גם “רשימה” של מופעים של מחלקה אחרת. (וכל קומבינציה אחרת שתעלו על דעתכם)

בוא ננסה לתרגל בעצמנו תרגיל פשוט:

  • כתוב מחלקה שמייצגת “מוצר”, עם המאפיינים: שם-מוצר, מחיר, תאריך ייצור.
  • צור מחלקה בשם “חנות”, עם המאפיינים:
    • רשימה של מוצרים.
    • פונקציה שמוסיפה מוצרים לחנות (הפונקציה מקבלת “מוצר”, ומוסיפה אותו).
    • ופונקציה אחרת שמטרתה “למחוק” מוצרים מהחנות.

 

למתקדמים:

נסו לכתוב את הפונקציות כך שיוכלו לקבל מוצר אחד או יותר, בשביל להוסיף/למחוק מהרשימה.

פתרון:
				
					class Product:
    def __init__(self, name, price, date):
        self.name = name
        self.price = price
        self.date = date

class store():
    def __init__(self):
        self.products = []
    def add_product(self, p):
        self.products.append(p)
    def remove_product(self, p):
        self.products.remove(p) 
				
			

בשביל לבדוק אם מה שעשינו תקין, נוכל לנסות להריץ את הקוד הבא:

				
					s = store()
table = Product('Tabel', 150, "12/12/2019")
chair = Product('chair', 30, "12/12/2018")
s.add_product(table)
s.add_product(chair)
print(s.products) 
				
			
אבל מה שיקרה הא שההדפסה תכיל משהו כזה:
				
					[<__main__.Product object at 0x7ff11da86c10>, <__main__.Product object at 0x7ff11da86c50>] 

				
			

הסיבה היא שמודפס לנו רשימה של “אובייקטים” מסוג “מוצר”.
אבל איך המחשב יידע כיצד להדפיס כל מוצר ברשימה?
בשביל שההדפסה תהיה יותר מובנת, נוכל להוסיף עבור כל מוצר את הפונקציה __repr__ שלמדנו מוקדם יותר בשיעור, ואז ההדפסה אוטומאטית תבצע מה שיוגדר בפונקציה הזו.

סוגי פונקציות של מחלקה

כאשר אנו ניצור תחת מחלקה פונקציות, נוכל לסווג אותן לשלושה סוגי פונקציות.

  • פונקציה שתפקידה לבצע פעולה על אובייקט. (למשל להדפיס מחיר של מוצר מסוים)
  • פונקציה שתפקידה לא קשור כלל למחלקה. (למשל שסתם מדפיסה “שלום עולם”)
  • פונקציה שתפקידה קשור למחלקה עצמה, ולא למופע מסוים.


ובהרחבה:

  1. הסוג הראשון שציינו, הוא פונקציה אשר מטרתה לבצע פעולה על מופע (אובייקט) של המחלקה.
    בשביל שפונקציה כזו תוכל לבצע פעולה על אובייקט, אז מובן שהיא צריכה “לקבל” את האובייקט כפרמטר. אז הדרך לעשות זאת זה בדיוק בצורה שעשינו עד כה. שלחנו את הפרמטר בצורה מרומזת לפונקציה, והיא קיבלה אותו לתוך משתנה בשם self.
  2. הסוג השני: פונקציה אשר מטרתה לבצע פעולה ללא קשר כלל למחלקה או לאובייקט. ברמת העיקרון לא היינו מצפים שפונקציה כזו בכלל תהיה חלק מהמחלקה, אבל במידה וכך אנו מעוניינים שיקרה, אז בעצם אין כל צורך שנעביר איזשהו אובייקט לפונקציה, וכמו כן, אין סיבה שנצטרך ליצור אובייקט בשביל לקרוא לפונקציה, כי היא לא אמורה לבצע פעולה כלשהי בשביל אובייקט.  בשביל להגדיר פונקציה כזו בצורה נכונה, אנו נוסיף מעל שורות הפונקציה את השורה הבאה: [email protected]
    ברגע שהוספנו את השורה הזו (מעל שורת ה-def של הפונקציה), מאותו רגע ואילך ניתן לקרוא לפונקציה בשתי דרכים. או דרך מופע, או דרך ציון שם המחלקה עצמה. 
    הפונקציה לא תקבל כלל את האובייקט, ולכן נוכל ליצור אותה כך שהיא לא מקבלת כלום, ואם אנו נרצה שבשביל הפעולה שלה היא כן תקבל איזשהם פרמטרים, נוכל לציינם בלי שהמשתנה הראשון יהיה self
    דוגמה לפונקציה כזו, שכל מטרתה היא לקבל פרמטר X ולהדפיס אותו, (כמובן פונקציה שהיא חלק ממחלקה מסוימת A)
				
					class A:
     @staticmethod
     def staticmethod_example(x):
        print(x) 
				
			

קריאה לפונקציה הזו, תוכל להיות או בצורה רגילה דרך אובייקט כמו שראינו בסוג הראשון, או גם כאשר אין לנו אובייקט, דרך ציון שם המחלקה A, ואז נקודה, ושם הפונקציה:

				
					A.example_function(5) 
				
			

הסוג האחרון:

פונקציה שלא מבצעת פעולות ברמת המופע של המחלקה, כי אם ברמת המחלקה עצמה.
למשל, אם נרצה ליצור למחלקה פונקציה שמדפיסה למשל את כל השדות שיש למחלקה, תתאים לסוג הזה.
ואיך עושים זאת?
מכיוון שהפונקציה לא מבצעת פעולות ברמת אובייקט, אז מה שהיא צריכה לקבל זה את המחלקה עצמה, ולא אובייקט.
כאשר נוסיף מעל שורות הפונקציה את השורה: [email protected]
מאותו רגע, המשתנה הראשון שמתקבל לפונקציה (מה שהכרנו עד כה כ-self שמייצג מופע) יהיה כעת משתנה שיקבל את המחלקה עצמה. לכן גם לא נקרא לו self, אלא cls (מלשון קלאס – המחלקה עצמה)
בשביל לקרוא לפונקציה, נוכל לעשות זאת גם כן (כמו הסוג השני) בשני אופנים. או על ידי ציון שם המחלקה, או דרך אובייקט.
כדוגמה: (פונקציה שמדפיסה את כל השדות של המחלקה – על הדרך גם נלמד איך עושים זאת)

				
					class A:
     @classmethod
     def classmethod_example(cls):
        print([i for i in cls.__dict__.keys() if i[:1] != '_']) 
				
			

הערה: לא נתעמק כרגע בלהבין את שורת ההדפסה שהפונקציה ביצעה (שמדפיסה את כל המשתנים והפונקציות של המחלקה), רק נציין שהשדות של המחלקה כמו גם הפונקציות, הן ברמת המחלקה עצמה. ולא ברמת אובייקט. (למעט כמובן שדות ש “נדחפו” לאובייקט, לא משנה אם בזמן ריצת הבנאי או סתם בקוד מחוץ למחלקה, בכל מקרה שדות אלו כבר לא יהיו שדות של המחלקה, והן לא תודפסנה בשורת ההדפסה הזו).

 
תרגיל מאתגר:

נתונה המחלקה הבאה:

				
					class Product():
     company = 'IKEA'
     def __init__(self, name):
        self.name = name 
				
			

בקוד שלהלן, ישנה שורה אחת שאיננה תקינה.
נסה להבין מהי, ולמה.

				
					print(Product.company)
print(Product.name)
print(Product('Table').name)
print(Product('Chair').company) 
				
			
פתרון:

שורת הקוד שמנסה להדפיס את השם של המוצר, ללא יצירת מופע:

				
					print(Product.name) 
				
			

איננה תקינה.
הסיבה היא, שהמשתנה name לא באמת נוצר כל עוד לא יצרנו מופע של המחלקה.

 

נתראה בשיעור הבא 🙂

כניסה

שכחתי סיסמה

אין לך חשבון? להצטרפות

איפוס סיסמה:

שכח את הסיסמה? הזן את שם המשתמש או כתובת הדואר אלקטרוני. תקבל קישור לאיפוס סיסמה באמצעות דואר אלקטרוני.

ברכות! סיימתם את השיעור הראשון בקורס!

עשיתם את הצעד הראשון בדרך שלכם להיות מתכנתים מקצועיים
הצטרפו אלינו כדי להמשיך במסלול שיוביל אתכם לעתיד בהייטק

שינוי סיסמה

עריכת פרטים אישיים