ในบทช่วยสอนนี้ เราจะเรียนรู้เกี่ยวกับ ตัวแปรส่วนตัว (private variables) ใน คลาส (classes) ของ Python
Python ไม่มีแนวคิด Private Variables โดยตรง
Python ไม่มีกลไกการเข้าถึงแบบ private จริงๆ เช่นภาษา Java หรือ C++ แต่ผู้พัฒนาส่วนใหญ่ปฏิบัติตาม ข้อตกลงการตั้งชื่อ (naming convention) เพื่อบ่งชี้ว่า ตัวแปรนั้นไม่ควรเข้าถึงจากภายนอกโดยตรง
ข้อตกลงการตั้งชื่อด้วย Double Underscore
การขึ้นต้นชื่อตัวแปรด้วย underscore สองตัว (__) จะบอกให้เข้าใจว่าเป็นตัวแปร "ส่วนตัว" (แต่ไม่ได้ห้ามเข้าถึงจริงๆ) ตัวอย่างเช่น __name, __balance เป็นต้น
ตัวอย่าง: การสร้างและเข้าถึงตัวแปรแบบ "ส่วนตัว"
class Sample:
def __init__(self, nv, pv):
# ตัวแปรทั่วไป (public)
self.nv = nv
# ตัวแปร "ส่วนตัว" (name mangling จะเปลี่ยนชื่อ)
self.__pv = pv
# สร้างอินสแตนซ์
sample = Sample('Normal variable', 'Private variable')
# เข้าถึงตัวแปรทั่วไป - ทำงานปกติ
print(sample.nv) # Normal variable
# พยายามเข้าถึง __pv โดยตรง - จะเกิด AttributeError
print(sample.__pv) # AttributeError: 'Sample' object has no attribute '__pv'
ทำไมถึงเกิด AttributeError?
Python ทำการ Name Mangling (การเปลี่ยนชื่อ) ให้กับตัวแปรที่ขึ้นต้นด้วย __ โดยเปลี่ยนชื่อเป็นรูปแบบ _ClassName__variableName ดังนั้น __pv ในคลาส Sample จะกลายเป็น _Sample__pv
วิธีเข้าถึงตัวแปรที่ถูก Name Mangling
# เข้าถึงผ่านชื่อที่ถูก mangle แล้ว
print(sample._Sample__pv) # Private variable
Name Mangling ยังใช้กับเมธอดได้เช่นกัน
class Sample:
def __init__(self, a):
self.a = a
# เมธอด "ส่วนตัว"
def __get_a(self):
return self.a
sample = Sample(5)
# เรียกผ่านชื่อที่ mangle แล้ว - ทำงานได้
print(sample._Sample__get_a()) # 5
# เรียกโดยตรง - จะ error
print(sample.__get_a()) # AttributeError
สรุป
จุดประสงค์ของ __ (double underscore) ไม่ใช่เพื่อป้องกันการเข้าถึง แต่เป็นสัญญาณบอกว่า ตัวแปร/เมธอดนี้ ตั้งใจจะใช้ภายในคลาสเท่านั้น การเข้าถึงจากภายนอกยังทำได้ แต่ควรหลีกเลี่ยงเพื่อรักษา encapsulation และลดการพึ่งพารายละเอียดภายใน (implementation details)
หากมีข้อสงสัยเกี่ยวกับบทช่วยสอนนี้ สามารถถามได้ในส่วนความคิดเห็นครับ