۱۲/۱۳/۱۳۸۸

برنامه نویسی شیء گرا - قسمت ششم > متودهای خاص


تا اینجا با متودهایی چون __init__ و __str__ آشنا شدید. این متودها معمولا مستقیم صدا زده نمیشوند و در مواقع خاصی عمل میکنند. مثلا __str__ هنگام پرینت کردن یک شیء صدا زده میشود. انواع دیگری از این متودهای خاص وجود دارد که در این پست یکی دیگر از آنها را معرفی میکنم.


> object.__repr__() or repr(object) or `object`

repr مخفف representation یا همان "نمایش" یک شیء است. برای این که بفهمیم هر شیء چه چیزی را نمایش میدهد کافیست نام آن را در Python Shell صدا بزنیم:

>>> a='I am string of a'
>>> a
'I am string of a'
>>> b=12.3
>>> b
12.300000000000001
>>> c=range(10)
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

هنگامی که یک شیء جدید تعریف میکنیم به حالت پیش فرض، هر نمونه از آن، نوع و مکان خود در حافظه را نمایش میدهد:
>>> class Point(object): pass

>>> p=Point()
>>> p                                               <__main__.Point object at 0x02012290>
>>> 

خروجی متود repr همواره رشته ایست از آنچه شیء نمایش میدهد:

>>> repr(p)
'<__main__.Point object at 0x02012290>'
>>> p.__repr__()
'<__main__.Point object at 0x02012290>'
>>>
>>> b=12.3
>>> repr(b)
'12.300000000000001'
>>> c=range(10)
>>> c.__repr__()
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> d=set([1,2,3,3])
>>> `d`
'set([1, 2, 3])'
>>>


خب، پس همانند متود __str__ خروجی این متود یک رشته است. در صورتی که متود __str__ برای یک شیء تعریف نشده باشد ولی __repr__ تعریف شده باشد، __repr__ به جای __str__ نیز صدا زده میشود (عکس این برقرار نیست!)

>>> class Point(object):
        def __init__(self,x,y):
       
    self.x=x
       
    self.y=y
   
    def __repr__(self):
       
    return str(self.x)+','+str(self.y)

   
>>> p=Point(2,3)
>>> print p
2,3
>>> str(p)
'2,3'
>>> repr(p)
'2,3'
>>> p
2,3
>>> 

همانطور که دیدید حالا که ما متود __repr__ برای Point را override کردیم (یعنی تعریف آنرا تغییر دادیم)، دیگر p ، نوع و مکان خود در حافظه را نمایش نمیدهد. ما تعیین کردیم که هر Point مختصات خود را نمایش دهد.
حالا متود __str__ را هم برای Point تعریف میکنیم و __repr__ را هم کمی تغییر میدهیم:

>>> class Point(object):
        def __init__(self,x,y):
       
    self.x=x
       
    self.y=y
       
   
    def __str__(self):
       
    return str(self.x)+','+str(self.y)
   
    def __repr__(self):
       
    return 'Point(x=%d,y=%d)'\
                   %(self.x,self.y)

   
>>> p=Point(2,3)
>>> print p
2,3
>>> str(p)
'2,3'
>>> p
Point(x=2,y=3)
>>> repr(p)
'Point(x=2,y=3)'
>>>

حالا که ما __str__ را هم override کرده ایم، دیگر متود repr به جای آن صدا زده نمیشود، در ضمن ما تعیین کردیم که هر Point ، نوع و مختصات خود را نمایش دهد. به این ترتیب هر Point نمایشی ساده و قابل فهم دارد.
علاوه بر قابل فهم تر کردن نمایش یک شیء، یکی دیگر از فواید متود repr، قابلیت شناخته شدن یک شیء برای استفاده در متود eval است.

با استفاده از متود eval میتوان یک دستور قابل اجرا که در قالب یک رشته نوشته شده را اجرا کرد:

>>> eval('abs(-1)')
1
>>> a=eval('range(10)')
>>> a==range(10)
True
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> eval('1+1')
2

ورودی متود eval همانند خروجی متود repr یک رشته است.
اشیاء از پیش تعریف شده در پایتون مثل اعداد، رشته ها، لیست ها و ... طوری نمایش داده میشوند که با استفاده از متود eval میتوان آنها را دوباره تولید کرد (کپی کرد):

>>> a=2
>>> b=eval(repr(a))
>>> b
2
>>> a==b
True
>>> repr(a)
'2'
>>> lst=range(10)
>>> repr(lst)
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> lst_copy=eval(repr(lst))
>>> lst_copy
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> p=Point(2,3)
>>> p
Point(x=2,y=3)
>>> p2=eval(repr(p))
>>> p2
Point(x=2,y=3)
>>> p2.x
2
>>> p2.y
3
>>> 

همانطور که دیدید من نیز متود __repr__ را به گونه ای override کرده ام که در صورت evaluate کردن نمایش یک Point، یک نمونه با همان مشخصات تولید شود.

با استفاده از متود repr میتوان هر شیء را به یک رشته تبدیل کرد. میتوان از این رشته ها در انواع تست ها، کپی کردن، ذخیره سازی در پایگاههای داده و ... بهره جست.
برای انواع خاصی از اشیاء همچون اعداد صحیح، لیست ها و ...، خروجی این متود همان خروجی متود str است. 

>>> str(1.0)==repr(1.0)
True
>>> str(3.2)==repr(3.2)
False
>>> print str(3.2),repr(3.2)
3.2 3.2000000000000002
>>> str(range(10))==repr(range(10))
True
>>> 
>>> print str('Good \n Luck')
Good
 Luck
>>> print repr('Good \n Luck')
'Good \n Luck'


برای اطلاعات بیشتر در باره ی مطالب این پست به فارسی به اینجا مراجعه کنید.
لیست کاملی از اسامی خاص در پایتون، اینجا موجود است. 

موفق باشید ☺☻
 

۵ نظر:

  1. سلام!
    بالخره فرصت کردم که تو نت یه چرخی بزنم.
    عرضم به حضورت که گویا زبون پایتون پر سرعت ترین زبانه. با اینکه شی گراست.
    تحریک شدم که تو یه فرصت مناسب برم سراغش.
    در ضمن. سعی کن بیشتر وارد جزئیات بشی تا کسی که صفر کیلومتره، و حتی برنامه نویسی نمی دونه بفهمه.. شاید بشه از این آموزش هات یه کتاب یا یع جزوه در اورد، من کمکت می کنم اگه بخوای

    پاسخحذف
  2. مرسی بابت پیشنهادات، فک کنم اگه بیشتر وارد جزییات بشم اتفاقا برای کسی که صفر کیلومتره خسته کننده شن مطالب! :دی، سعی میکنم کاملتر توضیح بدم.
    درباره ی کتاب! خوب بنظرم کسی که بخواد برنامه نویسی یاد بگیره بهتره در درجه ی اول از منابع انگلیسی استفاده کنه یا اگه فارسی حداقل مطالبو به روز یاد بگیره. من اینجا فقط چیزایی که خودم یاد میگیرمو میزارم بقیم استفاده کنن. فعلا قصد پول درآوردن از این آموزشارو ندارم :دی

    پاسخحذف
  3. منم نمی گم پول در بیار!
    میگم سعی کن که یه چیز موندگار بشه. (نسبتا!)

    پاسخحذف