בדוגמא של Instrumental.str אנו קוראים לSong.str(self), וע"י כך קוראים לשורה:
self._views = self._views + 1
אך משום מה, ההדפסה עצמה עדיין נעשית על פי הפורמט הרשום בInstrumental, ולא על פי הפורמט בSong.
לא ככ ברור לי, כיצד פייתון יודע עבור אילו שורות הוא צריך לעקוב אחרי מחלקת העל, ואילו אחרי המחלקה הנוכחית?
orpazf
ההדפסה נעשית על פי ערך ההחזרה של המתודה __str__ שרלוונטית עבור האובייקט, כלומר של המחלקה הנוכחית אם יש - ואם לא אז של מחלקת העל. במקרה הזה יש במחלקה הנוכחית ולכן זה ערך ההחזרה הרלוונטי
2 לייקים
yuval.cagan
כמו שאורפז אמרה, פייתון תמיד בודק האם יש הגדרה לפעולה ברמת התת- מחלקה, ורק אם אין מתבצעת קריאה למחלקת העל. בנוסף, הקריאה למחלקת העל בתוך הפונקציה מחזירה ערך שלא נשמר כמשתנה והוא אינו ערך ההחזרה הסופי של הפונקציה אל המשתמש.
assi
תודה על התשובות, זה קצת יותר מובן!
בכל אופן, מה שמבלבל, זה שברגע שמציינים song.str, פייתון אכן יודע להכנס ל__str__ עבור בכדי לעדכן את self._views, אך היא יודעת לעצור שם, ולהחזיר (return) את הערך מהתת-מחלקה.
orpazf
היא לא עוצרת שם בכלל
זו קריאה רגילה לפונקציה וכל הקוד בה מתבצע. אם למשל תוסיף הדפסה בפונקציה המקורית היא תתקיים. נסה לשמור את ערך ההחזרה של הפונקציה למשתנה ולהדפיס אותו - ולהיווכח בכך במו עיניך.
היא אמנם מחזירה את המחרוזת כפי שהיא מוגדרת במחלקת העל, אבל אנחנו לא משתמשים בה ואף לא שומרים אותה במשתנה, אלא יוצרים מחרוזת חדשה - ולכן זה רק נראה כאילו אנחנו לא עושים שום דבר נוסף מלבד העדכון.
aviadamar
מכיוון שזה אכן מבלבל וגם אני קצת השתגעתי עם זה אני נותן פה דוגמא פשוטה פשוטה שמסבירה בדיוק את זה שהפונקציה מבצעת את str המקורי (את כל מה שיש בו, גם הדפסות, גם השמות משתנים וגם return) ומחזירה אותו לחstr החדש… ועליו אנחנו עובדים.
דוגמא:
class A:
def __str__(self):
return "Hello "
class B(A):
def __init__(self, name):
self.name = name
def __str__(self):
return super().__str__() + self.name
ככה שעבור:
aviad = B('Aviad')
print(aviad)
יחזור:
Hello Aviad
4 לייקים
assi
כן, זה קצת מסתדר יותר עכשיו, דוגמא טובה. תודה!
לייק 1
livnadr
אפשר להפנות אותך להביט שוב בדוגמת ה - Instrumental תחת הכותרת המשנית super?
בדוגמה במחברת נראה שכן ביצעו שכפול קוד ב - str, שלא כמו ב - init.
ממה שאני הבנתי רצו לחסוך את השורה של ה - count, אבל לטעמי לפחות, עדיף להכניס את ערך ההחזרה שמגיע מ - str ממחלקת העל למשתנה ועליו לבצע מניפולציות. ככה לא קיים שכפול קוד.
מה דעתך?
Yam
מה יקרה אם הערך שמוחזר מ־str ישתנה טיפה?
זה משאיר אותנו קצת יותר פגיעים למחלקת־על שברירית
livnadr
אני מבינה. אבל, אפשר להגיד את זה גם על init, לא?
זה מרגיש שאין לזה סוף. גם בהכלה שינוי במחלקה מוכלת דורש ערנות.
אני אשמח אם תוכל לחדד את הניואנס.
Yam
לא, כי __init__לא מחזיר ערך
עדיף לא לקבל את הערך של מחלקת־העל ולעבוד עליו אם הערך הוא מחרוזת, לדוגמה.
באופן כללי, הסתמכות על מחרוזות בארכיטקטורה של התוכנה היא לרוב רעיון לא כ"כ טוב כי הן נוטות להשתנות באופן די תדיר.
אני מסכים שבאופן כללי הסיפור הזה של מחלקות וירושה דורש הרבה ערנות. זה מבאס אבל זה חלק מהמשחק.
לייק 1
livnadr
אפשר לשאול עוד משהו?
מקווה שאסביר את עצמי כמו שצריך…
שבוע שעבר כשדיברנו על תכונות/פעולות פרטיות ומוגנות, צוין שבאופן כללי פייתון היא שפה למבוגרים אחראיים. למדנו גם שפייתון מאפשרת בכל מיני דרכים פתלתלות לעקוף את המוסכמות בעניין גישה לתכונות ופעולות כאלו.
בנוסף למדנו שמתכנתים שמגיעים משפות אחרות התרגלו לתת גישה עקיפה דרך גטרס וסטרס.
הסקתי מהנ"ל שאין סיבה שאשתמש בגטרס וסטרס בפייתון. הרי אם המוסכמה היא שכשהגדרתי שלא נוגעים אז לא נוגעים וממילא מי שירצה בכך - לא יצטרך את גטרס וסטרס בשביל זה.
השבוע במחברת יש דוגמה (נגדית) שמשתמשת בגטרס וסטרס.
אז שתי שאלות:
אם הדוגמה מופיעה, כן מקובל להשתמש בגטרס וסטרס גם בפייתון?
בהנחה שהתשובה ל-1 היא כן: למה לא מספיק להסתמך על המוסכמה? קראתי פוסטים בפורום ונאמר שכדאי להקשות על הגישה למרות שהגדרנו כפרטיות/מוגנות. החשיבה שלי היא שאם יש מוסכמה אחת, למה צריך להעמיס עליה עוד גדר? הרי אולי גם הגדר הזו לא תספיק?