ตัววนซ้ำ (Iterators) ในภาษาไพธอน
บทความนี้อธิบายเกี่ยวกับตัววนซ้ำในไพธอน
YouTube Video
ตัววนซ้ำ (Iterators) ในภาษาไพธอน
ภาพรวม
ในไพธอน ตัววนซ้ำ (iterator) เป็นกลไกพื้นฐานสำหรับประมวลผลสมาชิกของคอลเลกชันเช่น list, tuple และ dictionary ทีละตัว
ตัววนซ้ำ (Iterator) คืออะไร?
ตัววนซ้ำคือ วัตถุที่สามารถคืนค่าสมาชิกทีละตัวได้ ในไพธอน วัตถุจะถือว่าเป็นตัววนซ้ำถ้ามีเงื่อนไขต่อไปนี้ครบสองข้อ:
- มีเมธอด
__iter__()ซึ่งคืนค่าตัวเอง - มีเมธอด
__next__()ซึ่งคืนค่าสมาชิกถัดไป เมื่อไม่มีข้อมูลจะคืนค่าอีก จะส่งข้อผิดพลาดStopIteration
1iterator = iter([1, 2, 3])
2print(next(iterator)) # 1
3print(next(iterator)) # 2
4print(next(iterator)) # 3
5# print(next(iterator)) # StopIteration occurs- ในโค้ดนี้ ฟังก์ชัน
iter()ถูกใช้ในการแปลงลิสต์ให้เป็นอิเทอเรเตอร์ และฟังก์ชันnext()ถูกใช้ในการดึงและแสดงแต่ละองค์ประกอบทีละรายการ
ข้อแตกต่างจาก Iterable
อิตเทอราเบิล (Iterable) คือวัตถุที่มีเมธอด __iter__() และสามารถใช้งานในลูป for ได้ ลิสต์และทูเพิลเป็นตัวอย่างของอิตเทอราเบิล
1nums = [10, 20, 30]
2it = iter(nums) # Get an iterator from the iterable
3print(next(it)) # 10- โค้ดนี้เป็นตัวอย่างของการรับอิเทอเรเตอร์จากอิเทอเรเบิล เช่น ลิสต์ และดึงองค์ประกอบตามลำดับโดยใช้
next()
วิธีตรวจสอบ:
1from collections.abc import Iterable, Iterator
2
3nums = [10, 20, 30]
4it = iter(nums)
5
6print(isinstance(nums, Iterable)) # True
7print(isinstance(nums, Iterator)) # False
8print(isinstance(it, Iterator)) # True- โค้ดนี้ยืนยันว่า
numsเป็นอิเทอเรเบิลแต่ไม่ใช่อิเทอเรเตอร์ ในขณะที่itที่ได้มาจากiter(nums)เป็นอิเทอเรเตอร์
ความสัมพันธ์ระหว่างลูป for กับตัววนซ้ำ
ลูป for ในไพธอนทำงานภายในดังนี้:
1nums = [1, 2, 3]
2iterator = iter(nums)
3while True:
4 try:
5 value = next(iterator)
6 print(value)
7 except StopIteration:
8 break- ดังที่แสดง ลูป
forใช้ตัววนซ้ำโดยอัตโนมัติเมื่อวนซ้ำข้อมูล
การสร้างตัววนซ้ำแบบกำหนดเอง
คุณสามารถสร้างตัววนซ้ำแบบกำหนดเองได้โดยใช้คลาส
1class Countdown:
2 def __init__(self, start):
3 self.current = start
4
5 def __iter__(self):
6 return self
7
8 def __next__(self):
9 if self.current <= 0:
10 raise StopIteration
11 value = self.current
12 self.current -= 1
13 return value
14
15for num in Countdown(3):
16 print(num) # 3, 2, 1- โค้ดนี้กำหนดอิเทอเรเตอร์แบบกำหนดเองที่นับถอยหลังโดยใช้คลาส
Countdownและพิมพ์ตัวเลขตั้งแต่ 3 ถึง 1 ด้วยลูปfor
ข้อแตกต่างระหว่าง Iterators กับ Generators และสถานการณ์ที่เหมาะสมในการใช้งาน
เจเนอเรเตอร์ (Generator) มีหน้าที่คล้ายกับตัววนซ้ำ สามารถสร้างตัววนซ้ำได้อย่างกระชับและง่ายขึ้น
1def countdown(n):
2 while n > 0:
3 yield n
4 n -= 1
5
6for i in countdown(3):
7 print(i) # 3, 2, 1- โค้ดนี้กำหนดฟังก์ชันเจเนอเรเตอร์ที่นับถอยหลังโดยใช้
yieldและพิมพ์ตัวเลขตั้งแต่ 3 ถึง 1 ด้วยลูปfor
ความแตกต่างระหว่างตัววนซ้ำ (คลาส) และเจเนอเรเตอร์ (ฟังก์ชัน)
มีความแตกต่างดังต่อไปนี้ระหว่างอิเทอเรเตอร์ (คลาส) และเจเนอเรเตอร์ (ฟังก์ชัน):
| คุณสมบัติ | Iterator (คลาส) | Generator (ฟังก์ชัน) |
|---|---|---|
| การนิยาม | __iter__() + __next__() |
ฟังก์ชันที่ใช้ yield |
| การจัดการสถานะ | ต้องจัดการแอตทริบิวต์เอง | จัดการสถานะโดยอัตโนมัติ |
| ความอ่านง่าย | อาจซับซ้อน | เรียบง่ายและชัดเจน |
-
ความแตกต่างในการนิยาม ตัววนซ้ำถูกนิยามโดยการเขียนเมธอด
__iter__()และ__next__()ด้วยตนเอง ในทางตรงข้าม เจเนอเรเตอร์เป็นเพียงฟังก์ชันที่ใช้คีย์เวิร์ดyieldจึงทำให้โค้ดกระชับและเรียบง่ายกว่า -
ความแตกต่างในการจัดการสถานะ สำหรับตัววนซ้ำ คุณต้องจัดการสถานะและความคืบหน้าด้วยตนเองโดยใช้ตัวแปร แต่เจเนอเรเตอร์จะเก็บสถานะไว้ภายในโดยอัตโนมัติ ลดภาระในการจัดการ
-
ความอ่านง่ายของโค้ด ตัววนซ้ำมักจะซับซ้อนเพราะต้องมีหลายเมธอดและต้องจัดการสถานะเอง ในขณะที่เจเนอเรเตอร์ใช้ไวยากรณ์ง่าย ทำให้เข้าใจได้ง่ายแม้กระทั่งผู้เริ่มต้น
ไลบรารีมาตรฐานสำหรับใช้ตัววนซ้ำ: itertools
itertools เป็นไลบรารีมาตรฐานของไพธอนที่มีเครื่องมือทรงพลังสำหรับทำงานกับตัววนซ้ำ
1import itertools
2
3for x in itertools.count(10, 2): # 10, 12, 14, ...
4 if x > 20:
5 break
6 print(x)- มันยังมีฟังก์ชันอื่น ๆ เช่น
cycle,repeat,chain,islice, และtee
กรณีตัวอย่างการใช้งานตัววนซ้ำ
กรณีการใช้งานของอิเทอเรเตอร์ประกอบด้วยสิ่งต่อไปนี้:
- การอ่านไฟล์ทีละบรรทัด: อ่านข้อมูลทีละบรรทัดจากไฟล์โดยใช้ตัววนซ้ำ
- ประมวลผลข้อมูลด้วยหน่วยความจำอย่างมีประสิทธิภาพ: ประมวลผลข้อมูลปริมาณมากแบบเรียงลำดับทีละรายการ
- สร้างลำดับค่าที่ไม่มีที่สิ้นสุด: ใช้ฟังก์ชันอย่าง
itertools.count()
สรุป
- ตัววนซ้ำคือวัตถุที่สามารถดึงค่าถัดไปทีละค่าได้
- คุณสามารถสร้างตัววนซ้ำที่กำหนดเองได้ด้วยการกำหนด
__iter__()และ__next__() - ตัววนซ้ำจะถูกจัดการโดยอัตโนมัติผ่านลูป
forหรือใช้ฟังก์ชันnext() - การใช้เจเนอเรเตอร์หรือ
itertoolsช่วยให้ประมวลผลได้อย่างมีประสิทธิภาพมากขึ้น
ด้วยการใช้ตัววนซ้ำ คุณสามารถประมวลผลข้อมูลปริมาณมากทีละรายการอย่างประหยัดหน่วยความจำ จัดการสถานะได้ดีขึ้นและเพิ่มประสิทธิภาพของโปรแกรม
คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย