【คัดลอกและวางเพื่อรัน】มาสร้างแอป To-Do List ง่ายๆ ด้วย Python กันเถอะ! (แบบข้อความ)
หากต้องการเรียกใช้ Python ผ่าน Command Prompt หรือ PowerShell บนคอมพิวเตอร์ของคุณ คุณจำเป็นต้องดาวน์โหลดและติดตั้ง Python ก่อน
หากคุณยังไม่ได้ติดตั้ง กรุณาดูบทความ การติดตั้ง Python และการตั้งค่าสภาพแวดล้อมการพัฒนา เพื่อทำการติดตั้ง Python
สวัสดีครับ! ผมที่เมื่อไม่กี่เดือนก่อนยังไม่มีความรู้ด้านโปรแกรมมิ่งเลย กำลังแบ่งปันสิ่งที่ได้เรียนรู้จากการสร้างเว็บไซต์ร่วมกับ AI ครับ
ครั้งนี้ เราจะมาสร้าง "แอป To-Do List" ด้วย Python ซึ่งผมขอแนะนำอย่างยิ่งสำหรับเป็นก้าวแรกในการเรียนเขียนโปรแกรม เป้าหมายของบทความนี้มีเพียงอย่างเดียว! คือการให้คุณได้สัมผัสกับความรู้สึกตื่นเต้นที่ว่า "โปรแกรมที่ฉันสร้างเองมันทำงานได้!"
เรื่องทฤษฎียากๆ เอาไว้ทีหลัง! ก่อนอื่น เรามาลองจับโค้ดที่สามารถคัดลอกไปวางแล้วทำงานได้เลย เพื่อให้รู้สึกว่า "อ๋อ มันทำงานแบบนี้นี่เอง!" กันดีกว่าครับ ส่วนศัพท์เทคนิคต่างๆ ผมจะอธิบายแบบเข้าใจง่ายสุดๆ จากประสบการณ์ที่ผมเคยติดขัดมาก่อน รับรองว่าไม่ต้องกังวลครับ
มาลองรันตัวที่เสร็จแล้วกันก่อนเลย!
สิบปากว่าไม่เท่าตาเห็น! เรามาลองรันแอป To-Do List เวอร์ชั่นสมบูรณ์กันก่อนเลยดีกว่าครับ คัดลอกโค้ดทั้งหมดด้านล่างนี้ ไปสร้างไฟล์ชื่อ todo.py แล้ววางโค้ดลงไปและบันทึกได้เลย
# -*- coding: utf-8 -*-
TASKS_FILE = "tasks.txt"
def load_tasks():
"""ฟังก์ชันสำหรับโหลดงานจากไฟล์"""
try:
with open(TASKS_FILE, "r", encoding="utf-8") as f:
# ใช้ strip() เพื่อลบตัวอักษรขึ้นบรรทัดใหม่ที่อยู่ท้ายแต่ละบรรทัด
tasks = [line.strip() for line in f.readlines()]
except FileNotFoundError:
# หากไม่มีไฟล์อยู่ ให้คืนค่าเป็นลิสต์ว่าง
tasks = []
return tasks
def save_tasks(tasks):
"""ฟังก์ชันสำหรับบันทึกงานลงในไฟล์"""
with open(TASKS_FILE, "w", encoding="utf-8") as f:
# เพิ่มการขึ้นบรรทัดใหม่ต่อท้ายแต่ละงานแล้วเขียนลงไป
for task in tasks:
f.write(task + "\n")
def list_tasks(tasks):
"""ฟังก์ชันสำหรับแสดงรายการงานทั้งหมด"""
if not tasks:
print("✅ ยังไม่มีงาน")
return
print("--- To-Do List ---")
# ใช้ enumerate เพื่อดึงทั้ง index (หมายเลข) และ task ออกมาพร้อมกัน
for i, task in enumerate(tasks):
print(f"{i + 1}: {task}")
print("------------------")
def add_task(tasks):
"""ฟังก์ชันสำหรับเพิ่มงาน"""
task = input("กรุณาใส่งานที่ต้องการเพิ่ม: ")
if task:
tasks.append(task)
save_tasks(tasks)
print(f"✨ เพิ่มงาน '{task}' เรียบร้อยแล้ว")
else:
print("⚠️ ยังไม่ได้ป้อนงาน")
def delete_task(tasks):
"""ฟังก์ชันสำหรับลบงาน"""
list_tasks(tasks)
if not tasks:
return
try:
# ให้ผู้ใช้เลือกงานที่จะลบด้วยหมายเลข
num_str = input("กรุณาใส่หมายเลขงานที่ต้องการลบ: ")
num = int(num_str)
# ผู้ใช้จะนับจาก 1 แต่ index ของลิสต์เริ่มจาก 0 จึงต้องปรับค่า
if 1 <= num <= len(tasks):
removed_task = tasks.pop(num - 1)
save_tasks(tasks)
print(f"🗑️ ลบงาน '{removed_task}' เรียบร้อยแล้ว")
else:
print("⚠️ ไม่มีงานหมายเลขนั้น")
except ValueError:
# การจัดการข้อผิดพลาดกรณีที่ป้อนข้อมูลอื่นที่ไม่ใช่ตัวเลข
print("⚠️ กรุณาป้อนหมายเลขให้ถูกต้อง")
def main():
"""ฟังก์ชันสำหรับประมวลผลหลัก"""
tasks = load_tasks()
while True:
print("\nคุณต้องการทำอะไร?")
command = input("1:แสดงรายการ, 2:เพิ่ม, 3:ลบ, 9:ออก > ")
if command == "1":
list_tasks(tasks)
elif command == "2":
add_task(tasks)
elif command == "3":
delete_task(tasks)
elif command == "9":
print("👋 กำลังออกจากแอป ขอบคุณที่ใช้งานครับ!")
break
else:
print("⚠️ กรุณาป้อน 1, 2, 3 หรือ 9")
if __name__ == "__main__":
main()
เมื่อบันทึกแล้ว ให้เปิด Terminal (ถ้าเป็น Windows ก็ใช้ Command Prompt หรือ PowerShell) แล้วเข้าไปยังไดเรกทอรีที่บันทึกไฟล์ไว้ จากนั้นรันคำสั่งต่อไปนี้
python todo.py
เป็นอย่างไรบ้างครับ? มีข้อความถามว่า "คุณต้องการทำอะไร?" ขึ้นมาไหม? ลองป้อน "2" เพื่อเพิ่มงาน, "1" เพื่อดูรายการ, หรือ "3" เพื่อลบงานดูนะครับ สามารถออกจากแอปได้ด้วยการป้อน "9" สุดยอดไปเลย! นี่มันเป็นแอปที่ใช้งานได้จริงแล้ว!
จากนี้ไป เรามาไขปริศนากันดีกว่าว่าคาถาเวทมนตร์ (โค้ด) เหล่านี้มันทำอะไรกันแน่
ขั้นตอนที่ 1: เวอร์ชั่นสุดง่าย มีแค่ "เพิ่ม" กับ "แสดงรายการ"
การพยายามทำความเข้าใจทั้งหมดในคราวเดียวอาจจะหนักเกินไป เรามาเริ่มจากโค้ดที่ง่ายกว่านี้ โดยเน้นไปที่หัวใจของแอป นั่นคือฟังก์ชัน "เพิ่มงาน" และ "แสดงรายการงาน" กันก่อนครับ
# เตรียมลิสต์ว่าง (คล้ายๆ array) สำหรับเก็บงาน
tasks = []
# ทำซ้ำไปเรื่อยๆ
while True:
print("\nคุณต้องการทำอะไร?")
command = input("1:แสดงรายการ, 2:เพิ่ม, 9:ออก > ")
if command == "1":
print("--- To-Do List ---")
for task in tasks:
print(task)
print("------------------")
elif command == "2":
task = input("กรุณาใส่งานที่ต้องการเพิ่ม: ")
tasks.append(task)
print(f"✨ เพิ่มงาน '{task}' เรียบร้อยแล้ว")
elif command == "9":
print("👋 กำลังออกจากแอป")
break # ออกจากลูป
else:
print("⚠️ กรุณาป้อน 1, 2 หรือ 9")
ในโค้ดสั้นๆ นี้ อัดแน่นไปด้วยพื้นฐานการเขียนโปรแกรมเลยครับ
tasks = []: นี่คือ "ลิสต์" สำหรับเก็บงานต่างๆ ครับ ลองนึกภาพว่าเรากำลังเตรียมกล่องเปล่าๆ ไว้while True:: นี่คือ "ลูปไม่รู้จบ" (infinite loop) มันจะรอรับคำสั่งจากผู้ใช้ไปเรื่อยๆ จนกว่าจะมีการป้อน "9" เข้ามา เป็นคาถาวิเศษที่ AI สอนผมตอนที่ผมถามครั้งแรกว่า "จะทำให้โปรแกรมรอรับคำสั่งไปเรื่อยๆ ได้ยังไง?"input(...): รับข้อความที่ผู้ใช้พิมพ์ผ่านคีย์บอร์ดif / elif / else: ใช้แยกการทำงานตามค่าของcommandที่รับเข้ามา เป็นเงื่อนไขที่ว่า "ถ้าเป็น 1 ให้แสดงรายการ, ถ้าเป็น 2 ให้เพิ่มงาน, นอกเหนือจากนั้น..."tasks.append(task): เพิ่มงานที่รับมาจากinputเข้าไปต่อท้ายในลิสต์tasksfor task in tasks:: ดึงข้อมูลในลิสต์tasksออกมาทีละตัวตั้งแต่ตัวแรก แล้วเก็บไว้ในตัวแปรชื่อtaskจากนั้นใช้print(task)เพื่อแสดงผลทางหน้าจอbreak: นี่คือสวิตช์สำหรับหลุดออกจากลูปไม่รู้จบ ถ้าลืมใส่คำสั่งนี้ไป ก็จะไม่มีทางออกจากโปรแกรมได้นอกจากการบังคับปิด (ซึ่งผมก็ทำบ่อย...!)
ขั้นตอนที่ 2: เพิ่ม "ฟังก์ชันลบ" และ "การจัดการข้อผิดพลาด"
ต่อไป เรามาทำให้สามารถลบงานที่เพิ่มเข้าไปได้กันดีกว่าครับ แต่แค่ลบเฉยๆ อาจจะไม่สะดวก เราเลยจะทำให้สามารถเลือกได้ว่าจะลบงานชิ้นไหนด้วยหมายเลข ตรงนี้จะเริ่มซับซ้อนขึ้นมาอีกนิดนะครับ!
# ... (นำโค้ดด้านล่างไปแทนที่ส่วน `if command == "1":` ในโค้ดของขั้นตอนที่ 1) ...
if command == "1":
print("--- To-Do List ---")
# การใช้ enumerate จะทำให้ดึงทั้งหมายเลขและข้อมูลในลิสต์ออกมาได้พร้อมกัน
for i, task in enumerate(tasks):
# i จะเริ่มจาก 0 ดังนั้นตอนแสดงผลเราจึงบวก 1 เข้าไป
print(f"{i + 1}: {task}")
print("------------------")
# ... (เพิ่มโค้ดด้านล่างนี้ต่อจาก `elif command == "2":` ในโค้ดของขั้นตอนที่ 1) ...
elif command == "3": # เพิ่มฟังก์ชันลบ
# แสดงรายการปัจจุบันก่อนเพื่อให้ผู้ใช้เลือกได้ง่ายขึ้น
for i, task in enumerate(tasks):
print(f"{i + 1}: {task}")
try:
num_str = input("กรุณาใส่หมายเลขงานที่ต้องการลบ: ")
num = int(num_str) # แปลงข้อความที่รับมาให้เป็นตัวเลข
# ใช้ pop() เพื่อลบข้อมูลออกจากลิสต์ตามตำแหน่ง (index) ที่ระบุ
removed_task = tasks.pop(num - 1)
print(f"🗑️ ลบงาน '{removed_task}' เรียบร้อยแล้ว")
except ValueError:
print("⚠️ กรุณาป้อนหมายเลขให้ถูกต้อง")
except IndexError:
print("⚠️ ไม่มีงานหมายเลขนั้น")
มีประเด็นใหม่ๆ เพิ่มขึ้นมาหลายอย่างเลยครับ
enumerate(tasks): อันนี้สะดวกมากๆ! เวลาที่เราวนลูปในลิสต์ มันจะใส่หมายเลข "0, 1, 2..." ให้โดยอัตโนมัติ ทำให้เราสามารถแสดงงานพร้อมกับหมายเลขได้แบบf"{i + 1}: {task}"นั่นเองtasks.pop(num - 1): นี่คือหัวใจของการลบครับpop()จะลบข้อมูล ณ ตำแหน่งที่ระบุออกจากลิสต์ ที่ต้องเป็นnum - 1ก็เพราะว่าผู้ใช้จะป้อน "1" แต่ในโลกของโปรแกรม (index ของลิสต์) จะเริ่มนับจาก "0" เราจึงต้องเลื่อนค่าไปหนึ่งตำแหน่ง การ "เริ่มจากศูนย์" นี้เป็นจุดที่โปรแกรมเมอร์มือใหม่สับสนกันทุกคนแน่นอน ดังนั้นจำไว้ให้ดีนะครับ!try / except: นี่คือกลไกสำหรับจัดการข้อผิดพลาดครับ หมายความว่า "ลองรันโค้ดในtry:ดูก่อนนะ, แต่ถ้าเกิดข้อผิดพลาดขึ้นมา ก็ให้ดักจับด้วยexcept:แล้วทำงานในส่วนนี้แทนที่จะปล่อยให้โปรแกรมพังไป"ValueError:int()จะแปลงข้อความเป็นตัวเลข แต่ถ้าป้อนตัวอักษรที่ไม่ใช่ตัวเลขเข้ามา เช่น "ก" ก็จะเกิดข้อผิดพลาดนี้IndexError: จะเกิดข้อผิดพลาดนี้เมื่อพยายามใช้pop()เพื่อลบหมายเลขที่ไม่มีอยู่จริงในลิสต์ (เช่น มีงานแค่ 3 ชิ้น แต่ระบุว่าจะลบ "5")
กฎเหล็กข้อหนึ่งคือ "ผู้ใช้ไม่ได้ทำตามที่ผู้พัฒนาคาดหวังเสมอไป" การใส่ระบบจัดการข้อผิดพลาดแบบนี้จะช่วยป้องกันไม่ให้แอปปิดตัวลงกะทันหัน และทำให้โปรแกรมของเราเป็นมิตรและแข็งแกร่งขึ้นครับ
ขั้นตอนที่ 3: บันทึกข้อมูลลงไฟล์ ป้องกันข้อมูลหาย
แอปของเราในตอนนี้มีจุดอ่อนสำคัญอยู่ครับ คือเมื่อเราปิดโปรแกรมไปครั้งหนึ่ง งานที่เราเพิ่มไว้ทั้งหมดจะหายไปหมดเลย แบบนี้ก็ใช้เป็น To-Do List ไม่ได้ใช่ไหมครับ? ดังนั้น เราจะมาเพิ่มฟังก์ชันสำหรับบันทึกงานลงไฟล์และอ่านข้อมูลกลับมาเมื่อเปิดโปรแกรมครั้งถัดไปกัน
# กำหนดชื่อไฟล์ไว้ก่อน
TASKS_FILE = "tasks.txt"
# --- นิยามฟังก์ชัน ---
def load_tasks():
try:
# "r" คือโหมดอ่าน (read)
with open(TASKS_FILE, "r", encoding="utf-8") as f:
# ใช้ readlines() อ่านทุกบรรทัดมาเป็นลิสต์ และใช้ strip() ลบตัวอักษรขึ้นบรรทัดใหม่
tasks = [line.strip() for line in f.readlines()]
except FileNotFoundError:
# กรณีที่ยังไม่มีไฟล์ เช่น การรันครั้งแรก จะเกิด error ดังนั้นเราจะคืนค่าเป็นลิสต์ว่าง
tasks = []
return tasks
def save_tasks(tasks):
# "w" คือโหมดเขียน (write) หากไม่มีไฟล์อยู่จะสร้างขึ้นมาใหม่
with open(TASKS_FILE, "w", encoding="utf-8") as f:
for task in tasks:
# ตอนเขียนลงไฟล์ ให้เพิ่มตัวอักษรขึ้นบรรทัดใหม่ (\n) ต่อท้ายแต่ละงาน
f.write(task + "\n")
# --- การประมวลผลหลัก ---
# เมื่อเปิดแอป ให้เริ่มจากการอ่านงานจากไฟล์ก่อน
tasks = load_tasks()
# ทุกครั้งที่มีการเพิ่มหรือลบงาน ให้แก้ไขโค้ดเพื่อเรียกใช้ save_tasks(tasks)
# (ดูตัวอย่างจากโค้ดฉบับสมบูรณ์ที่ให้ไว้ตอนแรก)
ประเด็นสำคัญของส่วนนี้คือ "การอ่านและเขียนไฟล์" ครับ
with open(...) as f:: เป็นสำนวนมาตรฐานเวลาที่ต้องจัดการไฟล์ใน Python ครับ การเขียนแบบนี้จะช่วยให้ไฟล์ถูกปิดโดยอัตโนมัติหลังจากอ่านหรือเขียนเสร็จสิ้น ทำให้ปลอดภัยกว่า "ผมเคยถาม AI ว่า 'สอนวิธีจัดการไฟล์อย่างปลอดภัยใน Python หน่อย' แล้วก็ได้คำแนะนำนี้มาเป็นอย่างแรกเลยครับ"- โหมด ("r", "w"): อาร์กิวเมนต์ตัวที่สองของ
open()ใช้ระบุว่าจะเปิดไฟล์อย่างไร"r"คือสำหรับอ่านอย่างเดียว (Read),"w"คือสำหรับเขียนอย่างเดียว (Write) ต้องระวังโหมด"w"ให้ดี เพราะถ้ามีไฟล์นั้นอยู่แล้ว มันจะลบเนื้อหาทั้งหมดทิ้งแล้วเขียนทับใหม่ encoding="utf-8": ให้คิดซะว่านี่เป็นคาถาบทหนึ่งครับ มันจำเป็นสำหรับการจัดการตัวอักษรหลายไบต์อย่างภาษาไทย ถ้าไม่ระบุอาจจะทำให้เกิดปัญหาตัวอักษรเพี้ยนได้- การอ่าน (load):
f.readlines()จะอ่านเนื้อหาในไฟล์มาเป็นลิสต์โดยแบ่งตามบรรทัด แต่ว่าท้ายแต่ละบรรทัดจะมีตัวอักษรขึ้นบรรทัดใหม่ (\n) ติดมาด้วย เราจึงใช้line.strip()เพื่อลบมันออกไปให้ได้ข้อมูลที่สะอาด - การเขียน (save):
f.write()จะเขียนข้อความลงในไฟล์ คราวนี้กลับกัน เราต้องการบันทึกแต่ละงานแยกกันคนละบรรทัด เราจึงต้องเพิ่มตัวอักษรขึ้นบรรทัดใหม่\nต่อท้ายข้อความของงานนั้นๆ ถ้าลืมทำแบบนี้ งานทั้งหมดจะถูกบันทึกติดกันเป็นพรืดในบรรทัดเดียว แล้วจะอ่านกลับมาอย่างถูกต้องไม่ได้ (ผมเองก็เคยติดปัญหานี้อยู่ 15 นาที...)
และสุดท้าย เหมือนกับโค้ดฉบับสมบูรณ์ที่ให้ไว้ตอนแรก การนำโค้ดที่ทำงานเป็นกลุ่มก้อนมาจัดระเบียบโดยใช้ def เพื่อสร้างเป็น "ฟังก์ชัน" (ซึ่งเรียกว่าการ Refactoring) จะทำให้โค้ดดูสะอาดตาและเข้าใจได้ง่ายขึ้นมากว่าส่วนไหนทำอะไร เมื่อโค้ดเริ่มยาวขึ้น การสร้างนิสัยจัดระเบียบโดยแบ่งตามฟังก์ชันการทำงานใส่กล่อง (ฟังก์ชัน) ไว้ จะทำให้ตัวเราในอนาคตทำงานสบายขึ้นเยอะเลยครับ
สรุป: ถ้ามันทำงานได้ ก็ถือว่าสำเร็จ! แล้วไปต่อกันเลย
お疲れ様でした!これであなたは、Pythonで自分だけのToDoリストアプリを作る力を手に入れました。重要なのは、完璧に理解することよりも、「コピペでもいいから、まず動かしてみる」ことです。動くものがあって、それを少しずついじりながら「これを変えたらどうなるんだろう?」と実験していくのが、上達への一番の近道だと、私は身をもって体験しました。
ข้อผิดพลาดไม่ใช่สิ่งที่น่ากลัว แต่มันคือคำใบ้ที่จะทำให้โปรแกรมของคุณดีขึ้น แม้ว่าจะอ่านข้อความข้อผิดพลาดไม่ออก ก็สามารถคัดลอกไปแปะถาม AI ได้เลยว่า "ข้อผิดพลาดนี้หมายความว่าอะไร แล้วจะแก้ยังไง?" ซึ่งส่วนใหญ่ก็จะได้รับคำตอบครับ
ぜひ、今回作ったアプリに「タスクの編集機能」や「完了したタスクにチェックを入れる機能」などを追加して、あなただけの最強のToDoリストに育ててみてください!
ก้าวต่อไป
เมื่อสร้างแอปพื้นฐานได้แล้ว ต่อไปเรามาลองท้าทายกับการคำนวณกันดูไหมครับ? เรามีบทความสอนวิธีสร้างแอปเครื่องคิดเลขง่ายๆ ที่สามารถบวกลบคูณหารได้
มาสร้างแอปเครื่องคิดเลขด้วย Python กันเถอะ (การดำเนินการทางคณิตศาสตร์)