Iterator ใน Python เป็นวัตถุ (object) ที่อนุญาตให้เราทำการวนซ้ำ (iterate) ข้อมูล ซึ่งช่วยให้เราสามารถเข้าถึงข้อมูลภายในวัตถุนั้นทีละตัวได้โดยไม่จำเป็นต้องโหลดข้อมูลทั้งหมดในหน่วยความจำพร้อมกัน
คุณสมบัติของ Iterator
ใน Python สิ่งที่สามารถเป็น iterator ได้จะต้องมีสองอย่างคือ
- มีเมธอด
__iter__()ซึ่งจะคืนค่าตัว iterator ของตัวเอง - มีเมธอด
__next__()ซึ่งคืนค่าข้อมูลตัวถัดไป ถ้าไม่มีข้อมูลให้คืนค่าแล้วจะต้องโยนข้อยกเว้นStopIteration
การสร้าง Iterator ใน Python
การใช้งาน iterator จาก object ที่เป็น iterable
# ตัวอย่างที่ใช้ list (ซึ่งเป็น iterable object)
my_list = [1, 2, 3, 4]
my_iter = iter(my_list)
print(next(my_iter)) # ผลลัพธ์: 1
print(next(my_iter)) # ผลลัพธ์: 2ในตัวอย่างนี้ my_list เป็น iterable (เช่น list, tuple หรือ string) และ iter(my_list) จะสร้าง iterator จากมัน เมธอด next() จะคืนค่าข้อมูลถัดไปใน iterable
การสร้าง class ของตัวเองเพื่อเป็น Iterator
class MyNumbers:
def __iter__(self):
self.current = 1
return self
def __next__(self):
if self.current <= 5:
num = self.current
self.current += 1
return num
else:
raise StopIteration
# สร้าง iterator จาก class ที่สร้างเอง
my_numbers = MyNumbers()
my_iter = iter(my_numbers)
for num in my_iter:
print(num)ในตัวอย่างนี้ เราสร้าง class MyNumbers ที่กำหนดให้ตัวเองเป็น iterator โดยการมีเมธอด __iter__() และ __next__() เมธอด __next__() จะคืนค่าเลขถัดไปจนถึง 5 แล้วจึงโยนข้อยกเว้น StopIteration เพื่อหยุดการวนซ้ำ
การใช้งาน Generator (เป็นรูปแบบหนึ่งของ iterator)
Generator เป็นฟังก์ชันพิเศษที่ใช้ yield เพื่อคืนค่าครั้งละหนึ่งค่าทุกครั้งที่เรียก next() และจะจำสถานะการทำงานไว้จนกว่าจะถูกเรียกใช้งานอีกครั้ง
def my_generator():
for i in range(1, 6):
yield i
gen = my_generator()
for value in gen:
print(value)ในตัวอย่างนี้ ฟังก์ชัน my_generator จะคืนค่าแต่ละตัวในช่วง 1 ถึง 5 ด้วยคำสั่ง yield และสามารถใช้ในลูปได้โดยตรง
การประยุกต์ใช้งาน Iterator
การอ่านไฟล์ทีละบรรทัด เมื่อไฟล์ใหญ่เกินไป การโหลดไฟล์ทั้งหมดเข้าในหน่วยความจำอาจไม่เหมาะสม Iterator ช่วยให้เราสามารถอ่านไฟล์ทีละบรรทัด
with open('example.txt', 'r') as file:
for line in iter(file.readline, ''):
print(line.strip())การสร้างลำดับข้อมูลแบบไม่สิ้นสุด สามารถใช้ iterator ในการสร้างลำดับข้อมูลขนาดใหญ่หรือไม่มีที่สิ้นสุด เช่น ลำดับ Fibonacci
class Fibonacci:
def __iter__(self):
self.a, self.b = 0, 1
return self
def __next__(self):
fib = self.a
self.a, self.b = self.b, self.a + self.b
return fib
fib_seq = Fibonacci()
fib_iter = iter(fib_seq)
for _ in range(10):
print(next(fib_iter))Looping Through an Iterator
การ Looping Through an Iterator เป็นวิธีการใช้ iterator เพื่อวนซ้ำ (loop) ผ่านค่าที่อยู่ในวัตถุ (object) ทีละตัวอย่างมีประสิทธิภาพ โดยไม่จำเป็นต้องโหลดข้อมูลทั้งหมดเข้าในหน่วยความจำในครั้งเดียว
การทำงานเบื้องหลังของการ Looping Through an Iterator
- เมื่อเรานำ
iteratorมาใช้กับลูป (เช่นfor loopหรือwhile loop) Python จะทำงานดังนี้- Python จะเรียกใช้เมธอด
__iter__()เพื่อรับตัวiteratorของ object นั้น - จากนั้นจะเรียกใช้เมธอด
__next__()ของiteratorเพื่อรับค่าถัดไปในลำดับ - เมื่อถึงจุดที่ไม่มีค่าที่จะคืนอีก เมธอด
__next__()จะโยนข้อยกเว้นStopIterationซึ่งเป็นสัญญาณให้ลูปหยุดการทำงาน
- Python จะเรียกใช้เมธอด
การใช้งาน Iterator กับ For Loop
for loop เป็นวิธีการทั่วไปที่สุดในการวนซ้ำผ่าน iterator ตัวอย่างเช่น
# ตัวอย่างการใช้ for loop กับ iterator
my_list = [10, 20, 30]
my_iter = iter(my_list)
for value in my_iter:
print(value)ในตัวอย่างนี้ Python จะใช้เมธอด __next__() ภายในลูปเพื่อดึงค่าจาก my_iter ทีละค่า และพิมพ์ออกมา
ผลลัพธ์
10
20
30
การใช้งาน Iterator กับ While Loop
ในบางกรณี เราสามารถใช้ while loop เพื่อควบคุมการวนซ้ำผ่าน iterator ได้ด้วยการใช้ next() โดยตรงและจัดการ StopIteration ด้วย try-except เช่น
my_list = [1, 2, 3]
my_iter = iter(my_list)
while True:
try:
value = next(my_iter)
print(value)
except StopIteration:
breakในตัวอย่างนี้ while loop จะทำงานจนกว่า StopIteration จะเกิดขึ้น และใช้ try-except เพื่อจับข้อยกเว้นและหยุดลูปเมื่อ iterator ไม่มีค่าเหลือให้ดึงอีก
ผลลัพธ์
1
2
3
การทำงานของ Iterator ภายใน For Loop
เบื้องหลังของ for loop Python จะทำสิ่งต่อไปนี้
- สร้าง iterator ด้วยการเรียก
iter() - เรียก
next()ภายในลูปเพื่อดึงค่าจาก iterator - จับ
StopIterationเพื่อหยุดลูป
ตัวอย่างต่อไปนี้เป็นตัวอย่างการจำลองการทำงานภายใน for loop แบบเต็ม
my_list = [1, 2, 3]
my_iter = iter(my_list)
# จำลองการทำงานของ for loop
while True:
try:
value = next(my_iter)
print(value)
except StopIteration:
breakผลลัพธ์ที่ได้จะเหมือนกับการใช้ for loop โดยตรง
การใช้งานอื่น ๆ ในการวนซ้ำผ่าน Iterator
การประยุกต์ใช้กับไฟล์
เมื่อทำการอ่านไฟล์ทีละบรรทัด ไฟล์ใน Python สามารถถูกมองว่าเป็น iterator โดยสามารถวนซ้ำผ่านไฟล์ได้อย่างสะดวก
with open('example.txt', 'r') as file:
for line in file:
print(line.strip())การใช้งาน Generator กับ For Loop
Generator เป็นอีกหนึ่งรูปแบบของ iterator ที่ใช้สำหรับการสร้างลำดับข้อมูลที่มีขนาดใหญ่มากหรือไม่จำกัด ซึ่งทำงานร่วมกับ for loop ได้อย่างดี
def my_generator():
for i in range(1, 4):
yield i
gen = my_generator()
for value in gen:
print(value)ผลลัพธ์
1
2
3
StopIteration
StopIteration เป็นข้อยกเว้น (exception) ใน Python ที่ถูกใช้โดย iterator เพื่อส่งสัญญาณบอกว่าไม่มีข้อมูลเพิ่มเติมให้ดึงออกมาแล้ว ซึ่งมักจะเกิดขึ้นเมื่อ iterator ถูกเรียกใช้จนหมดข้อมูล เช่น ในการเรียกใช้เมธอด __next__() ของ iterator จนครบทุกค่า
ลักษณะการทำงานของ StopIteration
- เมื่อเราสร้าง iterator จากวัตถุที่เป็น iterable เช่น list, tuple, หรือ string จะมีการดึงค่าผ่านเมธอด
__next__()ซึ่งดึงข้อมูลทีละตัวจนกว่าจะไม่มีข้อมูลเหลือ - เมื่อ iterator ถูกใช้งานจนหมดข้อมูลแล้ว การเรียก
__next__()ครั้งถัดไปจะโยนข้อยกเว้นStopIterationออกมาเพื่อบอกให้หยุดการวนซ้ำ
ตัวอย่างการใช้งาน StopIteration ใน Iterator
ตัวอย่างง่าย ๆ การทำงานของ StopIteration ใน Python มีดังนี้
my_list = [1, 2, 3]
my_iter = iter(my_list)
# ใช้ next() เพื่อดึงค่าทีละตัว
print(next(my_iter)) # ผลลัพธ์: 1
print(next(my_iter)) # ผลลัพธ์: 2
print(next(my_iter)) # ผลลัพธ์: 3
# ถ้าเรียก next() อีกครั้งเมื่อไม่มีข้อมูล จะเกิด StopIteration
try:
print(next(my_iter))
except StopIteration:
print("No more items.")ในตัวอย่างนี้ เราสร้าง my_iter จาก list ที่มี 3 ค่า การเรียก next() 3 ครั้งแรกจะดึงค่ามาได้ตามลำดับ แต่เมื่อเรียกครั้งที่ 4 จะเกิด StopIteration เพราะไม่มีค่าเหลือใน iterator
ผลลัพธ์
1
2
3
No more items.
การใช้งาน StopIteration กับ for loop
เมื่อใช้ for loop กับ iterable object เช่น list หรือ generator Python จะจัดการข้อยกเว้น StopIteration ให้โดยอัตโนมัติ เราจึงไม่จำเป็นต้องใช้ try-except เอง
ตัวอย่าง
my_list = [1, 2, 3]
# for loop จะจัดการ StopIteration ให้อัตโนมัติ
for item in my_list:
print(item)ในเบื้องหลัง Python จะเรียกใช้ next() กับ iterator และหยุดลูปเมื่อเกิด StopIteration โดยที่เราไม่ต้องเขียนโค้ดจัดการข้อยกเว้นนี้ด้วยตัวเอง
ผลลัพธ์
1
2
3
การใช้ StopIteration ใน Generator
ในฟังก์ชัน generator ค่าจะถูกส่งคืนด้วย yield จนกว่าจะไม่มีค่าเพิ่มเติม ในกรณีนี้ Python จะโยนข้อยกเว้น StopIteration โดยอัตโนมัติเมื่อ generator หมดค่าที่จะส่งคืน
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
for value in gen:
print(value)เมื่อ generator ส่งคืนค่าครบแล้วจะหยุดทำงานโดยไม่ต้องจัดการ StopIteration ด้วยตัวเอง Python จะจัดการให้ภายใน for loop
ผลลัพธ์
1
2
3
