Python Slicing และ Indexing



เราแตะเรื่อง index กับ slicing มาบ้างแล้วในบท string และ list บทนี้จะรวบให้ครบและเจาะจุดที่คนสับสนบ่อย เพราะ slicing เป็นเครื่องมือที่ใช้ตลอดเวลาใน Python

Indexing: เข้าถึงทีละตัว

ทั้ง string, list, tuple ใช้หลักเดียวกัน นับตำแหน่งจาก 0

word = "PYTHON"
#       012345
#      -654321   (ติดลบ)

print(word[0])    # P
print(word[3])    # H
print(word[-1])   # N
print(word[-2])   # O

เลขติดลบมีไว้เพื่อไม่ต้องคำนวณความยาวเอง word[-1] คือตัวสุดท้ายเสมอ ไม่ว่าข้อความจะยาวแค่ไหน

Slicing: ตัดเป็นช่วง

รูปแบบเต็มคือ [start:stop:step]

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(nums[2:5])    # [2, 3, 4]

กฎสำคัญ: รวม start แต่ไม่รวม stopnums[2:5] เอาตำแหน่ง 2, 3, 4 ไม่เอา 5 คิดง่าย ๆ ว่า stop - start = จำนวนสมาชิกที่ได้ (5 – 2 = 3 ตัว)

ละ start หรือ stop ได้

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(nums[:4])     # [0, 1, 2, 3]     ตั้งแต่ต้นถึงก่อนตำแหน่ง 4
print(nums[6:])     # [6, 7, 8, 9]     ตั้งแต่ตำแหน่ง 6 ถึงท้าย
print(nums[:])      # [0, 1, ..., 9]   ทั้งหมด (ก๊อปลิสต์)

ใช้เลขติดลบ

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(nums[-3:])    # [7, 8, 9]     สามตัวสุดท้าย
print(nums[:-2])    # [0, 1, ..., 7]  ทุกตัวยกเว้นสองตัวท้าย
print(nums[-5:-2])  # [5, 6, 7]

step: กระโดดทีละกี่ก้าว

ตัวเลขที่สามคือระยะก้าว

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(nums[::2])    # [0, 2, 4, 6, 8]    ทุกตัวที่ตำแหน่งคู่
print(nums[1::2])   # [1, 3, 5, 7, 9]    ทุกตัวที่ตำแหน่งคี่
print(nums[2:8:3])  # [2, 5]

กลับลำดับด้วย step ติดลบ

[::-1] เป็นสำนวนมาตรฐานสำหรับกลับลำดับ

word = "PYTHON"
print(word[::-1])   # NOHTYP

nums = [1, 2, 3, 4, 5]
print(nums[::-1])   # [5, 4, 3, 2, 1]

เช็คว่าข้อความเป็น palindrome (อ่านหน้าหลังเหมือนกัน) ได้ในบรรทัดเดียว

def is_palindrome(text):
    return text == text[::-1]

print(is_palindrome("นาน"))     # True
print(is_palindrome("python"))  # False

Slicing ไม่เคย error เรื่องขอบเขต

ต่างจาก indexing ตรง ๆ ที่เกินขอบเขตแล้ว error แต่ slicing จะให้เท่าที่มี

nums = [1, 2, 3]

print(nums[10])     # IndexError!
print(nums[1:100])  # [2, 3]  ไม่ error
print(nums[50:60])  # []      ไม่ error

Slice assignment: แก้ลิสต์เป็นช่วง

กับลิสต์ (ไม่ใช่ string หรือ tuple) เรากำหนดค่าให้ทั้ง slice ได้

nums = [1, 2, 3, 4, 5]

nums[1:3] = [20, 30, 40]
print(nums)   # [1, 20, 30, 40, 4, 5]

nums[:2] = [0]
print(nums)   # [0, 30, 40, 4, 5]

ก๊อปลิสต์ด้วย slice

lst[:] สร้างลิสต์ใหม่ที่มีสมาชิกเหมือนเดิม แก้ตัวใหม่ไม่กระทบตัวเก่า (แก้ปัญหา b = a ที่พูดถึงในบท list)

a = [1, 2, 3]
b = a[:]
b.append(4)
print(a)   # [1, 2, 3]
print(b)   # [1, 2, 3, 4]

ตัวอย่างรวม: แบ่งข้อมูลเป็นหน้า (pagination)

items = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
page_size = 3

total_pages = (len(items) + page_size - 1) // page_size

for page in range(total_pages):
    start = page * page_size
    end = start + page_size
    print(f"หน้า {page + 1}: {items[start:end]}")

ผลลัพธ์:

หน้า 1: ['A', 'B', 'C']
หน้า 2: ['D', 'E', 'F']
หน้า 3: ['G', 'H', 'I']
หน้า 4: ['J']

ตัวอย่างรวม: ดึงชื่อไฟล์กับนามสกุล

filename = "report_2026_final.pdf"

dot = filename.rfind(".")
name = filename[:dot]
ext = filename[dot + 1:]

print(name)   # report_2026_final
print(ext)    # pdf

เช็คความเข้าใจก่อนข้ามบท

  • ใช้ start:stop:step เพื่อดึงข้อมูลบางช่วงได้
  • จำได้ว่า index ติดลบนับจากท้าย และ stop ไม่ถูกรวม
  • ลองกลับข้อความจากหลังมาหน้าด้วย slicing

สรุป

  • Indexing เริ่มที่ 0, ติดลบนับจากท้าย, เกินขอบเขตแล้ว error
  • Slicing [start:stop:step] รวม start ไม่รวม stop, ละส่วนไหนก็ได้, ไม่ error เรื่องขอบเขต
  • [::-1] กลับลำดับ, [:] ก๊อปลิสต์
  • กับลิสต์ยังกำหนดค่าให้ slice ได้ (nums[1:3] = [...])

จบช่วงโครงสร้างข้อมูล บทต่อไปเข้าสู่เรื่องฟังก์ชัน การสร้างเครื่องมือของตัวเองไว้เรียกใช้ซ้ำ