---
title: "Python สำหรับมือใหม่ #3: ฟังก์ชัน List และ Dictionary"
description: "บทความตอนที่ 3 ในซีรีส์ Python สำหรับมือใหม่ จะพาคุณจัดโค้ดเป็นก้อนด้วย function เก็บข้อมูลหลายตัวด้วย list/dict แล้วจบด้วยโปรแกรมตัดเกรดจริง"
pubDate: 2026-09-11T17:00:00.000Z
updatedDate: 2026-09-11T17:00:00.000Z
tag: ["Python"]
url: https://9lynn.com/blog/python-for-beginner-3/
---
# Python สำหรับมือใหม่ #3: ฟังก์ชัน List และ Dictionary

> บทความตอนที่ 3 ในซีรีส์ Python สำหรับมือใหม่ จะพาคุณจัดโค้ดเป็นก้อนด้วย function เก็บข้อมูลหลายตัวด้วย list/dict แล้วจบด้วยโปรแกรมตัดเกรดจริง

Original: https://9lynn.com/blog/python-for-beginner-3/ — Markdown: https://9lynn.com/blog/python-for-beginner-3.md

---

import CodeOutput from '../../../components/CodeOutput.astro'

ใน Part 2 เราเขียนโค้ดจริงกันแล้วเนอะ ทั้งตัวแปร `if/else` แล้วก็ `for/while` แต่เชื่อไหมครับ พอโค้ดเริ่มยาวขึ้นอีกนิด ปัญหาเดิมจะมาเลยคือ **ก๊อปโค้ดซ้ำไปซ้ำมา** จะแก้ทีก็ต้องไล่แก้หลายที่ ลืมที่เดียวก็พังแล้ว

Part นี้เลยจะชวนมารู้จักของ 3 อย่างที่จะช่วยชีวิตเราได้เยอะมากครับ คือ **ฟังก์ชัน (function)** เอาไว้เก็บโค้ดเป็นก้อนเรียกใช้ซ้ำได้ **list** เอาไว้เก็บของหลายๆ ชิ้น แล้วก็ **dict** เอาไว้เก็บข้อมูลแบบมีชื่อกำกับ สุดท้ายเราจะเอาทั้ง 3 อย่างมาทำโปรแกรมตัดเกรดทั้งห้องกัน

---

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

พูดง่ายๆ ฟังก์ชันก็เหมือน **กล่องเก็บโค้ด** ครับ เราเอาโค้ดยัดใส่กล่อง ตั้งชื่อให้มัน เวลาจะใช้ก็แค่เรียกชื่อ ไม่ต้องเขียนซ้ำ

วิธีสร้างก็ไม่ยาก ใช้คำว่า `def` แล้วตามด้วยชื่อ วงเล็บ แล้วก็ `:` จากนั้นก็ indent เข้าไปเหมือนตอนเขียน `if` ใน Part 2 เลยครับ

### indent คืออะไร? แวะอธิบายหน่อย

**indent** ก็คือ **การย่อหน้าหรือเคาะเว้นข้างหน้า** นี่แหละครับ ปกติเรากด `Tab` หรือเคาะ `Space 4 ที` Python จะใช้ตรงนี้แหละบอกว่า "โค้ดบรรทัดนี้อยู่ข้างในกล่องไหน"

ภาษาอื่นเขาใช้ปีกกา `{ }` ครอบ แต่ Python ใช้ช่องว่างแทนครับ บรรทัดไหนย่อหน้าเท่ากันก็แปลว่าอยู่กลุ่มเดียวกัน บรรทัดไหนไม่ย่อก็คือหลุดออกมาข้างนอกแล้ว

<CodeOutput>

```python
def greet():
    print("ข้างใน")  # ย่อหน้า 4 ช่อง = อยู่ในฟังก์ชัน
    print("ข้างในเหมือนกัน")  # ย่อหน้าเท่ากัน = อยู่กลุ่มเดียวกัน

print("ข้างนอก")  # ไม่ย่อ = หลุดออกมาข้างนอกแล้ว
```

```text title="ผลลัพธ์"
ข้างใน
ข้างในเหมือนกัน
ข้างนอก
```

</CodeOutput>

มือใหม่โดนกันบ่อย 2 แบบครับ:
- **ลืมย่อ** หลัง `def ...:` แล้วเขียนชิดซ้ายเลย อันนี้ได้ `IndentationError` ทันที Python มันจะบอกว่า expected an indented block
- **ย่อไม่เท่ากัน** บรรทัดนึง 4 ช่อง อีกบรรทัด 2 ช่อง หรือปน `Tab` กับ `Space` มั่วๆ กัน อันนี้ก็พังเหมือนกันครับ ตั้งใน VS Code ให้กด Tab แล้วแปลงเป็น 4 Space จะสบายสุด

```python
def greet():
print("แบบนี้พังนะ ลืมย่อ")  # IndentationError
```

จำง่ายๆ ครับ เจอ `:` เมื่อไหร่ บรรทัดต่อไปต้องย่อเข้าไปก่อนเสมอ ไม่ว่าจะเป็น `def` `if` หรือ `for` ที่เราเจอใน Part 2 ก็กฎเดียวกันหมดเลย

```python
def ชื่อฟังก์ชัน():
    # โค้ดตรงนี้ยังไม่ทำงานนะ แค่บอกไว้ก่อนว่ากล่องนี้มีอะไรบ้าง
```

ลองดูแบบไม่ใช้ฟังก์ชันก่อน ถ้าอยากทักทาย 3 รอบก็ต้องเขียน 3 บรรทัด:

```python
print("สวัสดีครับ")
print("สวัสดีครับ")
print("สวัสดีครับ")
```

วันไหนอยากเปลี่ยนเป็น "สวัสดีตอนเช้า" ก็ต้องไล่แก้ทั้ง 3 ที่ ลืมสักที่ก็ตลกเลย แต่ถ้าใส่กล่องไว้ แก้ที่เดียวจบครับ:

<CodeOutput>

```python
def greet():
    print("สวัสดีครับ")

greet()  # เรียกใช้รอบแรก
greet()  # เรียกใช้อีกรอบ
```

```text title="ผลลัพธ์"
สวัสดีครับ
สวัสดีครับ
```

</CodeOutput>

มี 2 อย่างที่อยากให้จำไว้ครับ:
- ตอน `def` คือแค่ **บอกไว้ก่อน** โค้ดข้างในยังไม่ทำงานนะ
- มันจะทำงานก็ตอนเรา **เรียก** นี่แหละ ต้องมีวงเล็บด้วยนะ `greet()` ถ้าเขียนแค่ `greet` เฉยๆ Python มันจะไม่เรียกให้ครับ มันนึกว่าเราชี้ไปที่กล่องเฉยๆ

แล้วทำไมต้องใช้ล่ะ? เอาจริงๆ มีแค่ 3 ข้อเองครับที่เราจะรู้สึกได้ทันที:
1. **เขียนรอบเดียวพอ** อยากใช้กี่รอบก็เรียกเอา
2. **แก้ที่เดียว** เปลี่ยนในฟังก์ชัน ทุกที่ที่เรียกก็ได้ของใหม่หมด
3. **อ่านง่าย** ตั้งชื่อดีๆ อย่าง `get_grade` คนมาอ่านก็เดาได้เลยว่าทำอะไร ไม่ต้องไล่ดูโค้ดข้างในทั้งหมด

---

## parameter กับ argument: ส่งค่าเข้าไปให้ฟังก์ชันหน่อย

ฟังก์ชันแบบเมื่อกี้มันทำได้อย่างเดียวสิครับ ทักทายก็ทักได้แบบเดียว ของจริงเราอยากส่งค่าเข้าไปด้วย เช่น ทักคนละชื่อ ก็ต้องมีช่องรับค่านั่นแหละ

ตรงนี้มีศัพท์ 2 คำที่ชอบสลับกันครับ **parameter** คือตัวรอรับตอนเราสร้างฟังก์ชัน ส่วน **argument** คือค่าที่เราส่งเข้าไปตอนเรียกใช้ จำแบบนี้ก็ได้ครับ ตอนสร้างเรียก parameter ตอนใช้เรียก argument

<CodeOutput>

```python
def greet(name):  # name ตรงนี้คือ parameter รอรับค่า
    print("สวัสดีครับ", name)

greet("lynn")  # "lynn" ตรงนี้คือ argument ส่งเข้าไปจริงๆ
greet("มิ้น")
```

```text title="ผลลัพธ์"
สวัสดีครับ lynn
สวัสดีครับ มิ้น
```

</CodeOutput>

จะรับหลายค่าก็ได้ครับ แค่คั่นด้วยจุลภาค `,` แต่ต้องระวังเรื่องลำดับนิดนึง ค่าแรกจะเข้าตัวแรก ค่าที่สองเข้าตัวที่สอง สลับกันเมื่อไหร่งงทันที:

<CodeOutput>

```python
def introduce(name, age):
    print(f"{name} อายุ {age} ปี")

introduce("lynn", 25)
introduce(25, "lynn")  # สลับกันดูสิ ความหมายเพี้ยนเลย
```

```text title="ผลลัพธ์"
lynn อายุ 25 ปี
25 อายุ lynn ปี
```

</CodeOutput>

ถ้ากลัวสลับก็ระบุชื่อไปเลยก็ได้ครับ เรียกว่า keyword argument สลับลำดับได้ไม่เป็นไร:

```python
introduce(age=25, name="lynn")
```

### return: อยากได้ค่ากลับไปใช้ต่อ

ตรงนี้เป็นจุดที่หลายคนงงสุดครับ ระหว่าง `print` กับ `return`

`print` คือแค่ **โชว์บนจอ** ให้เราดูเฉยๆ ส่วน `return` คือ **ส่งค่ากลับ** ให้คนเรียกเอาไปทำอย่างอื่นต่อได้ แล้วพอเจอ `return` ปุ๊บ ฟังก์ชันจะหยุดตรงนั้นเลยครับ ไม่ทำต่อแล้ว

<CodeOutput>

```python
def add(a, b):
    return a + b  # ส่งผลบวกกลับไปให้คนเรียก

result = add(5, 3)  # result ก็จะได้ 8
print(result)
print(result + 10)  # เอาไปบวกต่อได้สบายๆ
```

```text title="ผลลัพธ์"
8
18
```

</CodeOutput>

ลองเทียบกับแบบที่ใช้แค่ `print` ดูครับ จะเห็นเลยว่าต่างกัน:

```python
def add_wrong(a, b):
    print(a + b)  # แค่โชว์ ไม่ได้ส่งอะไรกลับ

x = add_wrong(5, 3)
print(x)  # จะได้ None เพราะฟังก์ชันไม่ได้คืนอะไรให้เลย
# print(x + 10)  # บรรทัดนี้พังนะ None + 10 ทำไม่ได้
```

ทริคจำง่ายๆ ครับ **อยากโชว์ใช้ `print` อยากได้ค่าไปใช้ต่อใช้ `return`**

แล้วก็มีทริคเล็กๆ ที่ใช้บ่อยครับ คือเอา `return` มาตัดจบเร็วๆ จะได้ไม่ต้องซ้อน `if` เยอะ:

```python
def is_adult(age):
    if age < 18:
        return False  # เจอเด็กก็จบเลย ไม่ต้องมี else
    return True
```

---

## ค่า default กับ scope

### default parameter: ตั้งค่าเผื่อไว้กันลืม

บางที parameter มันมีค่าที่เราใช้บ่อยๆ อยู่แล้ว เราตั้งเผื่อไว้ได้เลยครับ ถ้าคนเรียกไม่ส่งมา Python ก็ใช้ค่านี้ให้เอง สะดวกดี

<CodeOutput>

```python
def greet(name="เพื่อน"):
    print("สวัสดีครับ", name)

greet()          # ไม่ส่งอะไรมา ก็ได้ "เพื่อน"
greet("lynn")    # ส่งมาก็ใช้ค่าที่ส่งมา
```

```text title="ผลลัพธ์"
สวัสดีครับ เพื่อน
สวัสดีครับ lynn
```

</CodeOutput>

มีที่ต้องระวังนิดเดียวครับ **ตัวที่มี default ต้องอยู่หลังตัวที่ไม่มี** ไม่งั้น Python มันงง ไม่รู้จะจับคู่ยังไง

```python
def greet(greeting, name="เพื่อน"):  # แบบนี้ถูก
    print(greeting, name)

# def greet(name="เพื่อน", greeting):  # แบบนี้พังนะ SyntaxError
```

### scope: ตัวแปรแต่ละตัวมีที่ของมัน

**scope** พูดง่ายๆ ก็คือ "ตัวแปรตัวนี้ใช้ได้ถึงตรงไหน" ครับ ตัวที่สร้างข้างในฟังก์ชันจะใช้ได้แค่ข้างในนั้น เรียกว่า **local** ส่วนตัวที่สร้างข้างนอกจะใช้ได้ทุกที่ เรียกว่า **global** ลองดูตัวอย่างนี้ครับ:

<CodeOutput>

```python
name = "lynn"  # สร้างข้างนอก ใช้ได้ทุกที่

def change():
    name = "มิ้น"  # ถึงชื่อจะซ้ำ แต่คนละตัวกับข้างนอกนะ ใช้ได้แค่ในนี้
    print("ในฟังก์ชัน:", name)

change()
print("นอกฟังก์ชัน:", name)
```

```text title="ผลลัพธ์"
ในฟังก์ชัน: มิ้น
นอกฟังก์ชัน: lynn
```

</CodeOutput>

ทำไมต้องแยกแบบนี้? ลองคิดดูครับ ถ้าทุกฟังก์ชันแก้ตัวแปรข้างนอกได้หมด โปรแกรมใหญ่ๆ ขึ้นมาจะไล่ไม่เจอเลยว่าใครแอบมาเปลี่ยนค่าตอนไหน บั๊กกระจายแน่นอน

เอาแบบที่ผมแนะนำสำหรับตอนนี้นะครับ จำแค่นี้พอ:
- อยากเอาค่าข้างนอกเข้าไปใช้ในฟังก์ชัน **ส่งผ่าน parameter** ดีกว่าดึงมาใช้ตรงๆ
- อยากได้ผลออกมาข้างนอก **ส่งผ่าน return** ดีกว่าสร้างตัวแปรข้างนอกในฟังก์ชัน
- เขียนแบบนี้โค้ดจะสะอาด เทสต์ง่าย ย้ายไปใช้ที่อื่นก็ง่ายครับ

---

## List — เก็บของหลายชิ้นตามลำดับ

ก่อนหน้านี้ตัวแปรนึงเก็บได้ค่าเดียวใช่ไหมครับ แต่ของจริงเราต้องเก็บหลายค่า เช่น คะแนนทั้งห้อง รายชื่อผลไม้ `list` นี่แหละคำตอบ ครอบด้วย `[ ]` สมาชิกคั่นด้วยจุลภาค แล้วเวลาจะหยิบใช้ก็จิ้มด้วย **index** ซึ่งเริ่มนับจาก `0` นะครับ ไม่ใช่ `1` ตรงนี้โดนกันทุกคน ผมก็โดนมาแล้ว

<CodeOutput>

```python
scores = [85, 70, 92]
print(scores[0])   # ตัวแรกคือ index 0 นะ
print(scores[1])   # ตัวที่สองคือ index 1
print(len(scores)) # len() เอาไว้นับว่ามีกี่ตัว
```

```text title="ผลลัพธ์"
85
70
3
```

</CodeOutput>

`list` มันยืดหยุ่นครับ เพิ่มทีหลัง ลบทีหลังได้ มีเครื่องมือติดมาให้ใช้เลย:

<CodeOutput>

```python
scores = [85, 70, 92]
scores.append(60)  # ต่อท้ายไปอีกตัว
print(scores)

scores.remove(70)  # ลบค่าที่เจอตัวแรกออก
print(scores)

print(92 in scores)  # เช็คว่ามีค่านี้ไหม ได้ True/False
```

```text title="ผลลัพธ์"
[85, 70, 92, 60]
[85, 92, 60]
True
```

</CodeOutput>

แล้วของคู่กันกับ list ก็คือ `for` ที่เราเรียนใน Part 2 นั่นแหละครับ วน list ได้ตรงๆ เลย ไม่ต้องมานั่งนับ index เองให้ปวดหัว:

<CodeOutput>

```python
scores = [85, 70, 92]

for s in scores:
    print("คะแนน:", s)
```

```text title="ผลลัพธ์"
คะแนน: 85
คะแนน: 70
คะแนน: 92
```

</CodeOutput>

จุดที่พลาดกันบ่อยๆ:
- มี 3 ตัว (index 0-2) แต่ดันไปจิ้ม `scores[3]` อันนี้ได้ `IndexError` แน่นอนครับ ทางแก้คือเช็ค `len()` ก่อน หรือวนด้วย `for` แทนไปเลยง่ายกว่า
- `append` มันเพิ่มทีละตัวนะครับ ถ้าอยากเพิ่มหลายตัวใช้ `extend` หรือเอา `+` ต่อกันก็ได้ เช่น `scores + [60, 50]`

---

## Dict — เก็บแบบมีชื่อกำกับ อ่านรู้เรื่อง

ถ้า list เหมาะกับ "ของหลายชิ้นแบบเดียวกันเรียงกัน" `dict` จะเหมาะกับ "ข้อมูลชุดเดียวกันแต่มีหลายช่อง" ครับ เช่น นักเรียน 1 คนมีทั้งชื่อทั้งคะแนน ถ้าเก็บเป็น `["lynn", 85]` คนมาอ่านก็งงว่าอะไรคืออะไร สู้เก็บเป็น `{"name": "lynn", "score": 85}` ไม่ได้ เห็นปุ๊บรู้ปั๊บเลย

`dict` ครอบด้วย `{ }` ข้างในเป็นคู่ `key: value` เวลาจะใช้ก็เรียกด้วย key ไม่ต้องสนลำดับครับ:

<CodeOutput>

```python
student = {"name": "lynn", "score": 85}

print(student["name"])   # เรียกด้วย key
print(student["score"])

student["grade"] = "A"   # ยังไม่มี key นี้ก็คือเพิ่มใหม่ มีแล้วก็คืออัปเดต
student["score"] = 90
print(student)
```

```text title="ผลลัพธ์"
lynn
85
{'name': 'lynn', 'score': 85, 'grade': 'A'}
```

</CodeOutput>

ปัญหาคลาสสิกเลยคือไปอ่าน key ที่ไม่มี โปรแกรมจะพังด้วย `KeyError` ครับ กันไว้ได้ 2 วิธี:

<CodeOutput>

```python
student = {"name": "lynn", "score": 85}

# วิธีที่ 1: ใช้ .get() ถ้าไม่มีก็ได้ None ไม่พัง หรือใส่ค่ากันเหนียวเองก็ได้
print(student.get("grade"))
print(student.get("grade", "ยังไม่ตัดเกรด"))

# วิธีที่ 2: วนด้วย .items() ได้ทั้ง key ทั้ง value พร้อมกันเลย
for key, value in student.items():
    print(key, "=", value)
```

```text title="ผลลัพธ์"
None
ยังไม่ตัดเกรด
name = lynn
score = 85
```

</CodeOutput>

สรุปสั้นๆ ให้จำคู่กันครับ:
- ของหลายชิ้นแบบเดียวกัน เรียงๆ กัน → ใช้ **`list`** เช่น `[85, 70, 92]`
- ข้อมูลชุดเดียวมีหลายช่อง แต่ละช่องมีความหมาย → ใช้ **`dict`** เช่น `{"name": "lynn", "score": 85}`
- มีหลายชุด แต่ละชุดมีหลายช่อง → เอา **list ครอบ dict** ซึ่งเดี๋ยวเราจะทำกันในตัวอย่างสุดท้ายพอดีเลย

---

## ลองรวมกัน: โปรแกรมตัดเกรดทั้งห้อง

ได้เวลารวมร่างครับ เอาทุกอย่างมาใช้ด้วยกัน — `list` เก็บนักเรียนหลายคน `dict` เก็บข้อมูลแต่ละคน `function` เก็บเกณฑ์ตัดเกรดไว้ที่เดียว:

<CodeOutput>

```python
def get_grade(score):
    # ฟังก์ชันนี้มีหน้าที่เดียว: รับคะแนนมา คืนเกรดกลับไป
    if score >= 80:
        return "A"
    elif score >= 70:
        return "B"
    elif score >= 60:
        return "C"
    else:
        return "F"

students = [
    {"name": "lynn", "score": 85},
    {"name": "มิ้น", "score": 72},
    {"name": "โอม", "score": 55},
]

for s in students:          # s คือข้อมูลนักเรียนทีละคน
    grade = get_grade(s["score"])  # ดึงคะแนนส่งเข้าไป ได้เกรดกลับมา
    print(f"{s['name']} ได้ {s['score']} คะแนน เกรด {grade}")
```

```text title="ผลลัพธ์"
lynn ได้ 85 คะแนน เกรด A
มิ้น ได้ 72 คะแนน เกรด B
โอม ได้ 55 คะแนน เกรด F
```

</CodeOutput>

มาไล่ดูทีละท่อนกันครับว่าทำอะไรบ้าง:
1. `def get_grade(score)` ตรงนี้คือที่เก็บเกณฑ์ที่เดียวเลย วันหลังอยากเปลี่ยนเช่น A ต้อง 85 ก็แก้ตรงนี้ที่เดียวจบ ไม่ต้องไล่แก้ทั้งไฟล์
2. `students = [...]` คือ list ของ dict ครับ แต่ละก้อนคือข้อมูลนักเรียน 1 คน อยากเพิ่มใครก็เติม dict ไปอีกก้อนแค่นั้นเอง
3. `for s in students` วนทีละคน ไม่ต้องนับ index เองให้เมื่อย
4. `get_grade(s["score"])` ดึงคะแนนออกมาจาก dict ด้วย key `"score"` แล้วโยนเข้าฟังก์ชัน ได้เกรดกลับมาทาง `return`
5. `f"..."` คือ f-string จาก Part 2 นั่นแหละ เอาตัวแปรมาแปะในข้อความด้วย `{ }` ได้เลย สะดวกมาก

เทียบกับ Part 2 ที่ตัดได้ทีละคนด้วย `if` ยาวๆ ตอนนี้สั้นกว่า อ่านง่ายกว่า แถมรองรับทั้งห้องโดยไม่ต้องแก้โลจิกเลยครับ นี่แหละข้อดีของการแยกโค้ดเป็นฟังก์ชัน + เลือกที่เก็บข้อมูลให้ถูก

ลองเอาไปเล่นต่อเองดูนะครับ:
- เพิ่มเพื่อนอีก 2 คนใน list แล้วลองรันดู
- ลองเปลี่ยนเกณฑ์ใน `get_grade` แล้วดูว่าผลทั้งห้องเปลี่ยนตามโดยไม่ต้องแตะที่อื่นเลย
- ลองเขียนฟังก์ชัน `is_pass(score)` ที่คืน `True/False` แล้วเอามาใช้คู่กับ `get_grade` ดูครับ

---

## สรุป

Part 3 นี้เราได้ของสำคัญครบเลยครับ:
- **ฟังก์ชัน** ด้วย `def` แยกโค้ดเป็นก้อน เขียนรอบเดียวเรียกได้หลายรอบ แก้ที่เดียวจบ
- **parameter/argument** เอาไว้ส่งค่าเข้า **`return`** เอาไว้ส่งค่าออก อย่าสลับกับ `print` ที่แค่โชว์นะ
- **default parameter** ตั้งค่าเผื่อไว้กันลืม **scope** ก็แค่จำว่าในกับนอกคนละตัวกัน ส่งผ่าน parameter/return จะสะอาดสุด
- **`list`** เก็บของหลายชิ้นตามลำดับ จิ้มด้วย index เริ่มจาก 0 เพิ่มด้วย `append` วนด้วย `for`
- **`dict`** เก็บแบบ key-value เรียกด้วย key ใช้ `.get()` กันพัง วนด้วย `.items()`
- **list ครอบ dict + function** คือท่าที่ใช้จริงบ่อยมาก จำโปรแกรมตัดเกรดวันนี้ไว้ดีๆ ได้ใช้แน่ครับ

ใน Part 4 เราจะไปต่อกันที่ **การอ่าน/เขียนไฟล์ กับดัก error ด้วย try/except** ครับ จะได้เขียนโปรแกรมที่เซฟข้อมูลไว้ใช้รอบหน้าได้จริง ไม่ต้องมานั่งกรอกใหม่ทุกครั้งที่รัน

**ติดตามต่อใน Part 4 นะครับ**
