Dunder Methods (เมธอดมหัศจรรย์)
Operator overloading: TypeScript ทำไม่ได้ แต่ Python ทำได้
หัวข้อที่มีชื่อว่า “Operator overloading: TypeScript ทำไม่ได้ แต่ Python ทำได้”TypeScript ไม่รองรับ operator overloading เลย ถ้าคุณสร้าง class Vector คุณต้องเรียกเมธอด .add(other) โดยตรง — การเขียน v1 + v2 ไม่มีทางใช้ได้กับ type ที่กำหนดเอง Python แก้ปัญหานี้ผ่าน dunder methods (ย่อมาจาก “double underscore”) ซึ่งเรียกอีกชื่อว่า magic methods เมธอดเหล่านี้คือเมธอดธรรมดาที่มีชื่ออย่าง __add__, __str__, และ __len__ ซึ่ง Python จะเรียกโดยอัตโนมัติเมื่อคุณใช้ operator หรือ built-in function กับ object ของคุณ
คำว่า “dunder” เป็นคำแสลงในชุมชน Python ที่ใช้เรียกชื่อที่ขึ้นต้นและลงท้ายด้วย underscore สองตัว คุณนิยามเมธอดเหล่านี้เอง และ Python จะเรียกใช้ให้เบื้องหลัง
นิยามการบวก Vector
หัวข้อที่มีชื่อว่า “นิยามการบวก Vector”ตัวอย่างที่อธิบายได้ชัดเจนที่สุดคือ vector 2 มิติ ใน TypeScript คุณต้องตั้งชื่อ operation อย่างชัดเจน ส่วนใน Python คุณเชื่อมโยงกับ + ได้โดยการนิยาม __add__
// TypeScript: no operator overloading — you must name the methodclass Vector { constructor(public x: number, public y: number) {}
toString(): string { return `Vector(${this.x}, ${this.y})`; }
add(other: Vector): Vector { return new Vector(this.x + other.x, this.y + other.y); }
equals(other: Vector): boolean { return this.x === other.x && this.y === other.y; }
get length(): number { return 2; }}
const v1 = new Vector(1, 2);const v2 = new Vector(3, 4);const v3 = v1.add(v2); // must call .add(), can't write v1 + v2console.log(v3.toString()); // "Vector(4, 6)"# Python: operator overloading via dunder methodsclass Vector: def __init__(self, x, y): self.x = x self.y = y
def __str__(self): return f"Vector({self.x}, {self.y})"
def __repr__(self): return f"Vector({self.x!r}, {self.y!r})"
def __len__(self): return 2
def __eq__(self, other): return self.x == other.x and self.y == other.y
def __add__(self, other): return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(1, 2)v2 = Vector(3, 4)v3 = v1 + v2 # calls v1.__add__(v2) automaticallyprint(str(v1)) # calls v1.__str__()print(len(v1)) # calls v1.__len__()print(v1 == Vector(1, 2)) # calls v1.__eq__(...)Python เรียก dunder ได้อย่างไร
หัวข้อที่มีชื่อว่า “Python เรียก dunder ได้อย่างไร”เวลา Python เจอ v1 + v2 เบื้องหลังจะเรียก type(v1).__add__(v1, v2) เรียก str(v1) ก็ไปที่ v1.__str__() และเรียก len(v1) ก็ไปที่ v1.__len__() พูดง่าย ๆ คือ built-in function และ operator แทบทุกตัวมี dunder hook คู่กันไว้ให้คุณเข้าไปกำหนดพฤติกรรมเอง
นอกจากนี้ยังมี __repr__ ซึ่งต่างจาก __str__ คือ str() ออกแบบมาสำหรับการแสดงผลที่มนุษย์อ่านได้ ส่วน repr() (และ REPL แบบ interactive) ใช้ __repr__ สำหรับ output ที่ชัดเจนและมุ่งเน้นนักพัฒนา แฟล็ก !r ใน f-string จะเรียก repr() กับค่านั้น
ลองทดสอบ
หัวข้อที่มีชื่อว่า “ลองทดสอบ”class Vector: def __init__(self, x, y): self.x = x self.y = y
def __str__(self): return f"Vector({self.x}, {self.y})"
def __repr__(self): return f"Vector({self.x!r}, {self.y!r})"
def __len__(self): return 2
def __eq__(self, other): return self.x == other.x and self.y == other.y
def __add__(self, other): return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(1, 2)v2 = Vector(3, 4)v3 = v1 + v2
print(str(v1))print(len(v1))print(v1 == Vector(1, 2))print(v3)Loading Python runtime (first run only)…