التوابع السحرية في بايثون: __str__ مقابل __repr__

تُعرف لغة بايثون، باعتبارها لغة مفسرة عالية المستوى، بسهولة قراءتها ومبادئ تصميمها الرائعة. ومع ذلك، عندما تتعمق أكثر في بايثون، قد تبدو بعض الأشياء معقدة إذا كنت قادمًا من لغة لا تحتوي على ميزة مماثلة. إحدى هذه الميزات هي التوابع السحرية، وفي هذه المقالة، سنكشف غموض التوابع السحرية __str__ و__repr__، والاختلافات بينهما، ولماذا ومتى تستخدم كل منهما.

ما هي التوابع السحرية؟

التوابع السحرية في بايثون هي توابع خاصة تضيف “سحرًا” إلى فئاتك. وهي محاطة دائمًا بعلامتي سفلية مزدوجة (على سبيل المثال __init__ أو __lt__). تُعرف هذه التوابع أيضًا باسم أساليب dunder، وهي اختصار لـ “double under”. لا يُقصد من التوابع السحرية أن يتم استدعاؤها مباشرةً من قِبلك، ولكن الاستدعاء يحدث داخليًا من الفئة عند إجراء معين. على سبيل المثال، عند إضافة رقمين باستخدام عامل +، داخليًا، سيتم استدعاء التابع __add__.

class Number:
    def __init__(self, num):
        self.num = num

    def __add__(self, other):
        return self.num + other.num

num1 = Number(2)
num2 = Number(3)

print(num1 + num2)  # Output: 5

في المثال أعلاه، يمكنك أن ترى أن التابع __add__ تيستخدم لتمكين استخدام عامل +. هذا هو سحر التوابع السحرية!

يمكن للتوابع السحرية أن تجعل فئاتك تتصرف بشكل أشبه بالأنواع المضمنة في بايثون، وتجعل الكود الخاص بك أكثر سهولة في الاستخدام.

فهم التابع __str__

يمثل التابع __str__ في بايثون التمثيل غير الرسمي أو القابل للطباعة بشكل جيد لكائن ما. يتم استدعاء هذه التابع بواسطة الدالة المضمنة str() ودالة print لتحويل الكائن إلى سلسلة.

دعونا نلقي نظرة على مثال حيث نقوم بتعريف فئة Person باستخدام التابع __str__:

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

    def __str__(self):
        return f'Person(name={self.name}, age={self.age})'

p = Person('John Doe', 30)
print(p)

سيكون ناتج هذا الكود:

Person(name=John Doe, age=30)

في هذا المثال، يقوم التابع __str__ بإرجاع سلسلة تمثل كائن Person في نموذج يمكن قراءته بواسطة الإنسان.

فهم التابع __repr__

من ناحية أخرى، يقوم التابع __repr__ بإرجاع سلسلة تصف تمثيلًا دقيقًا لا لبس فيه لكائن. والهدف الرئيسي من هذه التابع هو توضيح معلومات الكائن. وهي مخصصة للاستخدام في تصحيح الأخطاء والتطوير. يتم استدعاء طريقة __repr__ بواسطة الدالة المضمنة repr().

فيما يلي مثال حيث نقوم بتعريف فئة Person باستخدام التابع __repr__ :

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

    def __repr__(self):
        return f'Person(name={self.name!r}, age={self.age!r})'

p = Person('John Doe', 30)
print(repr(p))

سيكون ناتج هذا الكود:

Person(name='John Doe', age=30)

في هذا المثال، يقوم التابع __repr__ بإرجاع سلسلة إذا تم تقييمها، فإنها ستنتج كائنًا مكافئًا لـ p. لاحظ استخدام !r في تنسيق السلسلة للتأكد من أن السلسلة الناتجة تستخدم repr() بدلاً من str(). هذا جزء من المحاولة لجعل الناتج لا لبس فيه.

ملاحظة: إذا لم تقم بتعريف التابع __str__ في فئتك، فسوف يقوم Python باستدعاء التابع __repr__ عند محاولة طباعة كائن.

الفرق بين __str__ و __repr__

في بايثون، تعد __str__ و__repr__ تابعين يخدمان غرضين مختلفين. للوهلة الأولى، قد تبدو التابعين متشابهين حيث تقوم كل منهما بإرجاع تمثيل نصي للكائن. ومع ذلك، فإن الاختلاف الرئيسي بينهما يكمن في الجمهور المستهدف ومستوى التفاصيل التي توفرها.

الغرض من التابع __str__ هو توفير وصف موجز يمكن قراءته من قبل البشر لكائن ما. وهو ما ستراه عند طباعة كائن ما. من ناحية أخرى، الغرض من التابع __repr__ هو توفير تمثيل كامل وواضح للكائن، وهو ما يكون أكثر فائدة للمطورين. وهو ما ستراه عند عرض الكائن في وحدة التحكم.

وهنا مثال لتوضيح هذا الاختلاف:

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

    def __str__(self):
        return f'{self.name} is {self.age} years old.'

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

p = Person('John', 30)

print(p)  # John is 30 years old.
p  # Person(John, 30)

هنا، تستدعي print(p) التابع __str__ وتعيد سلسلة نصية يمكن قراءتها بواسطة البشر. ومع ذلك، عندما تكتب p في وحدة التحكم، تستدعي بايثون التابع __repr__ وتعيد سلسلة نصية أكثر تفصيلاً يمكن استخدامها لإعادة إنشاء الكائن.

لماذا ومتى نستخدم __str__

يستخدم التابع __str__ في المقام الأول لإنشاء تمثيل للكائن يمكن قراءته بواسطة الإنسان. إنها طريقة رائعة لتوفير ملخص أو وصف بسيط للكائن يمكن للمستخدمين النهائيين فهمه بسهولة.

قد ترغب في استخدام __str__ عند طباعة الكائنات لأغراض التسجيل أو التصحيح، أو عندما ترغب في عرض رسالة سهلة للمستخدم. على سبيل المثال، إذا كنت تقوم بتطوير لعبة، فقد تستخدم __str__ لطباعة إحصائيات اللاعب بتنسيق قابل للقراءة.

إليك كيفية استخدام __str__ في اللعبة:

class Player:
    def __init__(self, name, level, health):
        self.name = name
        self.level = level
        self.health = health

    def __str__(self):
        return f'Player {self.name} is at level {self.level} with {self.health} health points.'

player = Player('Hero', 10, 100)

print(player)  # Player Hero is at level 10 with 100 health points.

في هذا المثال، يقوم التابع __str__ بإرجاع سلسلة توفر ملخصًا موجزًا ​​للحالة الحالية للاعب. وهذا يجعل من السهل على المستخدمين فهم حالة اللاعب في لمحة.

لماذا ومتى تستخدم __repr__

التابع __repr__ في بايثون هو تابع خاص تعيد سلسلة يمثل نسخة قابلة للطباعة من كائن. ولكن متى نستخدمه؟ حسنًا، يهدف التابع __repr__ إلى أن يتكون واضح وكامل. وهذا يعني أنه إذا كان لديك كائن، فيجب أن يحتوي التابع __repr__ الخاص بهذا الكائن على جميع المعلومات اللازمة لإعادة إنشاء الكائن إذا تم إرجاعها إلى المترجم.

يجعل هذا الأمر __repr__ مفيدًا بشكل لا يصدق في تصحيح الأخطاء وتسجيلها، حيث يمكنه توفير نظرة عامة أكثر تفصيلاً لكائن ما مقارنةً بـ __str__. إذا كنت تعمل مع هياكل بيانات معقدة، أو تحتاج إلى تمثيل كامل لكائنك لاستكشاف الأخطاء وإصلاحها، فإن __repr__ هو الحل.

ملاحظة: في حالة عدم وجود تابع __str__ معرف، سيستخدم ايثون افتراضيًا __repr__ عند استدعاء دالة print() على كائن.

أمثلة: استخدام التابع __str__

الآن بعد أن ناقشنا التابع __repr__، فلنغير الموضوع ونلقي نظرة على بعض الأمثلة حول كيفية استخدام التابع __str__ في بايثون. تذكر أن __str__ تهدف إلى إرجاع تمثيل نصي قابل للطباعة بشكل جيد لكائن، مما يجعلها رائعة لإخراج المستخدم النهائي.

دعنا نحدد فئة Person بسيطة باستخدام طريقة __str__:

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

    def __str__(self):
        return f'Person(name={self.name}, age={self.age})'

الآن، دعنا ننشئ مثيل Person ونطبعه:

p = Person('John', 28)
print(p)

الناتج:

Person(name=John, age=28)

كما ترى، تستدعي دالة print() طريقة __str__ وتطبع تمثيلًا نصيًا سهل الاستخدام لكائن بايثون. يمكن أن يكون هذا مفيدًا للغاية عندما تريد تقديم معلومات الكائن بتنسيق قابل للقراءة ونظيف.

أمثلة: استخدام طريقةالتابع __repr__

دعنا نتعمق في بعض الأمثلة لفهم استخدام repr في بايثون. لنفترض وجود فئة تسمى “Person” تحتوي على بعض السمات.

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

إذا قمنا بإنشاء مثيل لهذه الفئة وحاولنا طباعتها، فسنحصل على رسالة غير مفيدة.

p = Person('John Doe', 30)
print(p)

الناتج:

<__main__.Person object at 0x7f3f8e7e3d30>

وهنا يأتي دور repr. فلنقم بإلغاء التابع repr في فئتنا.

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

    def __repr__(self):
        return f'Person(name={self.name}, age={self.age})'

الآن، عندما نقوم بإنشاء مثيل للفصل وطباعته، نحصل على مخرجات أكثر معنى.

p = Person('John Doe', 30)
print(p)

الناتج:

Person(name=John Doe, age=30)

يجب أن يعيد التابع __repr__ سلسلة نصية تمثل تعبيرًا صالحًا في بايثون. ومن المفترض أن تكون واضحة وكاملة. وهذا يعني أنه إذا قمت بنسخ ناتجها وتشغيلها، فيجب أن تحصل على نفس الكائن الذي تمت طباعته.

__str__ و__repr__ هما توابع خاصة في بايثون تسمحان لنا بالتحكم في كيفية تحويل الكائنات إلى سلاسل. في حين أن __str__ مخصصة لإنشاء تمثيل سلسلة قابل للقراءة للمستخدمين النهائيين، فإن __repr__ مصممة لإنشاء تمثيل سلسلة لا لبس فيه للمطورين. إن فهم الفرق بين هاتين التايعين ومتى تستخدم كل منهما أمر بالغ الأهمية لكتابة كود بايثون نظيف وفعال.

سواء كنت تقوم بتصحيح الأخطاء أو عرض البيانات، فإن هذه التوابع السحرية يمكن أن تجعل حياتك أسهل كثيرًا. تذكر أنه من الأفضل دائمًا تنفيذ __repr__ لفئاتك، وتنفيذ __str__ إذا كنت تعتقد أنه من المفيد الحصول على إصدار سلسلة من الكائن سهل الاستخدام.


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading