تکه کد زیر رو در نظر بگیرید :
lst = [1, 2, 3]
print(lst.__len__()) # 3
print(len(lst)) # 3
هردو جواب یکسان میدن، آیا تفاوتی دارند ؟ آیا میشه همیشه از مجیک متد های متناظر استفاده کرد؟ امروز میخوایم 4 تا از تفاوت ها رو بررسی کنیم.

1- اولین مورد که نظر خیلی ها هم هست readability هست! فرض کنید به جای تمام built-in فانکشن هایی که پایتون داره :
str(), bool(), len(), repr(), hash(), ...
ما معادل magic method اون رو استفاده کنیم:

__str__(), __bool__(), __len__(), __repr__(), __hash__(), ...

یه صفحه از کدمون میشه پر از underscore که هم زشته هم ناخوانا مخصوصا اگه ترکیب هم بشن باهم...

2- مورد مهم بعدی:
class C:
def __len__(self):
return 'salam'

obj = C()
print(obj.__len__()) # Fine
print(len(obj)) # Error

پایتون سر دومین print ارور داد ! البته که باید هم میداد، دلیلش منطقی هست وقتی ما طول یه آبجکتی رو میخوایم انتظار "عدد" داریم نمیشه طول آبجکت ما "سلام" باشه ولی توی اولی کامل ignore شده.
* وقتی متد شما توسط پایتون کال بشه، پایتون یه checking هم انجام میده !
یه بار دیگه با دیگه با str ببینیم این رو :
class C:
def __str__(self):
return 10

obj = C()
print(obj.__str__()) # Fine
print(str(obj)) # Error


3- مورد بعدی توی comparison operator ها (نه arithmetic operator ها مثل ضرب و ...):
class C:
def __lt__(self, other):
print('called')

class D:
pass

obj1 = C()
obj2 = D()

obj2 > obj1
obj2.__gt__(obj2)

دو نمونه داریم به اسم obj1 و obj2 ، از طرفی میدونیم magic method عه متناظر با علامت < متد عه __gt__ هست. ما برای هیچکدوم از کلاس ها __gt__ رو پیاده سازی نکردیم ولی:
پایتون توی مورد اول میاد میگه ، من نمتونم تشخیص بدم که obj2 بزرگ تر از obj1 هست یا نه ، بذار ببینم میتونم جور دیگه نگاه کنم و تشخیص بدم که obj1 کوچیک تر از obj2 هست ؟ بله میتونم! چون obj1 متد __lt__ رو پیاده سازی کرده پس اون رو کال میکنه.
ولی توی مورد دوم همچین خبری نیست.


4- مورد آخر که کم اهمیت هست ولی جالب بود بگیم ، توی دیتا تایپ های built-in پایتون ، سرعت built-in فانکشن ها سریع تر هست :
from timeit import timeit

print(timeit("len('salam')", number=10000000))
print(timeit("'salam'.__len__()", number=10000000))

# 0.4709385
# 0.6157927000000001

دلیلش هم اینکه فانکشن len با C نوشته شده ، با توجه به تایپی که بهش میدیم، مسیرش رو برای پیدا کردن انتخاب میکنه. ولی توی پایینی پایتون دنبال متد __len__ توی namespace عه اون نمونه میگرده. (توی 10 میلیون بار اجرا 0.2 ثانیه تفاوت یعنی هیچی).

Comments

Be the first to add a comment