operator overloading
ตัวดำเนินการ(operator) ทำงานกับ built-in class แต่ทำงานแตกต่างกันตามชนิดของข้อมูล ตัวอย่างเช่น ตัวดำเนินการ “+” จะดำเนินการเพื่อบวกจำนวน 2 จำนวน หรือ อาจจะใช้เพื่อทำการเชื่อมข้อความ 2 ข้อความก็ได้ คุณลักษณะเช่นนี้ ซึ่งอนุญาติให้ตัวดำเนินการสามารถทำงานแตกต่างกันตามบริบทของข้อมูล จะเรียกว่า operator overloadding
/** * Insert your code here */
ผลที่ได้
Traceback (most recent call last): ... TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
จากตัวอย่าง หากเราใช้ operator overloadding กับคลาสที่เราทำการสร้างขึ้นมาเอง จะเกิดปัญหาดังตัวอย่าง แต่ในไพธอนนั้น เราสามารถจะกำหนดรายละเอียดเพื่อให้ไพธอนรู้ถึงวิธีการจัดการกับข้อมูลดังกล่าวได้
special function
ฟังก์ชันของคลาสที่เริ่มต้นด้วย “__” นั้นจะถูกเรียกว่า special function เช่น ฟังก์ชัน __init__ ซึ่งจะถูกเรียกขึ้นถูกครั้งที่มีการสร้างออบเจ็คใหม่จากคลาสนั้นๆ การกำหนด special function นี้ จะทำให้คลาสที่เราทำการสร้างขึ้นมาใหม่นั้น compatible กับ built-in class
ตัวอย่างการใช้งาน
p1 = Point(2, 3) print( p1 )
ผลที่ได้
<__main__.Point object at 0x00000000031F8CC0>
ซึ้งข้อมูลที่ปรินท์ออกมาได้นั้นยังไม่ค่อยสื่อความหมายมากนัก แต่หากเราทำการกำหนดรายละเอียดลงไปในฟังก์ชัน __str__() ของคลาสที่เราสร้างขึ้น เราสามารถจะปรินท์ค่าที่สื่อความหมายได้มากขึ้น
ตัวอย่างการใช้งาน
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
p1 = Point(1, 5)
print( p1 )
ผลที่ได้
(1, 5)
จากตัวอย่าง เมื่อเราทำการกำหนดรายละเอียดให้กับฟังก์ชัน __str__ แล้วเมื่อทำการพิมพ์ค่าออกมา ค่าดังกล่าว สื่อความหมายถึงข้อมูลมากขึ้น
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
p1 = Point(5, -2)
print( str(p1) )
print( format(p1) )
ผลที่ได้
(5, -2) (5, -2)
เมื่อเราใช้คำสั่ง str( p1 ) หรือ format( p1 ) ไพธอนเองจะเรียกใช้ฟังก์ชัน p1.__str__() ภายในอัตโนมัติ
การ overloading กับตัวดำเนินการ “+”
หากต้องการจะทำการ overload จากตัวดำเนินการ “+” เราต้องทำการ implement ฟังก์ชัน __add__() ในคลาสที่เราทำการสร้างขึ้นมาใหม่ เราสามารถกำหนดเราละเอียดอย่างไรก็ได้ภายในฟังก์ชัน แต่เมื่อต้องทำการคืนค่าออกมาต้องคืนค่าออกมาในรูปแบบของออบเจ็ค Point ซึ่งเป็นผลรวมของข้อมูลทั้งสองที่ส่งเข้าไปดำเนินการ
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
point1 = Point(5, -2)
point2 = Point(3, 7)
result = point1 + point2
print( result )
ผลที่ได้
(2, 5)
จากตัวอย่าง เมื่อเราทำการคำนวณผลรวมของข้อมูล point1+point2 ไพธอนจะเรียกฟังก์ชัน point1.__add__(point2) ซึ่งก็เทียบเท่า Point.__add__(point1, point2) ในทำนองเดียวกัน เราสามารถที่จะทำการ overload เครื่องหมายดำเนินการอื่นๆ ได้อีกและ special function ที่เราจำเป็นต้องระบุรายละเอียดสำหรับตัวดำเนินการนั้นๆ ดังรายละเอียดในตารางด้านล่าง
| Operator | Expression | Internally |
|---|---|---|
| Addition | p1 + p2 | p1.__add__(p2) |
| Subtraction | p1 – p2 | p1.__sub__(p2) |
| Multiplication | p1 * p2 | p1.__mul__(p2) |
| Power | p1 ** p2 | p1.__pow__(p2) |
| Division | p1 / p2 | p1.__truediv__(p2) |
| Floor Division | p1 // p2 | p1.__floordiv__(p2) |
| Remainder (modulo) | p1 % p2 | p1.__mod__(p2) |
| Bitwise left shift | p1 << p2 | p1.__lshift__(p2) |
| Bitwise right shift | p1 >> p2 | p1.__rshift__(p2) |
| Bitwise AND | p1 & p2 | p1.__and__(p2) |
| Bitwise OR | p1 | p2 | p1.__or__(p2) |
| Bitwise XOR | p1 ^ p2 | p1.__xor__(p2) |
| Bitwise NOT | ~p1 | p1.__invert__() |
Overloading comparison operator
ไพธอนไม่ได้จำกัด operator overloading เฉพาะการดำเนินการทางคณิตศาสาตร์ เราสามารถจะ overload สำหรับตัวดำเนินการเปรียบเทียบได้เช่นกัน โดยหากเราต้องการจะทำงานกับเครื่องหมาย < ในคลาส Point โดยจะทำการเปรียบเทียบ magnitude ของ Point เหล่านี้กับจุดเริ่มต้น และคืนค่าเป็นผลจากคำนวณดังกล่าว
ตัวอย่างการใช้งาน
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
def __lt__(self, other):
self_mag = (self.x ** 2) + (self.y ** 2)
other_mag = (other.x ** 2) + (other.y ** 2)
return self_mag < other_mag
print( Point(1, 1) < Point(-2, -3) )
# True
print( Point(1,1) < Point(0.5,-0.2) )
#False
print( Point(1,1) < Point(1,1) )
#False
สำหรับ special function ที่เราต้องการ implement เพื่อจะ overload การดำเนินการเปรียบเทียบ ตามรายละเอียดตารางด้านล่าง
| Operator | Expression | Internally |
|---|---|---|
| Less than | p1 < p2 | p1.__lt__(p2) |
| Less than or equal to | p1 <= p2 | p1.__le__(p2) |
| Equal to | p1 == p2 | p1.__eq__(p2) |
| Not equal to | p1 != p2 | p1.__ne__(p2) |
| Greater than | p1 > p2 | p1.__gt__(p2) |
| Greater than or equal to | p1 >= p2 | p1.__ge__(p2) |