ความรู้เบื้องต้นเกี่ยวกับคลาสใน Python และการเขียนโปรแกรมเชิงวัตถุ [คำอธิบายสำหรับมือใหม่]
หากต้องการเรียกใช้ Python ผ่าน Command Prompt หรือ PowerShell บนคอมพิวเตอร์ของคุณ คุณจำเป็นต้องดาวน์โหลดและติดตั้ง Python ก่อน
หากคุณยังไม่ได้ติดตั้ง กรุณาดูบทความ การติดตั้ง Python และการตั้งค่าสภาพแวดล้อมการพัฒนา เพื่อทำการติดตั้ง Python
สวัสดีทุกท่านที่เพิ่งก้าวเข้ามาในโลกของการพัฒนาเว็บ! ในครั้งนี้ เราจะมาอธิบายแนวคิดที่สำคัญที่ใช้ในภาษาโปรแกรมส่วนใหญ่ นั่นคือ "การเขียนโปรแกรมเชิงวัตถุ (OOP)" และหัวใจหลักของมันใน Python อย่าง "คลาส" ให้เข้าใจง่ายกว่าที่ไหนๆ ไม่ต้องกลัวศัพท์เทคนิคครับ เมื่ออ่านบทความนี้จบ คุณจะร้อง "อ๋อ เข้าใจแล้ว!" อย่างแน่นอน
เป้าหมายหลักของบทความนี้คือการให้ทุกคนได้สัมผัสกับ "ความสนุกที่ได้เห็นโค้ดทำงาน" ครับ ทิ้งทฤษฎียากๆ ไว้ก่อน แล้วมาลองคัดลอกและวางโค้ดที่ใช้งานได้จริง เพื่อสัมผัสถึงความสะดวกสบายของการเขียนโปรแกรมเชิงวัตถุไปพร้อมกัน!
การเขียนโปรแกรมเชิงวัตถุคืออะไรกันแน่?
เมื่อได้ยินคำว่า "การเขียนโปรแกรมเชิงวัตถุ" อาจจะฟังดูยากใช่ไหมครับ? แต่จริงๆ แล้วมันคือแนวคิดที่อยู่รอบตัวเราในชีวิตประจำวันเลยทีเดียว
ตัวอย่างที่มักถูกหยิบยกมาเปรียบเทียบมากที่สุดคือ "แม่พิมพ์ขนม" กับ "ขนม" ครับ
- คลาส (Class): คือ "แม่พิมพ์ขนม" ครับ เป็นเหมือนพิมพ์เขียวที่กำหนดว่าจะมีรูปร่างหน้าตาอย่างไร และจะใส่วัตถุดิบอะไรบ้าง (เช่น ไส้ถั่วแดง, ครีม)
- อ็อบเจกต์ (Object): คือ "ขนม" แต่ละชิ้นที่ถูกสร้างขึ้นมาจาก "แม่พิมพ์" ถึงแม้จะทำมาจากพิมพ์เดียวกัน แต่ไส้ข้างในอาจจะต่างกัน หรือมีรอยไหม้เล็กน้อย ซึ่งแต่ละชิ้นก็จะมีเอกลักษณ์เป็นของตัวเอง
ในโลกของการเขียนโปรแกรม หากเราสร้าง "พิมพ์เขียว" (คลาส) นี้ขึ้นมาครั้งหนึ่งแล้ว เราก็จะสามารถสร้าง "สิ่งของ" (อ็อบเจกต์) ที่เป็นรูปธรรมจากมันได้อย่างมีประสิทธิภาพและในปริมาณมาก นี่คือแนวคิดพื้นฐานของการเขียนโปรแกรมเชิงวัตถุครับ ถ้าเปรียบกับเว็บไซต์ การจัดการองค์ประกอบต่างๆ เช่น "ผู้ใช้", "บทความบล็อก", หรือ "สินค้า" ให้เป็นอ็อบเจกต์แต่ละชิ้น จะช่วยให้ระบบที่ซับซ้อนดูเป็นระเบียบและจัดการได้ง่ายขึ้น
พื้นฐานคลาสใน Python: มาสร้างพิมพ์เขียวกันเถอะ
เอาล่ะครับ เรามาเริ่มสร้าง "พิมพ์เขียว" หรือคลาสใน Python กันเลยดีกว่า โดยในที่นี้เราจะใช้ธีมเกี่ยวกับสุนัข (Dog) ในการดำเนินเรื่องครับ
1. คลาสที่เรียบง่ายที่สุด
ก่อนอื่น มาลองกำหนดคลาสที่ข้างในยังว่างเปล่ากันก่อน แค่นี้ก็ถือว่าเป็น "พิมพ์เขียว" ที่สมบูรณ์แล้วครับ
# กำหนดคลาส (พิมพ์เขียว) ที่ชื่อว่า Dog
class Dog:
pass # pass หมายถึง "ไม่ต้องทำอะไร" ใช้เมื่อจำเป็นต้องมีคำสั่งตามไวยากรณ์ แต่ยังไม่มีโค้ดที่จะเขียน
# สร้างอ็อบเจกต์ (instance) สุนัขที่เป็นรูปธรรมจากคลาส Dog
my_dog = Dog()
# ลองแสดงผลดูว่า my_dog คืออะไร
print(my_dog)
ผลการรัน:
<__main__.Dog object at 0x10e28a2d0>
เมื่อดูผลลัพธ์ จะเห็นว่าอ็อบเจกต์ของคลาส `Dog` ได้ถูกสร้างขึ้นมาแล้ว (ส่วนที่เป็น `0x...` จะแตกต่างกันไปในแต่ละสภาพแวดล้อมการรัน)
2. การกำหนดคุณลักษณะเฉพาะด้วยเมธอด `__init__`
ต่อไป เราจะมาทำให้สุนัขของเรามีข้อมูลเฉพาะตัว (เรียกว่า property หรือ attribute) เช่น "ชื่อ" และ "สายพันธุ์" กันครับ เหมือนกับการใส่ไส้ให้กับขนมนั่นเอง สิ่งที่เราจะใช้คือเมธอดพิเศษที่ชื่อว่า `__init__` (เป็นฟังก์ชันที่อยู่ในคลาส) ซึ่งเป็นเมธอดสำหรับตั้งค่าเริ่มต้นที่จะถูกเรียกใช้งานโดยอัตโนมัติทันทีที่อ็อบเจกต์ถูกสร้างขึ้น
class Dog:
# เมธอดสำหรับตั้งค่าเริ่มต้น ที่จะถูกเรียกอัตโนมัติเมื่อสร้างอ็อบเจกต์
def __init__(self, name, breed):
# บันทึกข้อมูลลงในอ็อบเจกต์ในรูปแบบ self.ชื่อตัวแปร
self.name = name
self.breed = breed
print(f"{self.name} ({self.breed}) เกิดแล้ว!")
# สร้างอ็อบเจกต์สุนัขพันธุ์ "ชิบะอินุ" ชื่อ "โปจิ"
dog1 = Dog("โปจิ", "ชิบะอินุ")
# สร้างอ็อบเจกต์สุนัขพันธุ์ "อาคิตะ" ชื่อ "ฮาจิ"
dog2 = Dog("ฮาจิ", "อาคิตะ")
# ลองแสดงชื่อและสายพันธุ์ของแต่ละตัว
print(f"ชื่อสุนัขตัวที่ 1: {dog1.name}")
print(f"สายพันธุ์สุนัขตัวที่ 1: {dog1.breed}")
print(f"ชื่อสุนัขตัวที่ 2: {dog2.name}")
print(f"สายพันธุ์สุนัขตัวที่ 2: {dog2.breed}")
พารามิเตอร์ตัวแรกของ `__init__` คือ `self` ซึ่งเป็นคีย์เวิร์ดพิเศษที่อ้างถึงตัวอ็อบเจกต์ที่กำลังจะถูกสร้างขึ้นมาเอง ให้คิดซะว่ามันเป็นเหมือนคาถาครับ การเขียน `self.name = name` ก็คือการผูกข้อมูลเข้ากับอ็อบเจกต์ในความหมายว่า "ชื่อของอ็อบเจกต์นี้คือ..." นั่นเอง
ผลการรัน:
โปจิ (ชิบะอินุ) เกิดแล้ว!
ฮาจิ (อาคิตะ) เกิดแล้ว!
ชื่อสุนัขตัวที่ 1: โปจิ
สายพันธุ์สุนัขตัวที่ 1: ชิบะอินุ
ชื่อสุนัขตัวที่ 2: ฮาจิ
สายพันธุ์สุนัขตัวที่ 2: อาคิตะ
เพียงแค่เรียกใช้คลาสแบบ `Dog("โปจิ", "ชิบะอินุ")` เมธอด `__init__` ก็จะถูกรัน และสร้างอ็อบเจกต์ที่มีข้อมูลของตัวเองขึ้นมา เราสามารถเข้าถึงข้อมูลของอ็อบเจกต์นั้นๆ ได้โดยใช้ `.` (จุด) เชื่อม เช่น `dog1.name`
3. การกำหนดพฤติกรรมด้วยเมธอด
อ็อบเจกต์ไม่ได้มีแค่ข้อมูล (attribute) เท่านั้น แต่ยังสามารถมี "พฤติกรรม" (method) ได้อีกด้วย สำหรับสุนัขแล้ว เรามาลองเพิ่มพฤติกรรมการ "เห่า" กันดีกว่าครับ
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
# เพิ่มพฤติกรรม (เมธอด) การเห่าของสุนัข
def bark(self):
return f"{self.name}: โฮ่งๆ!"
# สร้างอ็อบเจกต์
my_dog = Dog("โคโระ", "พันธุ์ผสม")
# เรียกใช้เมธอด bark
greeting = my_dog.bark()
print(greeting)
เพียงแค่กำหนดฟังก์ชันด้วย `def` ภายในคลาสเท่านั้นเองครับ ในตอนนี้ก็อย่าลืมใส่ `self` เป็นพารามิเตอร์ตัวแรกเสมอ เราสามารถเข้าถึงชื่อของอ็อบเจกต์นั้นๆ (`self.name`) ผ่าน `self` ได้ครับ
ผลการรัน:
โคโระ: โฮ่งๆ!
ขั้นสูง: การนำพิมพ์เขียวกลับมาใช้ใหม่ด้วย "การสืบทอด"
ตรงนี้แหละครับคือจุดที่การเขียนโปรแกรมเชิงวัตถุทรงพลังอย่างแท้จริง ด้วยกลไกที่เรียกว่า "การสืบทอด" (Inheritance) เราสามารถสร้างคลาสใหม่โดยการเพิ่มหรือเปลี่ยนแปลงฟังก์ชันจากคลาสที่มีอยู่เดิม (พิมพ์เขียว) ได้อย่างง่ายดาย
ตัวอย่างเช่น เราจะสร้างคลาส "สุนัขนำทาง (GuideDog)" ขึ้นมาใหม่โดยใช้คลาส `Dog` ที่เราสร้างไว้ก่อนหน้านี้เป็นพื้นฐาน สุนัขนำทางก็คือสุนัขประเภทหนึ่ง ดังนั้นจึงมี "ชื่อ" และ "สายพันธุ์" และมีความสามารถพื้นฐานในการ "เห่า" เหมือนกัน แต่สิ่งที่เพิ่มเข้ามาคืองานพิเศษ (เมธอด) ในการ "ช่วยเหลือผู้คน"
# คลาสแม่ (superclass) ที่เป็นต้นแบบ
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
print(f"สุนัขชื่อ {self.name} เกิดแล้ว เป็นพันธุ์ {self.breed}")
def bark(self):
return f"{self.name}: โฮ่ง!"
# สร้างคลาสลูก (subclass) ใหม่โดยสืบทอดจากคลาส Dog
class GuideDog(Dog): # ใส่ชื่อคลาสแม่ไว้ในวงเล็บ
def assist(self):
return f"{self.name} กำลังนำทางผู้คนอย่างปลอดภัย"
# สร้างอ็อบเจกต์สุนัขนำทาง
g_dog = GuideDog("แอล", "ลาบราดอร์ รีทรีฟเวอร์")
# สามารถใช้เมธอดของคลาสแม่ (Dog) ได้ด้วย
print(g_dog.bark())
# เมธอดเฉพาะที่เพิ่มเข้ามาในคลาสลูก (GuideDog)
print(g_dog.assist())
เพียงแค่ใส่ชื่อคลาสที่ต้องการใช้เป็นต้นแบบไว้ในวงเล็บหลังชื่อคลาสใหม่ เช่น `class GuideDog(Dog):` การสืบทอดก็เสร็จสมบูรณ์แล้วครับ แค่นี้ `GuideDog` ก็จะได้รับคุณสมบัติ (attribute) ทั้งหมดของ `Dog` (เช่น `name`, `breed`) และเมธอด (`bark`) มาใช้งาน ทำให้สามารถนำโค้ดกลับมาใช้ใหม่ได้มากขึ้นและมีประสิทธิภาพสูงมากครับ
ผลการรัน:
สุนัขชื่อ แอล เกิดแล้ว เป็นพันธุ์ ลาบราดอร์ รีทรีฟเวอร์
แอล: โฮ่ง!
แอล กำลังนำทางผู้คนอย่างปลอดภัย
ตัวอย่างการใช้งานจริง: คลาสสำหรับจัดการบทความบล็อก
ทีนี้ มาดูตัวอย่างที่ใกล้เคียงกับงานสร้างเว็บจริงๆ กันบ้างครับ เราจะสร้างคลาส `BlogPost` สำหรับจัดการบทความในเว็บไซต์บล็อก โดยบทความจะมี "หัวข้อ", "เนื้อหา", "ผู้เขียน" และมีความสามารถในการ "แสดงผล"
import textwrap
class BlogPost:
def __init__(self, title, content, author):
self.title = title
self.content = content
self.author = author
# เมธอดสำหรับแสดงข้อมูลบทความอย่างสวยงาม
def display(self):
print("--------------------")
print(f"หัวข้อ: {self.title}")
print(f"ผู้เขียน: {self.author}")
print("--- เนื้อหา ---")
# แสดงผลข้อความยาวๆ โดยมีการตัดบรรทัด
print(textwrap.fill(self.content, width=40))
print("--------------------")
# สร้างอ็อบเจกต์บทความหลายๆ ชิ้น
post1 = BlogPost(
"ความรู้เบื้องต้นเกี่ยวกับคลาสใน Python",
"การเขียนโปรแกรมเชิงวัตถุคือแนวคิดในการสร้างโปรแกรมเหมือนการประกอบชิ้นส่วน คลาสคือพิมพ์เขียว และอ็อบเจกต์คือตัวตนที่จับต้องได้",
"Taro Yamada"
)
post2 = BlogPost(
"พื้นฐานการออกแบบเว็บ",
"การออกแบบที่ดีไม่ได้คำนึงถึงแค่ความสวยงาม แต่ให้ความสำคัญกับความง่ายในการใช้งานของผู้ใช้เป็นอันดับแรก พื้นที่ว่างและการใช้สีจึงเป็นสิ่งสำคัญ",
"Hanako Sato"
)
# แสดงผลบทความ
post1.display()
post2.display()
จะเห็นว่าการจัดการบทความแต่ละชิ้นให้เป็นอ็อบเจกต์ ทำให้ข้อมูล (เช่น หัวข้อ) และพฤติกรรม (ฟังก์ชันการแสดงผล) ถูกรวบไว้ด้วยกัน ทำให้การจัดการง่ายขึ้นมากครับ
ผลการรัน:
--------------------
หัวข้อ: ความรู้เบื้องต้นเกี่ยวกับคลาสใน Python
ผู้เขียน: Taro Yamada
--- เนื้อหา ---
การเขียนโปรแกรมเชิงวัตถุคือแนวคิดในการสร้าง
โปรแกรมเหมือนการประกอบชิ้นส่วน คลาสคือ
พิมพ์เขียว และอ็อบเจกต์คือตัวตนที่จับต้องได้
--------------------
--------------------
หัวข้อ: พื้นฐานการออกแบบเว็บ
ผู้เขียน: Hanako Sato
--- เนื้อหา ---
การออกแบบที่ดีไม่ได้คำนึงถึงแค่ความสวยงาม
แต่ให้ความสำคัญกับความง่ายในการใช้งานของผู้ใช้
เป็นอันดับแรก พื้นที่ว่างและการใช้สีจึงเป็น
สิ่งสำคัญ
--------------------
[มาลองรันโค้ดจริงกัน!] ตัวอย่างโค้ด Python ฉบับสมบูรณ์
รอมานานแล้วใช่ไหมครับ! ในส่วนนี้ เราจะนำเสนอโค้ดฉบับสมบูรณ์ของ "โปรแกรมจัดการผู้ใช้" ซึ่งรวบรวมเนื้อหาทั้งหมดที่ผ่านมา คุณสามารถคัดลอกโค้ดนี้ไปบันทึกเป็นไฟล์ `.py` แล้วรันผ่าน Terminal (หรือ Command Prompt) บนเครื่องคอมพิวเตอร์ของคุณได้เลย มาลองสัมผัสประสบการณ์ "โค้ดที่รันได้จริง" กันครับ!
วิธีการรัน
- คัดลอกโค้ดทั้งหมดด้านล่าง
- นำไปวางในโปรแกรม Text Editor (เช่น VSCode) แล้วบันทึกเป็นชื่อ `user_manager.py`
- เปิด Terminal แล้วไปยังไดเรกทอรีที่คุณบันทึกไฟล์ไว้
- พิมพ์ `python user_manager.py` แล้วกด Enter
หากเครื่องคอมพิวเตอร์ของคุณยังไม่ได้ติดตั้ง Python สามารถดาวน์โหลดได้ที่ python.org ครับ
# user_manager.py
class User:
"""
คลาสสำหรับแสดงข้อมูลผู้ใช้ของเว็บไซต์
"""
def __init__(self, user_id, name, email):
self.user_id = user_id
self.name = name
self.email = email
self.is_active = True # โดยปกติจะเป็นผู้ใช้ที่ใช้งานอยู่
def get_profile(self):
"""
จัดรูปแบบและส่งคืนข้อมูลโปรไฟล์ของผู้ใช้
"""
status = "ใช้งานอยู่" if self.is_active else "ไม่ใช้งาน"
return f"ID: {self.user_id}\nชื่อ: {self.name}\nอีเมล: {self.email}\nสถานะ: {status}"
def deactivate(self):
"""
ปิดการใช้งานผู้ใช้
"""
self.is_active = False
print(f"ผู้ใช้ '{self.name}' ถูกปิดการใช้งานแล้ว")
# ส่วนที่ใช้รันโปรแกรมหลัก
if __name__ == "__main__":
# สร้างอ็อบเจกต์ผู้ใช้หลายๆ คน
user1 = User("web-creator", "Taro Tanaka", "tanaka@example.com")
user2 = User("designer-sato", "Hanako Sato", "sato@example.com")
# แสดงโปรไฟล์
print("--- รายชื่อผู้ใช้ ---")
print(user1.get_profile())
print("-" * 20)
print(user2.get_profile())
print("\n" + "=" * 20 + "\n")
# ลองปิดการใช้งานผู้ใช้หนึ่งคน
user2.deactivate()
print("\n--- รายชื่อผู้ใช้หลังการเปลี่ยนแปลง ---")
print(user1.get_profile())
print("-" * 20)
print(user2.get_profile())
เมื่อรันโค้ดนี้ ใน Terminal ของคุณควรจะแสดงผลลัพธ์ดังนี้ครับ
ตัวอย่างผลการรัน:
--- รายชื่อผู้ใช้ ---
ID: web-creator
ชื่อ: Taro Tanaka
อีเมล: tanaka@example.com
สถานะ: ใช้งานอยู่
--------------------
ID: designer-sato
ชื่อ: Hanako Sato
อีเมล: sato@example.com
สถานะ: ใช้งานอยู่
====================
ผู้ใช้ 'Hanako Sato' ถูกปิดการใช้งานแล้ว
--- รายชื่อผู้ใช้หลังการเปลี่ยนแปลง ---
ID: web-creator
ชื่อ: Taro Tanaka
อีเมล: tanaka@example.com
สถานะ: ใช้งานอยู่
--------------------
ID: designer-sato
ชื่อ: Hanako Sato
อีเมล: sato@example.com
สถานะ: ไม่ใช้งาน
เป็นอย่างไรบ้างครับ? จะเห็นว่าการใช้คลาสทำให้ข้อมูลผู้ใช้และการดำเนินการที่เกี่ยวข้อง (เช่น การปิดใช้งาน) ถูกจัดเก็บรวมกันอย่างเป็นระเบียบ ทำให้โค้ดอ่านง่ายขึ้นอย่างเห็นได้ชัดเลยใช่ไหมครับ
ข้อควรระวังและข้อผิดพลาดที่พบบ่อย
สุดท้ายนี้ ขอแนะนำจุดที่มือใหม่มักจะสะดุดเมื่อเริ่มใช้งานคลาสครับ
- ลืมใส่ `self`: ตอนที่กำหนดเมธอด หากลืมใส่ `self` เป็นพารามิเตอร์ตัวแรก หรือตอนที่เข้าถึง attribute ภายในเมธอดแล้วลืมใส่ `self.` (เช่น `self.name`) จะทำให้เกิด error ครับ ให้จำไว้ว่า "เรื่องภายในคลาส ต้องผ่าน `self`"
- สะกด `__init__` ผิด: `__init__` จะมีขีดล่างสองขีดอยู่ข้างหน้าและข้างหลังครับ หากใส่แค่ขีดเดียว เช่น `_init_` มันจะถูกมองว่าเป็นเมธอดธรรมดา และจะไม่ถูกเรียกใช้งานอัตโนมัติเป็นเมธอดตั้งค่าเริ่มต้น
- ลืมใส่ `()` ตอนสร้าง instance: หากลืมใส่วงเล็บ เช่น `my_dog = Dog` จะไม่เป็นการสร้างอ็อบเจกต์ แต่จะเป็นการนำคลาสทั้งคลาสไปเก็บไว้ในตัวแปรแทน ต้องใส่วงเล็บเสมอ เช่น `my_dog = Dog()`
ไปยังขั้นตอนถัดไป
เมื่อเข้าใจพื้นฐานของคลาสและการเขียนโปรแกรมเชิงวัตถุแล้ว ต่อไปเรามาลองใช้ไลบรารีมาตรฐานที่มีประโยชน์ของ Python กันครับ การจัดการวันและเวลาเป็นสิ่งที่ต้องทำบ่อยมากในการเขียนโปรแกรม
ในบทความถัดไป เราจะเรียนรู้วิธีการดึงวันที่ปัจจุบันและคำนวณวันที่โดยใช้โมดูล `datetime`
→ วิธีจัดการวันและเวลาด้วยโมดูล datetime