سربارگذاری عملگرها در پایتون — به زبان ساده
میتوان معنای یک «عملگر» (Operator) را در «زبان برنامهنویسی پایتون» (Python Programming Language) بسته به «عملوندهایی» (Operands) که استفاده کرده است تغییر داد. این کار با عنوان «سربارگذاری عملگرها» (Operating Overloading) نامیده میشود. در این مطلب، به مبحث سربارگذاری عملگرها در پایتون پرداخته شده و مثالهایی برای درک بهتر مطلب بیان شده است.
سربارگذاری عملگرها در پایتون
عملگرهای پایتون برای «کلاسهای توکار» (Built-in Classes) کار میکنند. اما، عملگرها در برخورد با انواع مختلف دادهها، رفتارهای گوناگونی از خود بروز میدهند. برای مثال، عملگر «+»، جمع حسابی را روی دو عدد انجام میدهد، دو لیست را ادغام و یا، دو رشته را الحاق میکند.
این ویژگی در پایتون، که به عملگرها این امکان را میدهد که در زمینههای گوناگون معناهای مختلفی داشته باشند، «سربارگذاری عملگرها» (Operating Overloading) نامیده میشود. با این حساب، هنگامی که از آنها با اشیایی از کلاسهای تعریف شده توسط کاربر استفاده میشود، چه اتفاقی میافتد؟ فرض میشود که کلاسهای زیر، در تلاش برای شبیهسازی یک نقطه در دستگاه مختصات دوبُعدی هستند.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y
و اما، همانطور که مشهود است خطاهایی نمایش داده شدند. TypeError هنگامی نمایش داده میشود که پایتون نمیداند چگونه دو شی Point را به یکدیگر اضافه کند. خبر خوب آنکه میتوان با استفاده از سربارگذاری عملگرها، این کار را به پایتون یاد داد. اما، در ابتدا نیاز به بررسی «توابع خاص» (Special Functions) در پایتون است.
توابع خاص در پایتون
توابع کلاسی که با دو «زیرخط» (Underscore) آغاز میشوند، توابع خاص در پایتون هستند. دلیل این امر آن است که این توابع عادی نیستند. تابع ()__init__ که در بالا تعریف شده است، یکی از آنها محسوب میشود. این تابع هر بار که یک شی جدید از آن کلاس ساخته میشود، فراخوانی خواهد شد. تعداد زیادی تابع خاص در پایتون وجود دارد.
با استفاده از توابع خاص، میتوان کلاس را با توابع توکار سازگار کرد.
>>> p1 = Point(2,3) >>> print(p1) <__main__.Point object at 0x00000000031F8CC0>
خروجی به خوبی پرینت نشده است. اما اگر متد ()__str__ در کلاس تعریف شود، میتوان چگونه پرینت شدن آن را کنترل کرد. بنابراین، در ادامه، این مورد نیز به کلاس اضافه میشود.
1class Point:
2 def __init__(self, x = 0, y = 0):
3 self.x = x
4 self.y = y
5
6 def __str__(self):
7 return "({0},{1})".format(self.x,self.y)
اکنون، تابع ()print مجددا آزموده میشود.
>>> p1 = Point(2,3) >>> print(p1) (2,3)
اکنون بهتر شد. معلوم میشود که متد مشابهی هنگام استفاده از توابع توکار ()str یا ()format فراخوانی شده است.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
بنابراین، هنگامی که از (str(p1 یا (format(p1 استفاده میشود، پایتون به طور داخلی ()__p1.__str را انجام میدهد. از همین رو، نام آنها توابع خاص است. اکنون، میتوان به بحث سربارگذاری عملگرها بازگشت.
سربارگذاری عملگرها در پایتون: عملگر +
برای سربارگذاری عملگر +، نیاز به پیادهسازی تابع ()__add__ در کلاس است. قدرت زیاد، مسئولیت زیادی را نیز به همراه دارد. اکنون، کاربر میتواند هر کاری که میخواهد درون این تابع انجام بدهد.
اما، اکنون حساستر است به اینکه یک شی Point از مجموع مختصات را بازگرداند.
1class Point:
2 def __init__(self, x = 0, y = 0):
3 self.x = x
4 self.y = y
5
6 def __str__(self):
7 return "({0},{1})".format(self.x,self.y)
8
9 def __add__(self,other):
10 x = self.x + other.x
11 y = self.y + other.y
12 return Point(x,y)
اکنون، مجددا جمع آزموده میشود.
>>> p1 = Point(2,3) >>> p2 = Point(-1,2) >>> print(p1 + p2) (1,5)
چیزی که در واقع به وقوع میپیوندد آن است که هنگام انجام p1 + p2، پایتون (p1.__add__(p2 را فراخوانی میکند که به نوبه خود (Point.__add__(p1,p2 است. به طور مشابه، میتوان دیگر عملگرها را نیز سربارگذاری کرد. تابع خاصی که برای پیادهسازی مورد نیاز است، در زیر نمایش داده شده است.
سربارگذاری عملگر مقایسه در پایتون
پایتون، سربارگذاری عملگرها را صرفا محدود به عملگرهای حسابی نمیکند. میتوان «عملگر مقایسه» (Comparison Operators) را نیز به همین صورت سربارگذاری کرد. فرض میشود که هدف پیادهسازی علامت «کوچکتر» در کلاس Point است. بزرگی این pointها از origin مقایسه میشود و سپس، نتایج آن بازگردانده میشود.
این مورد را میتوان به صورت زیر نیز پیادهسازی کرد.
1class Point:
2 def __init__(self, x = 0, y = 0):
3 self.x = x
4 self.y = y
5
6 def __str__(self):
7 return "({0},{1})".format(self.x,self.y)
8
9 def __lt__(self,other):
10 self_mag = (self.x ** 2) + (self.y ** 2)
11 other_mag = (other.x ** 2) + (other.y ** 2)
12 return self_mag < other_mag
اجرای این نمونهها در پایتون به صورت زیر خواهد بود.
>>> Point(1,1) < Point(-2,-3) True >>> Point(1,1) < Point(0.5,-0.2) False >>> Point(1,1) < Point(1,1) False
به طور مشابه، توابع خاصی که نیاز به پیادهسازی آنها برای سربارگذاری دیگر عملگرهای مقایسه است، در زیر بیان شدهاند.
ماشالله خانم حصارکی عجب فعال هستین