Tutorial

For-Loop ใน Python ทำงานยังไง?

By Arnon Puitrakul - 17 กุมภาพันธ์ 2022

For-Loop ใน Python ทำงานยังไง?

เรื่องที่น่าสนใจ และ หลาย ๆ คนมองข้ามไปคือเรื่องพื้นฐานมาก ๆ อย่าง For-Loop หรือ Loop อื่น ๆ อย่าง While Loop เราก็ใช้กันบ่อยนะ ใช้กันแทบจะทุกโปรแกรมเลย แต่เราเคยสงสัยกันมั้ยว่า เบื้องหลังของมัน มันทำงานยังไงถึงออกมาให้เราใช้งานได้แบบนี้ โดยของที่ถือว่าเป็น Foundation ในเรื่องนี้คือ Iterable และ Iterator

Iterable

Iterable ถ้าจะให้อธิบายง่าย ๆ คือ Object ที่มีความสามารถในการ Iterate หรือง่ายกว่านั้นอีก คือมันสามารถ Return สมาชิกของมันในแต่ละรอบได้ ถ้าเราเขียน Python มา พวกนี้มันก็คืออะไรก็ตามที่เราสามารถ Loop ใส่มันได้นั่นเอง

>>> iter("Hello World")
<str_iterator object at 0x102b09e20>

>>> iter([1,2,3,4])
<list_iterator object at 0x102b26070>

>>> iter(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

ตัวอย่างเช่น String ใน Python มันก็จะประกอบด้วย Character หลาย ๆ ตัวต่อกัน การ Iterate ก็คือการที่มันพ่น Character ที่อยู่ใน String ออกมาในแต่ละรอบนั่นเอง ซึ่งถ้า Object ไหนที่เป็น Iterable Object เราสามารถยัดมันใส่ Function ที่ชื่อว่า iter() ได้ จากตัวอย่างสุดท้ายเราจะเห็นว่า มันไม่สามารถ Iterate ได้ เพราะ Integer ไม่ใช่ Iterable Object นั่นเอง

Iterator

>>> hello_iter = iter("Hello World")

>>> next(hello_iter)
'H'

>>> next(hello_iter)
'e'

ณ ตอนนี้เรามี Object ที่สามารถ Iterate ได้แล้ว ก็คือ Iterable แล้วถามว่า ใครจะที่จะเป็นคนไล่รันเอาค่าสมาชิกออกมา สิ่งนั้นก็คือ Iterator มองภาพง่าย ๆ ว่ามันเป็นเครื่องจักรที่เอาค่าออกมา จากใน iter() ตัวมันเอง มันก็ทำอะไรไม่ได้ แต่มันจะเริ่มโยนสมาชิกออกมาก็ต่อเมื่อเราเรียกอีกคำสั่งนึง นั่นคือ next()

>>> next(hello_iter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

แต่แน่นอนว่าจำนวนสมาชิกมันไม่ได้มีไม่อั้น มันมีจำกัด อย่างใน String "Hello World" ก็มีสมาชิก 11 ตัวด้วยกัน เมื่อเราเรียก next() ไปเรื่อย ๆ จนถึงครั้งที่ 12 ตัว Python จะดัน Exception ออกมาว่าเป็น StopIteration Exception ขึ้นมา ซึ่งเราสามารถเอา Try...Except มาจับได้

>>> list_iter = iter([1,2])
>>> next(list_iter)
1

>>> next(hello_iter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

เมื่อเรารัน Iterator เพิ่มเข้าไปอีกหนึ่งตัวในโปรแกรม เราจะเห็นว่า Iterator ก็ยังทำงานได้อย่างถูกต้อง โดยเอาอันสมาชิกตัวแรกออกมา และเมื่อเราเรียก Iterator ตัวก่อนหน้าที่มันเรียกจนหมดแล้ว มันก็ยังคงคืน Exception กลับมาเหมือนเดิม จากการทดลองนี้ เราได้ข้อสังเกตว่าแต่ละ Iterator มันก็จะมีการจัดการ State ของใครของมัน ไม่เกี่ยวกับส่วนกลางใด ๆ ทั้งสิ้น

เรื่องนี้เราสามารถอธิบายได้จากวิธีการสร้าง Iterable บน Class โดยที่ Class นั้น ๆ จะเป็น Iterable ได้ มันจะต้องมีการ Implement Dunder Method ที่ชื่อว่า __iter__ ลงไปด้วย แล้วเมื่อเราสร้างออกมาเป็น Object ไม่ว่าเราจะสร้างออกมากี่อัน แต่จะตัว มันก็จะมีการจัดการ State ในตัวของมันเอง เหมือนกับที่เราสามารถใส่ค่าใน Attribute ที่ไม่เหมือนกันได้นั่นเอง

How for-loop works?

หลังจากเราเข้าใจ Concept ของคำว่า Iterable และ Iterator แล้ว เรามาดูคำตอบกันว่าจริง ๆ แล้ว For-Loop เขาทำงานยังไงใน Python เราอยากให้ลองเอาสิ่งที่เราเล่าเมื่อกี้มาคิดดูก่อนว่า มันน่าจะทำอย่างไร ถึงออกมาเป็น For-Loop ได้...... โอเค เฉลย

ขั้นตอนของมันจริง ๆ คือ มันจะแปลง Iterable ให้เป็น Iterator ก่อนผ่านคำสั่ง iter() จากนั้น มันก็จะเรียก next() ของ Iterator ที่สร้างเอาไว้ ทำแบบนี้ไปเรื่อย ๆ จนกว่าจะได้ StopIteration ออกมา มันก็จะออกจาก Loop นั่นเอง อื้อ แค่นั้นเลย....

สรุป

วันนี้เรามาเล่าในหลังม่านการทำงานของ For-Loop ทั้งหลาย ซึ่งมันใช้ 2 ส่วนในการทำให้มันเกิดขึ้นได้คือ Iterable และ Iterator ทำงานเข้าด้วยกัน โดยที่ทั้ง 2 อย่างนี้มีความแตกต่างกัน คือ Iterable คือ Object ที่สามารถ Iterate ได้ ส่วน Iterator เป็นเหมือนเครื่องจักรในการพ่นค่าสมาชิกใน Iterable ออกมานั่นเอง เอาจริง ๆ แล้ว หลาย ๆ คนอาจจะมองว่ามันเป็นเรื่องที่ เออ รู้ทำไมอะ เราว่ามันทำให้เออรู้สึกว่า Python มันเป็นภาษาที่แปลกดีนะ มันใช้วิธีแบบนี้เพื่อให้มันเข้าใจได้ง่าย และ นำไปใช้ได้ง่าย

Read Next...

Multiprogramming, Multiprocessing และ Multithreading

Multiprogramming, Multiprocessing และ Multithreading

หลังจากที่เรามาเล่าเรื่อง malloc() มีคนอยากให้มาเล่าเรื่อง pthread เพื่อให้สามารถยัด Content ที่ละเอียด และเข้าใจง่ายในเวลาที่ไม่นานเกินไป เลยจะมาเล่าพื้นฐานที่สำคัญของคำ 3 คำคือ Multiprogramming, Multitasking, Multiprocessing และ Multithreading...

Synology NAS และ SSD Cache จำเป็นจริง ๆ เหรอ เหมาะกับระบบแบบใด

Synology NAS และ SSD Cache จำเป็นจริง ๆ เหรอ เหมาะกับระบบแบบใด

ใน Synology NAS มีความสามารถนึงที่น่าสนใจคือ การใช้ SSD เป็น Cache สำหรับระบบ ที่ทำให้ Performance ในการอ่านเขียน เร็วขึ้นกว่าเดิมมาก ๆ แน่นอนว่า เราลองละ วันนี้เราจะมาเล่าให้อ่านกันว่า หากใครคิดที่จะทำ มันเหมาะ หรือ ไม่เหมาะกับการใช้งานของเรา...

ฮาวทูย้าย Synology Add-on Package ไปอีก Volume

ฮาวทูย้าย Synology Add-on Package ไปอีก Volume

เรื่องราวเกิดจากการที่เราต้องย้าย Add-on Package ใน DSM และคิดว่าหลาย ๆ คนน่าจะต้องประสบเรื่องราวคล้าย ๆ กัน วันนี้เราจะมาเล่าวิธีการว่า เราทำยังไง เจอปัญหาอะไร และ แก้ปัญหาอย่างไรให้ได้อ่านกัน...

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

การใช้ Docker CLI ในการจัดการ Container เป็นท่าที่เราใช้งานกันทั่วไป มันมีความยุ่งยาก และผิดพลาดได้ง่ายยังไม่นับว่ามี Instance หลายตัว ทำให้เราต้องค่อย ๆ SSH เข้าไปทำทีละตัว มันจะดีกว่ามั้ย หากเรามี Centralised Container Managment ที่มี Web GUI ให้เราด้วย วันนี้เราจะพาไปทำความรู้จักกับ Portainer กัน...