ตอนแรกอยากเปิด blog ด้วยหัวข้อบันเทิงหน่อย ๆ แต่เผอิญได้ไอเดียเขียนเรื่องจริงจังระหว่างที่ทำงานอยู่ เลยได้เรื่องเขียนเกี่ยวกับของที่เจอบ่อยอย่าง for loop ในภาษา Python เสียหน่อยแล้วกัน
เคยสังเกตไหมว่า for statement ในภาษา Python จะใช้งานกับ iterable เพียงอย่างเดียวเท่านั้น ( ถ้างงกับประโยคนี้ อ่านข้ามไปก่อน ) ซึ่งจะแตกต่างจากหลาย ๆ ภาษาที่ for statement ที่มักใช้ประโยคเงื่อนไข ( conditional clause ) เพื่อตรวจสอบเงื่อนไขของการซ้ำลูป
ตัวอย่างการใช้งาน for statement ในภาษา C ซึ่งมี i < n
เป็น conditional clause
มือใหม่หลาย ๆ คนที่พยายามจะแปลงโค้ดข้างต้นเป็นภาษา Python อาจจะเขียนโค้ดในลักษณะดังต่อไปนี้
ข้อโต้แย้ง
“นี่ไง! ค่าของตัวแปร i
จะวิ่งไล่จาก 0
จนถึง len( A ) - 1
ซึ่งตรงตามเงื่อนไขเดียวกับโปรแกรมภาษา C++ ข้างบนเลย ( เมื่อกำหนดให้ n == len( A )
)”
หากเรากำลังพูดถึงการเปลี่ยนแปลงค่าของตัวเแปร i
ใน for statement เป็นหลักแล้ว คำกล่าวข้างต้นนี้ถูกต้องเลยทีเดียว
แต่ว่ากลไกของ for statement ของทั้งสองโปรแกรมนี้กลับแตกต่างกันโดยสิ้นเชิง
ก่อนที่เราจะพูดถึงกลไกการทำงานของ for statement ในภาษา Python เรามาปรับปรุงโค้ดข้างต้นเสียหน่อยดีกว่า ( ซึ่งผู้อ่านบางท่านอาจจะตั้งข้อสังเกตไว้แล้ว )
สังเกตว่า for statement ของเราในโค้ดนี้ v
จะแทนจำนวนแต่ละจำนวนในลิสต์ values
แต่ถ้าพิจารณาในละเอียดยิ่งขึ้น จะพบว่า values
ไม่จำเป็นต้องเป็นลิสต์ก็ได้ เช่น
ข้อโต้แย้ง
“เดี๋ยวนะ! ชักจะไปกันใหญ่แล้วหละ! แล้วทำไมโค้ดพวกนี้ถึงใช้กับค่าพวกนี้ได้ทั้งหมดเลยหละ?” ( ซึ่งหากลองย้อนกลับไปดูย่อหน้าแรก ๆ ของบทความนี้จะมีคำใบ้อยู่ )
ใช่แล้ว! ค่า values
เหล่านี้ล้วนแต่เป็น iterable ทั้งนั้น
หมายความว่าอย่างไร? เจตนารมณ์ของ iterable ในภาษา Python ก็คือวัตถุที่สามารถไล่เรียกดูสมาชิกแต่ละตัวได้
ไม่ว่าจะเป็น built-in data types อย่าง list
, set
, tuple
, dict
, etc.
หรือแม้แต่วัตถุอื่น ๆ เช่น range
หรือ generator expression และอื่น ๆ อีกมากมายเองก็เกิดเป็น iterable เช่นกัน
ในกรณีของ range( start, stop, step )
)
เองนั้นจะก่อเกิด iterable ที่มีค่าเริ่มจาก start
ไปจนถึงก่อนค่า stop
โดยนับกระโดดข้ามทีละ step
นั่นเอง
Python Iterable Specification
ในเชิงสเปกของภาษา Python นั้น วัตถุทุกชิ้นที่มี method ชื่อ
__iter__( self )
สร้างไว้ล้วนแต่เป็น iterable ทั้งสิ้น และเมื่อพูดถึง for statement แล้ว สิ่งแรกที่เกิดขึ้นเมื่อเริ่มรัน for statement ก็คือการเรียก method__iter__( self )
นี้นี่เองและเมื่อ method
__iter__( self )
ถูกเรียกใช้งาน มันจะรีเทิร์นค่าออกมาเป็นวัตถุอีกชิ้นหนึ่งซึ่งเรียกว่า iterator และเจ้า iterator นี่เองก็จะมี method ชื่อ__next__( self )
กำหนดไว้เช่นกัน ซึ่งทุก ๆ ครั้งที่เรียก method นี้ซ้ำ ๆ กันจึงจะคืนค่าสมาชิกแต่ละตัวตามลำดับหมายเหตุ: แนวคิดนี้มีความใกล้เคียงกับ
java.lang.Iterable
และjava.util.Iterator
สำหรับคนที่ใช้ภาษา Java มาก่อน
อย่าเพิ่งตกใจไป! ทั้ง method __iter__
และ __next__
ที่กล่าวมาข้างต้นนั้น
ผู้พัฒนาภาษา Python ได้นำไปสเปกเหล่านี้ใช้สร้าง data types
( อย่าง list
, set
, dict
, etc. )
หรือแม้แต่ range
ที่เราใช้งานกันอยู่ทุกวัน เพื่ออำนวยความสะดวกผู้ใช้ภาษา Python นั่นเอง
โดยส่วนใหญ่แล้ว เรามักไม่มีเหตุผลที่จะต้องเขียน method __iter__
หรือ __next__
เอง
เว้นเสียแต่เราจะประกาศสร้าง data type ขึ้นใช้งานเองเพิ่มเติม
นอกจากนี้ ยังมีวิธีต่าง ๆ มากมายที่ Python สร้างสรรค์ไว้ให้ผู้ใช้งานภาษา Python สามารถสร้าง iterable ขึ้นใช้งานเองได้
( อย่างเช่น Generator expression ดังที่ปรากฏข้างต้น ) โดยไม่ต้องไปยุ่มย่ามกับ
method __iter__
หรือ __next__
ในเมื่อเราทราบแล้วว่าโค้ดของฟังก์ชัน product
ข้างต้นนั้นสามารถใช้งานกับ iterable ของจำนวนเต็มในรูปแบบใด ๆ ก็ได้
เราจะปรับปรุงโค้ดนี้ให้ชัดเจนขึ้นว่า values
สามารถเป็น iterable แบบใดก็ได้ ซึ่งได้ผลดังนี้
เมื่อคุ้นชินกับการใช้งาน iterable สักพักหนึ่งแล้ว เราอาจจะเขียนฟังก์ชันเดียวกันนี้โดยใช้
functools.reduce
ซึ่ง consume iterable โดยตรง จึงได้เป็นโค้ดใหม่ดังนี้
เรายังมีคำถามที่ยังค้างคาอยู่คำถามหนึ่ง เราลองกลับไปดูโค้ดภาษา Python อันแรกของเราอีกครั้ง
จะพบว่า range
ที่ใช้ในโค้ดนี้จะเกิดเป็นวัตถุ iterable ที่มีสมาชิกเป็น
0
, 1
, …, len( A )-1
ตามลำดับ
จากนั้นเราจึงใช้จำนวนเหล่านั้นเพื่อ index ค่าภายในลิสต์ A
อีกทอดหนึ่ง
( สังเกตดี ๆ ว่าเรายังทำงานกับวัตถุที่เป็น iterable อย่างไม่มีข้อยกเว้น )
หวังว่าจะทำให้ผู้ใช้งาน Python หลายท่านมองเห็นภาพการทำงานของ for statement มากขึ้น ในบทความถัดไปจะพูดถึงการสร้าง iterable ด้วยวิธีต่าง ๆ และการนำมาใช้อำนวยความสะดวกในการเขียนโปรแกรม ซึ่งจะทำให้โค้ดของเราเข้าใจง่ายขึ้นตามไปด้วย
หมายเหตุ: มีรายละเอียดหลายประการที่เกี่ยวข้องกับหัวข้อนี้ ซึ่งผู้เขียนไม่สามารถกล่าวถึงได้ทั้งหมดภายในบทความเดียว จึงขออภัยมา ณ ที่นี้
อัปเดตเรื่องอื่น ๆ
สัปดาห์หน้ามีแพลนจะไปเที่ยวประเทศญี่ปุ่น อีเวนท์สำคัญก็คือคอนเสิร์ต Yuki Kajiura LIVE vol.#15 〜Soundtrack Special at the Amphitheater〜 ทั้งวันที่ 15 และ 16 มิถุนายนเลย และสัปดาห์ถัดไปก็ยังมีคอนเสิร์ตคล้าย ๆ กันของไทยด้วย คงจะมีรีวิวเร็ว ๆ นี้แน่นอน