שאלה לגבי קריאה ל __str__ ממחלקת העל, והוספת פלט נוסף

בדוגמא של Instrumental.str אנו קוראים לSong.str(self), וע"י כך קוראים לשורה:
self._views = self._views + 1

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

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

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

2 לייקים

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

תודה על התשובות, זה קצת יותר מובן!
בכל אופן, מה שמבלבל, זה שברגע שמציינים song.str, פייתון אכן יודע להכנס ל__str__ עבור בכדי לעדכן את self._views, אך היא יודעת לעצור שם, ולהחזיר (return) את הערך מהתת-מחלקה.

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

מכיוון שזה אכן מבלבל וגם אני קצת השתגעתי עם זה אני נותן פה דוגמא פשוטה פשוטה שמסבירה בדיוק את זה שהפונקציה מבצעת את 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 לייקים

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

לייק 1

אפשר להפנות אותך להביט שוב בדוגמת ה - Instrumental תחת הכותרת המשנית super?
בדוגמה במחברת נראה שכן ביצעו שכפול קוד ב - str, שלא כמו ב - init.
ממה שאני הבנתי רצו לחסוך את השורה של ה - count, אבל לטעמי לפחות, עדיף להכניס את ערך ההחזרה שמגיע מ - str ממחלקת העל למשתנה ועליו לבצע מניפולציות. ככה לא קיים שכפול קוד.
מה דעתך?

מה יקרה אם הערך שמוחזר מ־str ישתנה טיפה?
זה משאיר אותנו קצת יותר פגיעים למחלקת־על שברירית

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

לא, כי __init__לא מחזיר ערך :slight_smile:
עדיף לא לקבל את הערך של מחלקת־העל ולעבוד עליו אם הערך הוא מחרוזת, לדוגמה.
באופן כללי, הסתמכות על מחרוזות בארכיטקטורה של התוכנה היא לרוב רעיון לא כ"כ טוב כי הן נוטות להשתנות באופן די תדיר.

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

לייק 1

אפשר לשאול עוד משהו? :slight_smile:
מקווה שאסביר את עצמי כמו שצריך…

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

השבוע במחברת יש דוגמה (נגדית) שמשתמשת בגטרס וסטרס.
אז שתי שאלות:

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

אעדיף שתפתחי בשביל זה אשכול חדש, למען הסדר הטוב

לייק 1