บทที่ 9

ฟังก์ชัน - Function

Code Organization

เรียนรู้การสร้างและใช้ฟังก์ชันเพื่อจัดระเบียบโค้ด

🎯 จุดประสงค์การเรียนรู้

• เข้าใจแนวคิดและประโยชน์ของฟังก์ชัน

• สามารถสร้างและเรียกใช้ฟังก์ชันได้

• รู้จักการส่งค่าเข้าและรับค่าออกจากฟังก์ชัน

• ประยุกต์ใช้ฟังก์ชันในการแก้ปัญหาจริง

ฟังก์ชัน (Function) คืออะไร?

🏭 เปรียบเทียบกับโรงงานผลิต

ฟังก์ชัน = โรงงานที่รับวัตถุดิบเข้ามา แล้วผลิตสินค้าออกไป

Input (วัตถุดิบ) = ข้อมูลที่ส่งเข้าฟังก์ชัน

Process (กระบวนการ) = โค้ดที่ประมวลผลข้อมูล

Output (สินค้า) = ผลลัพธ์ที่ได้จากฟังก์ชัน

# ตัวอย่างฟังก์ชันง่ายๆ
def greet_student(name):
    """ฟังก์ชันทักทายนักเรียน"""
    message = f"สวัสดี {name}! ยินดีต้อนรับสู่ห้องเรียน"
    return message

# การเรียกใช้ฟังก์ชัน
result = greet_student("สมชาย")
print(result)  # สวัสดี สมชาย! ยินดีต้อนรับสู่ห้องเรียน
💡 ข้อดี: ลดการเขียนโค้ดซ้ำ, จัดระเบียบง่าย, แก้ไขง่าย, ทดสอบง่าย

การสร้างฟังก์ชัน

📋 โครงสร้างฟังก์ชัน

ฟังก์ชันใน Python ประกอบด้วยส่วนสำคัญ 4 ส่วน

# โครงสร้างฟังก์ชันพื้นฐาน
def function_name(parameters):
    """คำอธิบายฟังก์ชัน (Docstring)"""
    # โค้ดที่ต้องการให้ทำงาน
    return result  # (ไม่บังคับ)

✅ ฟังก์ชันไม่มี Parameter

def show_menu():
    """แสดงเมนูโปรแกรม"""
    print("=== เมนูหลัก ===")
    print("1. เพิ่มข้อมูล")
    print("2. ดูข้อมูล")
    print("3. ออก")

# เรียกใช้
show_menu()

🔹 ฟังก์ชันมี Parameter

def calculate_grade(score):
    """คำนวณเกรดจากคะแนน"""
    if score >= 80:
        return "A"
    elif score >= 70:
        return "B"
    else:
        return "C"

# เรียกใช้
grade = calculate_grade(85)
print(grade)  # A

🏃‍♂️ แบบฝึกหัด

สร้างฟังก์ชัน say_hello() ที่แสดงข้อความ "สวัสดีครับ!"

Parameters และ Arguments

🎯 ความแตกต่างที่สำคัญ

Parameters = ตัวแปรในฟังก์ชัน (ตัวรับ)

Arguments = ค่าที่ส่งเข้าฟังก์ชัน (ตัวส่ง)

# ฟังก์ชันที่มี parameters หลายตัว
def calculate_bmi(weight, height):
    """คำนวณค่า BMI"""
    bmi = weight / (height ** 2)
    return round(bmi, 2)

# การเรียกใช้แบบต่างๆ
# แบบที่ 1: ส่งตามลำดับ (Positional Arguments)
my_bmi = calculate_bmi(65, 1.70)
print(f"BMI: {my_bmi}")  # BMI: 22.49

# แบบที่ 2: ระบุชื่อ parameter (Keyword Arguments)
friend_bmi = calculate_bmi(height=1.65, weight=55)
print(f"BMI เพื่อน: {friend_bmi}")  # BMI เพื่อน: 20.2
# ฟังก์ชันที่มีค่า Default
def introduce_student(name, grade=10, school="โรงเรียนมัธยม"):
    """แนะนำตัวนักเรียน"""
    return f"ชื่อ {name} เรียนชั้น ม.{grade} ที่{school}"

# เรียกใช้แบบต่างๆ
print(introduce_student("สมชาย"))
# ชื่อ สมชาย เรียนชั้น ม.10 ที่โรงเรียนมัธยม

print(introduce_student("สมหญิง", 11))
# ชื่อ สมหญิง เรียนชั้น ม.11 ที่โรงเรียนมัธยม

print(introduce_student("สมศักดิ์", 12, "โรงเรียนวิทยาศาสตร์"))
# ชื่อ สมศักดิ์ เรียนชั้น ม.12 ที่โรงเรียนวิทยาศาสตร์
⚠️ กฎสำคัญ: Parameters ที่มีค่า default ต้องอยู่หลัง parameters ที่ไม่มีค่า default

การคืนค่า - Return

return ค่าเดียว

คืนค่าหนึ่งค่า

ฟังก์ชันส่งค่าหนึ่งค่ากลับไป

def square(x):
    return x ** 2

result = square(5)
print(result)  # 25
return หลายค่า

คืนหลายค่าพร้อมกัน

ใช้ tuple ในการส่งหลายค่า

def get_name_grade():
    return "สมชาย", "A"

name, grade = get_name_grade()
print(name, grade)  # สมชาย A
ไม่มี return

ไม่คืนค่า (None)

ฟังก์ชันทำงานแล้วจบ

def print_hello():
    print("สวัสดี!")

result = print_hello()
print(result)  # None
return เงื่อนไข

คืนค่าตามเงื่อนไข

return ที่ต่างกันตามสถานการณ์

def check_pass(score):
    if score >= 60:
        return "ผ่าน"
    return "ไม่ผ่าน"
# ตัวอย่างฟังก์ชันคำนวณคะแนนเฉลี่ย
def calculate_average(scores):
    """คำนวณคะแนนเฉลี่ยและเกรด"""
    if not scores:  # ถ้าไม่มีคะแนน
        return 0, "F"
    
    average = sum(scores) / len(scores)
    
    # กำหนดเกรด
    if average >= 80:
        grade = "A"
    elif average >= 70:
        grade = "B"
    elif average >= 60:
        grade = "C"
    else:
        grade = "F"
    
    return round(average, 2), grade

# ทดสอบฟังก์ชัน
my_scores = [85, 92, 78, 88, 95]
avg, grade = calculate_average(my_scores)
print(f"คะแนนเฉลี่ย: {avg}, เกรด: {grade}")  # คะแนนเฉลี่ย: 87.6, เกรด: A

ขอบเขตของตัวแปร - Scope

🏠 เปรียบเทียบกับห้องในบ้าน

Local Variable = ของในห้องส่วนตัว (ใช้ได้เฉพาะในห้องนั้น)

Global Variable = ของในห้องรับแขก (ใช้ได้ทุกห้อง)

# Global Variable (ตัวแปรส่วนรวม)
school_name = "โรงเรียนมัธยม"  # ใช้ได้ทุกที่
total_students = 1000

def show_school_info():
    """แสดงข้อมูลโรงเรียน"""
    # สามารถใช้ Global Variable ได้
    print(f"โรงเรียน: {school_name}")
    print(f"จำนวนนักเรียน: {total_students} คน")

def calculate_class_average(scores):
    """คำนวณคะแนนเฉลี่ยของห้อง"""
    # Local Variable (ตัวแปรภายในฟังก์ชัน)
    total_score = sum(scores)  # ใช้ได้เฉพาะในฟังก์ชันนี้
    student_count = len(scores)
    average = total_score / student_count
    
    print(f"โรงเรียน: {school_name}")  # ใช้ Global Variable ได้
    return average

# เรียกใช้ฟังก์ชัน
show_school_info()
class_scores = [80, 85, 92, 78, 88]
avg = calculate_class_average(class_scores)
print(f"คะแนนเฉลี่ย: {avg:.1f}")
# ปัญหาที่เกิดขึ้นได้
def test_scope():
    message = "สวัสดีจากในฟังก์ชัน"  # Local Variable
    print(message)

test_scope()  # ทำงานได้
# print(message)  # Error! ไม่สามารถใช้ Local Variable ภายนอกฟังก์ชันได้
💡 หลักการดี: หลีกเลี่ยงการใช้ Global Variable มากเกินไป ให้ส่งค่าผ่าน Parameters แทน

ฟังก์ชันพื้นฐานที่ Python มีให้

🛠️ Built-in Functions ที่ใช้บ่อย

Python มีฟังก์ชันพร้อมใช้งานมากมาย ไม่ต้องสร้างเอง

Math Functions

ฟังก์ชันคณิตศาสตร์

print(abs(-5))      # 5
print(max(1, 5, 3))  # 5
print(min(1, 5, 3))  # 1
print(round(3.7))   # 4
print(sum([1, 2, 3])) # 6
Type Functions

ฟังก์ชันแปลงชนิด

print(str(123))     # "123"
print(int("456"))   # 456
print(float("7.8")) # 7.8
print(bool(1))      # True
print(list("abc"))  # ['a', 'b', 'c']
Info Functions

ฟังก์ชันตรวจสอบ

print(len("Hello"))  # 5
print(type(123))    # <class 'int'>
print(isinstance(5, int))  # True
help(print)        # ดูวิธีใช้
Range Functions

ฟังก์ชันช่วง

print(list(range(5)))
# [0, 1, 2, 3, 4]

print(list(range(2, 8)))
# [2, 3, 4, 5, 6, 7]

print(list(enumerate(["a", "b"])))
# [(0, 'a'), (1, 'b')]

🏃‍♂️ แบบฝึกหัด

ใช้ฟังก์ชัน built-in หาค่าเฉลี่ยของคะแนน [85, 92, 78, 88, 95] ได้ใน 1 บรรทัด

ฟังก์ชันแบบสั้น - Lambda

⚡ Lambda = ฟังก์ชันย่อๆ ใช้งานง่าย

เหมาะสำหรับฟังก์ชันง่ายๆ ที่ใช้เพียงครั้งเดียว

🔴 แบบปกติ (def)

# ฟังก์ชันคำนวณพื้นที่วงกลม
def circle_area(radius):
    return 3.14 * radius ** 2

area = circle_area(5)
print(area)  # 78.5

# ฟังก์ชันคูณ 2
def double(x):
    return x * 2

result = double(10)
print(result)  # 20

🟢 แบบ Lambda

# ฟังก์ชันคำนวณพื้นที่วงกลม
circle_area = lambda radius: 3.14 * radius ** 2

area = circle_area(5)
print(area)  # 78.5

# ฟังก์ชันคูณ 2
double = lambda x: x * 2

result = double(10)
print(result)  # 20
# ตัวอย่างการใช้ Lambda กับ List
numbers = [1, 2, 3, 4, 5]

# ใช้ map() กับ lambda เพื่อแปลงทุกตัวในลิสต์
squares = list(map(lambda x: x**2, numbers))
print(f"ยกกำลัง 2: {squares}")  # [1, 4, 9, 16, 25]

# ใช้ filter() กับ lambda เพื่อกรองข้อมูล
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(f"เลขคู่: {even_numbers}")  # [2, 4]

# ตัวอย่างการเรียงลำดับนักเรียนตามคะแนน
students = [
    {"name": "สมชาย", "score": 85},
    {"name": "สมหญิง", "score": 92},
    {"name": "สมศักดิ์", "score": 78}
]

# เรียงตามคะแนนจากมากไปน้อย
sorted_students = sorted(students, key=lambda student: student["score"], reverse=True)
for student in sorted_students:
    print(f"{student['name']}: {student['score']}")
# สมหญิง: 92
# สมชาย: 85
# สมศักดิ์: 78
💡 เมื่อไหร่ใช้ Lambda: ฟังก์ชันสั้นๆ ใช้ครั้งเดียว, ใช้กับ map(), filter(), sorted()

ฟังก์ชันเรียกตัวเอง - Recursion

🔄 Recursion = ฟังก์ชันที่เรียกตัวเองซ้ำๆ

เหมาะสำหรับปัญหาที่สามารถแบ่งย่อยเป็นปัญหาเล็กๆ ที่เหมือนกัน

📈 Factorial (ตัวอย่างคลาสสิก)

# วิธี Recursion
def factorial(n):
    """คำนวณ n! (n factorial)"""
    # Base case (เงื่อนไขหยุด)
    if n <= 1:
        return 1
    
    # Recursive case (เรียกตัวเอง)
    return n * factorial(n - 1)

# ทดสอบ
print(factorial(5))  # 120
print(factorial(0))  # 1

🌟 Fibonacci (ลำดับฟีโบนักชี)

# วิธี Recursion
def fibonacci(n):
    """หาเลขฟีโบนักชีตำแหน่งที่ n"""
    # Base cases
    if n <= 0:
        return 0
    elif n == 1:
        return 1
    
    # Recursive case
    return fibonacci(n-1) + fibonacci(n-2)

# ทดสอบ
for i in range(8):
    print(fibonacci(i), end=" ")
# 0 1 1 2 3 5 8 13
# ตัวอย่างปัญหาจริง: นับถอยหลัง
def count_down(n):
    """นับถอยหลังจาก n ลงมา 0"""
    print(n)
    
    # Base case
    if n <= 0:
        print("ปล่อยจรวด!")
        return
    
    # Recursive case
    count_down(n - 1)

# ทดสอบ
count_down(5)
# 5
# 4
# 3
# 2
# 1
# 0
# ปล่อยจรวด!
⚠️ ข้อระวัง: ต้องมี Base Case เสมอ ไม่งั้นจะเรียกตัวเองไม่มีที่สิ้นสุด (Infinite Recursion)

หลักการออกแบบฟังก์ชันที่ดี

✨ Clean Code = โค้ดที่อ่านง่าย เข้าใจง่าย

ฟังก์ชันที่ดีควรทำงานเดียว ชื่อสื่อความหมาย และใช้งานง่าย

❌ ฟังก์ชันแบบไม่ดี

# ฟังก์ชันทำหลายอย่าง ชื่อไม่สื่อความหมาย
def process(data):
    # คำนวณเฉลี่ย
    avg = sum(data) / len(data)
    # พิมพ์ผลลัพธ์
    print(f"Average: {avg}")
    # เขียนไฟล์
    with open("result.txt", "w") as f:
        f.write(str(avg))
    # ส่งอีเมล
    send_email(avg)
    return avg

# ยากต่อการทดสอบและแก้ไข
result = process([80, 85, 90])

✅ ฟังก์ชันแบบดี

# แยกฟังก์ชันตามหน้าที่
def calculate_average(scores):
    """คำนวณคะแนนเฉลี่ย"""
    if not scores:
        return 0
    return sum(scores) / len(scores)

def display_result(average):
    """แสดงผลลัพธ์"""
    print(f"คะแนนเฉลี่ย: {average:.2f}")

def save_to_file(data, filename):
    """บันทึกข้อมูลลงไฟล์"""
    with open(filename, "w") as f:
        f.write(str(data))

# ใช้งานง่าย ทดสอบง่าย
scores = [80, 85, 90]
avg = calculate_average(scores)
display_result(avg)
save_to_file(avg, "result.txt")
Single Purpose

ทำงานเดียว

ฟังก์ชันหนึ่งควรทำงานเดียวเท่านั้น

Clear Naming

ชื่อสื่อความหมาย

ชื่อฟังก์ชันบอกได้ชัดเจนว่าทำอะไร

Small Size

ขนาดเล็ก

ไม่ควรยาวเกิน 20-30 บรรทัด

No Side Effects

ไม่มีผลข้างเคียง

ไม่แก้ไขตัวแปรภายนอกโดยไม่จำเป็น

ข้อผิดพลาดที่พบบ่อย

❌ ผิด

# 1. ลืม return
def add_numbers(a, b):
    result = a + b
    # ลืม return!

sum_result = add_numbers(5, 3)
print(sum_result)  # None

# 2. ใช้ Mutable Default
def add_student(name, class_list=[]):
    class_list.append(name)
    return class_list

list1 = add_student("สมชาย")
list2 = add_student("สมหญิง")
print(list2)  # ['สมชาย', 'สมหญิง'] ผิด!

✅ ถูก

# 1. มี return
def add_numbers(a, b):
    result = a + b
    return result  # ถูกต้อง!

sum_result = add_numbers(5, 3)
print(sum_result)  # 8

# 2. ใช้ None เป็น Default
def add_student(name, class_list=None):
    if class_list is None:
        class_list = []  # สร้างใหม่ทุกครั้ง
    class_list.append(name)
    return class_list

list1 = add_student("สมชาย")
list2 = add_student("สมหญิง")
print(list2)  # ['สมหญิง'] ถูกต้อง!
# 3. ข้อผิดพลาดอื่นๆ ที่พบบ่อย

# ผิด: ใช้ Global Variable มากเกินไป
total_score = 0
def bad_add_score(score):
    global total_score
    total_score += score  # แก้ไข Global

# ถูก: ส่งค่าผ่าน Parameter และ Return
def good_add_score(current_total, score):
    return current_total + score  # ไม่แก้ไข Global

# ผิด: ฟังก์ชันทำหลายอย่างพร้อมกัน
def bad_process_student(name, scores):
    avg = sum(scores) / len(scores)  # คำนวณ
    print(f"{name}: {avg}")                # แสดงผล
    save_to_database(name, avg)          # บันทึก
    send_email_to_parent(name, avg)      # ส่งเมล
    return avg

# ถูก: แยกเป็นฟังก์ชันย่อย
def calculate_average(scores):
    return sum(scores) / len(scores)

def process_student(name, scores):
    avg = calculate_average(scores)
    display_result(name, avg)
    save_result(name, avg)
    notify_parent(name, avg)
    return avg
💡 เคล็ดลับ: ใช้ Docstring อธิบายฟังก์ชัน ทดสอบด้วยข้อมูลหลากหลาย ตั้งชื่อให้สื่อความหมาย

ตัวอย่างการใช้งานจริง

🎮 ระบบจัดการเกมคำถาม

ใช้ฟังก์ชันต่างๆ ในการสร้างเกมถามตอบง่ายๆ

# ระบบเกมคำถาม - ใช้ฟังก์ชันหลายแบบ
import random

# ข้อมูลคำถาม
QUESTIONS = [
    {"question": "เมืองหลวงของไทยคือ?", "answer": "กรุงเทพฯ"},
    {"question": "2 + 2 = ?", "answer": "4"},
    {"question": "ภาษาโปรแกรมที่เรียน?", "answer": "Python"},
    {"question": "1 ปี มีกี่วัน?", "answer": "365"}
]

def display_welcome():
    """แสดงข้อความต้อนรับ"""
    print("ยินดีต้อนรับสู่เกมคำถาม!")
    print("จงตอบคำถามให้ถูกต้องมากที่สุด")
    print("=" * 40)

def get_random_question(questions):
    """สุ่มเลือกคำถาม"""
    return random.choice(questions)

def ask_question(question_data):
    """ถามคำถามและรับคำตอบ"""
    question = question_data["question"]
    print(f"คำถาม: {question}")
    user_answer = input("คำตอบของคุณ: ").strip()
    return user_answer

def check_answer(user_answer, correct_answer):
    """ตรวจสอบคำตอบ (ไม่แยกตัวพิมพ์ใหญ่เล็ก)"""
    return user_answer.lower() == correct_answer.lower()

def display_result(is_correct, correct_answer):
    """แสดงผลลัพธ์"""
    if is_correct:
        print("ถูกต้อง! เก่งมาก")
    else:
        print(f"ผิด! คำตอบที่ถูกคือ: {correct_answer}")

def calculate_score(correct_count, total_count):
    """คำนวณคะแนนเป็นเปอร์เซ็นต์"""
    if total_count == 0:
        return 0
    return (correct_count / total_count) * 100

def get_grade(score):
    """แปลงคะแนนเป็นเกรด"""
    grade_map = {
        90: "A", 80: "B", 70: "C", 
        60: "D", 0: "F"
    }
    for min_score, grade in grade_map.items():
        if score >= min_score:
            return grade
    return "F"
def display_final_score(correct, total):
    """แสดงคะแนนสรุป"""
    score = calculate_score(correct, total)
    grade = get_grade(score)
    
    print("\n" + "=" * 40)
    print("ผลการแข่งขัน")
    print(f"ตอบถูก: {correct}/{total} ข้อ")
    print(f"คะแนน: {score:.1f}%")
    print(f"เกรด: {grade}")
    
    # ข้อความกำลังใจตามผลคะแนน
    if score >= 90:
        print("ยอดเยี่ยม! คุณเก่งมาก!")
    elif score >= 70:
        print("ดีมาก! พยายามต่อไป")
    elif score >= 50:
        print("ผ่านเกณฑ์! ลองทบทวนอีกนิด")
    else:
        print("ลองศึกษาเพิ่มเติมนะ")

def play_quiz_game(num_questions=3):
    """ฟังก์ชันหลักในการเล่นเกม"""
    display_welcome()
    
    correct_answers = 0
    total_questions = min(num_questions, len(QUESTIONS))
    
    # คัดลอกคำถามเพื่อไม่ให้ซ้ำ
    available_questions = QUESTIONS.copy()
    
    for i in range(total_questions):
        print(f"\nคำถามที่ {i + 1}")
        
        # เลือกคำถามและลบออกจากรายการ
        question_data = get_random_question(available_questions)
        available_questions.remove(question_data)
        
        # ถามและตรวจคำตอบ
        user_answer = ask_question(question_data)
        is_correct = check_answer(user_answer, question_data["answer"])
        
        # แสดงผลและนับคะแนน
        display_result(is_correct, question_data["answer"])
        if is_correct:
            correct_answers += 1
    
    # แสดงคะแนนสรุป
    display_final_score(correct_answers, total_questions)

# เรียกใช้เกม
if __name__ == "__main__":
    play_quiz_game(3)  # เล่น 3 ข้อ

🎯 ความรู้ที่ได้จากตัวอย่าง

• แยกฟังก์ชันตามหน้าที่ - แต่ละฟังก์ชันทำงานเดียว

• ใช้ชื่อฟังก์ชันที่สื่อความหมายชัดเจน

• ส่งผ่านข้อมูลด้วย Parameters แทนการใช้ Global

• มี Docstring อธิบายการทำงานของฟังก์ชัน

• จัดการข้อมูลด้วย Return Value

• รวมฟังก์ชันย่อยเป็นฟังก์ชันใหญ่

โปรเจกต์สรุป: ระบบจัดการคะแนน

🎯 สร้างระบบจัดการคะแนนนักเรียนแบบครบครัน

ใช้ฟังก์ชันทุกแบบที่เรียนมา พร้อมเมนูและการจัดการข้อมูล

# โปรเจกต์: ระบบจัดการคะแนนนักเรียน

# ======= ฟังก์ชันจัดการข้อมูลพื้นฐาน =======
def create_student(student_id, name, grade):
    """สร้างข้อมูลนักเรียนใหม่"""
    return {
        "id": student_id,
        "name": name,
        "grade": grade,
        "scores": {},
        "created_date": "2024-01-01"
    }

def add_score(student, subject, score):
    """เพิ่มคะแนนวิชาให้นักเรียน"""
    if 0 <= score <= 100:
        student["scores"][subject] = score
        return True
    return False

def calculate_average(scores_dict):
    """คำนวณคะแนนเฉลี่ย"""
    if not scores_dict:
        return 0
    return round(sum(scores_dict.values()) / len(scores_dict), 2)

def get_grade_from_average(average):
    """แปลงคะแนนเฉลี่ยเป็นเกรด"""
    if average >= 80: return "A"
    elif average >= 70: return "B"
    elif average >= 60: return "C"
    elif average >= 50: return "D"
    else: return "F"

# ======= ฟังก์ชันค้นหาและแสดงผล =======
def find_student_by_id(students, student_id):
    """ค้นหานักเรียนจากรหัส"""
    for student in students:
        if student["id"] == student_id:
            return student
    return None

def display_student_info(student):
    """แสดงข้อมูลนักเรียนแบบละเอียด"""
    avg = calculate_average(student["scores"])
    grade = get_grade_from_average(avg)
    
    print(f"\n===== ข้อมูลนักเรียน =====")
    print(f"รหัส: {student['id']}")
    print(f"ชื่อ: {student['name']}")
    print(f"ชั้น: ม.{student['grade']}")
    print(f"คะแนนเฉลี่ย: {avg} ({grade})")
    
    if student["scores"]:
        print(f"คะแนนแต่ละวิชา:")
        for subject, score in student["scores"].items():
            print(f"  - {subject}: {score}")
    else:
        print("ยังไม่มีคะแนน")

def get_top_students(students, limit=5):
    """หานักเรียนที่มีคะแนนเฉลี่ยสูงสุด"""
    students_with_avg = []
    for student in students:
        avg = calculate_average(student["scores"])
        if avg > 0:  # มีคะแนน
            students_with_avg.append((student, avg))
    
    # เรียงตามคะแนนจากมากไปน้อย
    sorted_students = sorted(students_with_avg, 
                                   key=lambda x: x[1], 
                                   reverse=True)
    return sorted_students[:limit]
# ======= ฟังก์ชันเมนูและการโต้ตอบ =======
def show_main_menu():
    """แสดงเมนูหลัก"""
    print("\n" + "="*50)
    print("    ระบบจัดการคะแนนนักเรียน")
    print("="*50)
    print("1. เพิ่มนักเรียนใหม่")
    print("2. เพิ่มคะแนน")
    print("3. ค้นหานักเรียน")
    print("4. แสดงรายชื่อทั้งหมด")
    print("5. นักเรียนยอดเยี่ยม 5 อันดับ")
    print("6. สรุปคะแนนของห้อง")
    print("9. ออกจากโปรแกรม")
    print("="*50)

def get_menu_choice():
    """รับตัวเลือกเมนูจากผู้ใช้"""
    try:
        choice = int(input("เลือกเมนู (1-9): "))
        return choice
    except ValueError:
        return 0  # ค่าผิด

def display_class_summary(students, grade_filter=None):
    """แสดงสรุปคะแนนของห้อง"""
    filtered_students = students
    if grade_filter:
        filtered_students = [s for s in students 
                               if s["grade"] == grade_filter]
    
    if not filtered_students:
        print("ไม่มีข้อมูลนักเรียน")
        return
    
    total_students = len(filtered_students)
    students_with_scores = [s for s in filtered_students 
                            if s["scores"]]
    
    if students_with_scores:
        all_averages = [calculate_average(s["scores"]) 
                        for s in students_with_scores]
        class_average = round(sum(all_averages) / len(all_averages), 2)
        highest_avg = max(all_averages)
        lowest_avg = min(all_averages)
    else:
        class_average = highest_avg = lowest_avg = 0
    
    grade_text = f"ชั้น ม.{grade_filter}" if grade_filter else "ทุกชั้น"
    
    print(f"\n===== สรุปคะแนน{grade_text} =====")
    print(f"จำนวนนักเรียนทั้งหมด: {total_students} คน")
    print(f"นักเรียนที่มีคะแนน: {len(students_with_scores)} คน")
    print(f"คะแนนเฉลี่ยของห้อง: {class_average}")
    print(f"คะแนนสูงสุด: {highest_avg}")
    print(f"คะแนนต่ำสุด: {lowest_avg}")

# ======= ฟังก์ชันหลัก =======
def main():
    """ฟังก์ชันหลักของโปรแกรม"""
    students = []  # เก็บข้อมูลนักเรียนทั้งหมด
    
    print("ยินดีต้อนรับสู่ระบบจัดการคะแนนนักเรียน!")
    
    while True:
        show_main_menu()
        choice = get_menu_choice()
        
        if choice == 9:
            print("ขอบคุณที่ใช้งาน!")
            break
        elif choice == 1:
            # เพิ่มนักเรียน
            student_id = input("รหัสนักเรียน: ").strip()
            if find_student_by_id(students, student_id):
                print("มีรหัสนักเรียนนี้แล้ว")
            else:
                name = input("ชื่อ-นามสกุล: ").strip()
                grade = int(input("ชั้น (1-6): "))
                student = create_student(student_id, name, grade)
                students.append(student)
                print(f"เพิ่ม {name} เรียบร้อยแล้ว")
        
        # ... (จัดการเมนูอื่นๆ ต่อไป)

# เรียกใช้โปรแกรม
if __name__ == "__main__":
    main()

🎉 ความรู้ที่ได้จากบทนี้

• การสร้างและเรียกใช้ฟังก์ชันแบบต่างๆ

• การส่งผ่าน Parameters และการ Return Values

• ขอบเขตของตัวแปร (Local vs Global Scope)

• ฟังก์ชัน Built-in ที่ Python มีให้

• Lambda Functions สำหรับงานง่ายๆ

• Recursion และการเรียกตัวเอง

• หลักการออกแบบฟังก์ชันที่ดี

• การประยุกต์ใช้ในโปรแกรมจริง