درک و استفاده از __str__ و __repr__ در پایتون

درک و استفاده از __str__ و __repr__ در پایتون

در پایتون، نمایش یک شیء (object) به صورت قابل خواندن برای انسان، یکی از جنبه‌های مهم برنامه‌نویسی است. دو متد ویژه، __str__ و __repr__، نقش کلیدی در این زمینه ایفا می‌کنند. این دو متد به شما امکان می‌دهند نحوه نمایش یک شیء را در موقعیت‌های مختلف کنترل کنید. در این مقاله، به بررسی عمیق این دو متد، تفاوت‌های آن‌ها، و نحوه استفاده صحیح از آن‌ها می‌پردازیم. این مقاله در سطح ‘مفاهیم متوسط’ پایتون قرار می‌گیرد و برای افرادی که با مفاهیم پایه پایتون آشنا هستند مناسب است.

__repr__ چیست؟

متد __repr__ (مخفف representation) یک نمایش رسمی و بدون ابهام از یک شیء را ارائه می‌دهد. هدف اصلی این متد، ارائه اطلاعاتی است که بتواند شیء را دوباره ایجاد کند (یا حداقل، تا حد امکان به آن نزدیک شود). به عبارت دیگر، __repr__ باید یک رشته را برگرداند که به عنوان یک عبارت پایتون معتبر، قابل ارزیابی باشد و شیء مشابهی را ایجاد کند.

اگر یک کلاس متد __repr__ را تعریف نکند، پایتون به طور پیش‌فرض از یک نمایش عمومی استفاده می‌کند که معمولاً شامل نام کلاس و آدرس حافظه شیء است. این نمایش برای انسان چندان قابل فهم نیست، اما برای دیباگ کردن و شناسایی شیءها مفید است.

به عنوان مثال:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(2, 3)
print(repr(p))  # خروجی: <__main__.Point object at 0x...>

همانطور که می‌بینید، خروجی repr(p) یک رشته است که نشان می‌دهد p یک شیء از کلاس Point است و آدرس حافظه آن را نمایش می‌دهد. این اطلاعات برای انسان چندان مفید نیست.

__str__ چیست؟

متد __str__ (مخفف string) یک نمایش غیررسمی و برای انسان قابل فهم از یک شیء را ارائه می‌دهد. هدف اصلی این متد، ارائه یک رشته‌ای است که به راحتی قابل خواندن و درک باشد. این متد معمولاً برای نمایش شیء به کاربران نهایی استفاده می‌شود.

اگر یک کلاس متد __str__ را تعریف نکند، پایتون به طور پیش‌فرض از خروجی متد __repr__ استفاده می‌کند. به همین دلیل، توصیه می‌شود که همیشه متد __str__ را برای کلاس‌های خود تعریف کنید تا یک نمایش مناسب و قابل فهم از شیء ارائه دهید.

به عنوان مثال:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p = Point(2, 3)
print(str(p))  # خروجی: Point(2, 3)
print(p)      # خروجی: Point(2, 3) (به دلیل استفاده از str(p) به طور ضمنی)

در این مثال، متد __str__ را برای کلاس Point تعریف کرده‌ایم. این متد یک رشته را برمی‌گرداند که نشان می‌دهد شیء p یک نقطه با مختصات (2, 3) است. این نمایش برای انسان بسیار قابل فهم‌تر از خروجی __repr__ است.

تفاوت‌های کلیدی بین __str__ و __repr__

| ویژگی | __repr__ | __str__ |
|—|—|—|
| هدف | ارائه یک نمایش رسمی و بدون ابهام | ارائه یک نمایش غیررسمی و برای انسان قابل فهم |
| مخاطب | توسعه‌دهندگان و دیباگرها | کاربران نهایی |
| قابلیت ارزیابی | رشته خروجی باید یک عبارت پایتون معتبر باشد | رشته خروجی لزوماً یک عبارت پایتون معتبر نیست |
| پیش‌فرض | اگر __str__ تعریف نشده باشد، از __repr__ استفاده می‌شود | اگر __repr__ تعریف نشده باشد، از یک نمایش عمومی استفاده می‌شود |

چه زمانی از کدام متد استفاده کنیم؟

به طور کلی، توصیه می‌شود که:

  • همیشه متد __repr__ را تعریف کنید. این متد باید یک نمایش دقیق و بدون ابهام از شیء را ارائه دهد که بتواند برای دیباگ کردن و شناسایی شیءها استفاده شود.
  • اگر می‌خواهید یک نمایش خاص و برای انسان قابل فهم از شیء ارائه دهید، متد __str__ را نیز تعریف کنید.
  • اگر متد __str__ را تعریف نکنید، پایتون به طور پیش‌فرض از خروجی متد __repr__ استفاده می‌کند.

مثال‌های بیشتر

بیایید چند مثال دیگر را بررسی کنیم تا درک بهتری از نحوه استفاده از این دو متد به دست آوریم.

مثال 1: کلاس Vector

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

v = Vector(1, 2)
print(repr(v))  # خروجی: Vector(1, 2)
print(str(v))   # خروجی: (1, 2)

در این مثال، متد __repr__ یک نمایش رسمی از شیء Vector را ارائه می‌دهد که شامل نام کلاس و مقادیر x و y است. متد __str__ یک نمایش ساده‌تر و برای انسان قابل فهم‌تر را ارائه می‌دهد که فقط شامل مقادیر x و y در داخل پرانتز است.

مثال 2: کلاس Date

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    def __repr__(self):
        return f"Date({self.year}, {self.month}, {self.day})"

    def __str__(self):
        return f"{self.day}/{self.month}/{self.year}"

d = Date(2023, 10, 27)
print(repr(d))  # خروجی: Date(2023, 10, 27)
print(str(d))   # خروجی: 27/10/2023

در این مثال، متد __repr__ یک نمایش رسمی از شیء Date را ارائه می‌دهد که شامل نام کلاس و مقادیر year، month و day است. متد __str__ یک نمایش رایج و برای انسان قابل فهم‌تر را ارائه می‌دهد که تاریخ را به صورت روز/ماه/سال نمایش می‌دهد.

نکات مهم

  • همیشه سعی کنید متد __repr__ را به گونه‌ای تعریف کنید که بتواند شیء را دوباره ایجاد کند.
  • متد __str__ را برای ارائه یک نمایش مناسب و قابل فهم از شیء به کاربران نهایی تعریف کنید.
  • اگر متد __str__ را تعریف نکنید، پایتون به طور پیش‌فرض از خروجی متد __repr__ استفاده می‌کند.
  • از f-strings برای ایجاد رشته‌های پویا و قابل خواندن در متد __repr__ و __str__ استفاده کنید.

نتیجه‌گیری

متدهای __str__ و __repr__ ابزارهای قدرتمندی هستند که به شما امکان می‌دهند نحوه نمایش اشیاء در پایتون را کنترل کنید. با درک تفاوت‌های بین این دو متد و نحوه استفاده صحیح از آن‌ها، می‌توانید کد خود را خواناتر، قابل فهم‌تر و قابل نگهداری‌تر کنید. به یاد داشته باشید که __repr__ برای توسعه‌دهندگان و دیباگرها است، در حالی که __str__ برای کاربران نهایی است.

بدون دیدگاه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *