כיצד להשתמש בשיטות __str__() ו-__repr__() בפייתון

הקדמה

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

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

מה ההבדל בין __str__() ל־__repr__()?

אופציה `__str__()` מחזירה מחרוזת שניתנת לקריאה על ידי אדם, או מצג לא רשמי של אובייקט. פעולה זו נקראת על ידי הפונקציות המובנות print(), str(), ו־format(). אם לא תגדיר מתודה __str__() עבור מחלקה, אז המימוש המובנה של האובייקט יקרא למתודה __repr__() במקום.

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

באופן כללי, מחרוזת של __str__() מתאימה למשתמשים ומחרוזת של __repr__() מתאימה למפתחים.

__str__() ו־__repr__() – דוגמאות באמצעות מחלקה מובנית

הדוגמאות בסעיף זה קוראות ישירות למתודות __str__() ו־__repr__() לצורך הדגמה.

מחלקת datetime.datetime היא מחלקה מובנית בפייתון שיש לה מימוש ברירת מחדל של מתודות __str__() ו־__repr__().

הקוד לדוגמא הבאה מראה את המחרוזות שמוחזרות על ידי היישום הברירת מחדל של מתודות __str__() ו־__repr__() עבור אובייקט מסוג datetime.datetime:

import datetime

mydate = datetime.datetime.now()

print("__str__() string: ", mydate.__str__())
print("str() string: ", str(mydate))

print("__repr__() string: ", mydate.__repr__())
print("repr() string: ", repr(mydate))

הפלט הוא:

Output
__str__() string: 2023-01-27 09:50:37.429078 str() string: 2023-01-27 09:50:37.429078 __repr__() string: datetime.datetime(2023, 1, 27, 9, 50, 37, 429078) repr() string: datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)

הפלט מראה כי הפונקציה str() קוראת ל־__str__() ומחזירה מחרוזת ידידותית לאדם, בעוד שהפונקציה repr() קוראת ל־__repr__() ומחזירה מחרוזת עשירה במידע יותר המשמשת לשחזור האובייקט. למעשה, ניתן להשתמש בפונקציה repr() עם הפונקציה eval() כדי ליצור אובייקט חדש מהמחרוזת:

import datetime

mydate1 = datetime.datetime.now()
mydate2 = eval(repr(mydate1))

print("mydate1 repr() string: ", repr(mydate1))
print("mydate2 repr() string: ", repr(mydate2))

print("the values of the objects are equal: ", mydate1==mydate2)

הפלט הוא:

Output
mydate1 repr() string: datetime.datetime(2023, 1, 26, 9, 43, 24, 479635) mydate2 repr() string: datetime.datetime(2023, 1, 26, 9, 43, 24, 479635) the values of the objects are equal: True

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

__str__() ו־__repr__() דוגמאות באמצעות מחלקה חדשה

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

המחלקה הבאה אינה מיישמת את מתודות __str__() או __repr()__:

class Ocean:

    def __init__(self, sea_creature_name, sea_creature_age):
        self.name = sea_creature_name
        self.age = sea_creature_age

c = Ocean('Jellyfish', 5)

print(str(c))
print(repr(c))

הפלט כאשר אתה משתמש ב־str() ו־repr() הוא:

Output
<__main__.Ocean object at 0x102892860> <__main__.Ocean object at 0x102892860>

הדוגמה הקודמת מדגימה כי המימוש הברירת מחדל של __repr()__ עבור האובייקט מחזיר מחרוזת עם המחלקה וה־id של האובייקט בפורמט הקסדצימלי, שאינו מאוד שימושי. שימו לב ש־str() ו־repr() מחזירים את אותה הערך, מכיוון ש־str() קורא ל־__repr__() כאשר __str__() אינו מיושם.

עדכנו את מחלקת האוקיינוס עם מימושים של השיטות __str__() ו־__repr__():

class Ocean:

    def __init__(self, sea_creature_name, sea_creature_age):
        self.name = sea_creature_name
        self.age = sea_creature_age
    
    def __str__(self):
        return f'The creature type is {self.name} and the age is {self.age}'

    def __repr__(self):
        return f'Ocean(\'{self.name}\', {self.age})'

c = Ocean('Jellyfish', 5)

print(str(c))
print(repr(c))

הפלט הוא:

Output
The creature type is Jellyfish and the age is 5 Ocean('Jellyfish', 5)

המימוש של __str__() בדוגמה הקודמת מחזיר מחרוזת שקלה לקריאה המספקת את הפרטים הרלוונטיים של האובייקט למשתמש. המימוש של __repr__() מחזיר מחרוזת שהיא ביטוי Python תקף שיכול לשמש ליצירת האובייקט מחדש: Ocean('Jellyfish', 5). הדוגמה משתמשת ב־עיצוב f-string עבור המחרוזות, אך ניתן לעצב את המחרוזות באמצעות כל עיצוב נתמך על ידי Python.

מסקנה

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

Source:
https://www.digitalocean.com/community/tutorials/python-str-repr-functions