Python with BirdsCoding freedom

คำสั่งวนลูปในภาษาไพธอน (Loops in Python)#

20 minutes

วัตถุประสงค์

หลังจากทำทำแล็บ นศ.จะสามารถ

  • เขียนคำสั่งวนลูป (Loop) ในภาษาไพธอน (for-loop & while-loop) ได้

Ref:

คำสั่งวนลูป (Loop)#

Range#

ในบางครั้งเราอาจต้องการรันโค้ดเดิมซ้ำหลายๆ ครั้ง เราเรียกว่า การวนลูปหรือการวนซ้ำ (Loop)

คำสั่งที่สามารถควบคุมโปรแกรมให้ทำงานซ้ำๆ ในเงื่อนไขที่กำหนดและเพิ่มความสามารถในการเขียนโปรแกรมมี 2 คำสั่ง คือ for Loop และ while Loop

ก่อนที่เราจะไปเขียนคำสั่ง for Loop เรามาดูฟังก์ชัน range( ) กันก่อน เนื่องจากในภาษา Python เรามักจะใช้ฟังก์ชัน range( ) กับคำสั่ง for Loop ในการวนอ่านค่าออบเจ็คของตัวเลข (ดู Note)

ฟังก์ชัน range( ) เป็น built-in ฟังก์ชัน** ใช้สำหรับสร้างออบเจ็คของตัวเลขที่มีการเรียงลำดับและไม่สามารถเปลี่ยนค่าได้ (Immutable sequence type)

เช่น ตัวเลขเรียงลำดับ (เพิ่มขึ้นที่ละ 1) 0, 1, 2, 3, 4, 5 หรือตัวเลขเรียงลำดับแบบก้าวกระโดด 3, 6, 9, 12 มีทั้งไปทาง + และ - ตามระบบเส้นจำนวนจริง (ดังนั้น 2, 1, 0, -1, -2 ก็ได้)

เราสามารถเรียกฟังก์ชัน range( ) ได้ 3 วิธี ดังนี้

  1. range(stop) รับหนึ่งอาร์กิวเมนต์

  2. range(start, stop) รับสองอาร์กิวเมนต์

  3. range(start, stop, step) รับสามอาร์กิวเมนต์

โดยที่อาร์กิวเมนต์ทั้ง start, stop, step ต้องเป็นเลขจำนวนจริง

วิธีที่ 1 รับหนึ่งอาร์กิวเมนต์ : จะเป็นชุดตัวเลขที่เริ่มจาก 0 (เสมอ) แล้วเพิ่มทีละ 1 จนถึง stop-1 (ไม่รวมเลขที่เป็น stop) เช่น range(9): 0, 1, 2, 3, …, 7, 8 (ทั้งหมด 9 (9-0) ตัวเลข)

วิธีที่ 2 รับสองอาร์กิวเมนต์ : จะเป็นชุดตัวเลขที่เริ่มจากเลข start แล้วเพิ่มทีละ 1 จนถีง stop-1 (ไม่รวมเลขที่เป็น stop) เช่น range(1, 9): 1, 2, 3, …, 7, 8 (ทั้งหมด 8 (9-1) ตัวเลข)

วิธีที่ 3 รับสามอาร์กิวเมนต์ : จะเป็นชุดตัวเลขที่เริ่มจากเลข start แล้วเพิ่มทีละ step … (แต่ไม่รวมเลข stop) เช่น range(1, 9, 2): 1, 3, 5, 7 (ทั้งหมด 4 ตัวเลข)

** ตามข้อเท็จจริงแล้ว range ไม่ได้เป็นฟังก์ชัน แต่เป็นคอนสตรัคเตอร์ (Constructor)*1 Ranges

รายการของ Built-in functions in Python3 : https://docs.python.org/3/library/functions.html

# Use the range

range(10)
range(0, 10)

NOTE:

range(10) กับ range(0,10) ได้ผลลัพธ์เหมือนกัน (เนื่องจากดีฟอลต์เริ่มที่ 0)

ค่าส่งกลับของฟังก์ชัน range() ไม่ใช่ list แต่เป็น….

# range() is a type in Python! 
type(range(3))
range

Note

อาร์กิวเมนต์ที่ส่งให้ฟังก์ชัน range() ต้องเป็นเลขจำนวนเต็ม (int) เสมอ

# Try calling range() with a float and see what happens
range(10.3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [3], line 2
      1 # Try calling range() with a float and see what happens
----> 2 range(10.3)

TypeError: 'float' object cannot be interpreted as an integer

*เราสามารถใช้คอนสตรัคเตอร์ (Constructor)1 list( ) แปลง range( ) ให้เป็น List ได้

Syntax :

list([iterable*2])

*1 คอนสตรัคเตอร์ (Constructor) ในภาษาอื่น ๆ (C++ , JAVA หรือ C#) จะหมายถึงเมธอดที่มีชื่อเดียวกันกับคลาส แต่ในภาษา Python จะหมายถึง ฟังก์ชันที่ทำงานเมื่อมีการเรียกใช้งาน class โดยอยู่ในฟังก์ชัน __init__ เพื่อกำหนดค่าเริ่มต้นให้กับออบเจ็กต์ที่ถูกสร้างจากคลาส คอนสตรัคเตอร์จะทำงานอัตโนมัติเมื่อมีการสร้างอ็อปเจ็คขึ้นมา

*2Iterable คือ อ็อบเจกต์ใดๆ ที่เราสามารถทำการวนซ้ำกับมันได้ เช่น range, lists, dictionaries, tuples หรือแม้แต่ strings ก็เป็น Iterable (ข้อมูลประเภท collection/containers เป็น Iterable)

(iterable กับ iterator ต่างกัน)

# How range works in Python?

# empty range
print(list(range(0)))

# using range(stop)
print(list(range(10)))

# using range(start, stop, step)
print(list(range(1, 10, 2)))

# using range(start, (neg)stop, (neg)step)
print(list(range(1, -10, -2)))

เข้าถึงสมาชิกใน range( ) ได้โดยใช้เลขดัชนีอาร์เรย์เหมือน Lists

# Access items in a range() by index, just as you would with a list
range(10)[-1]
9
range(10)[0:4]
range(0, 4)

คำสั่ง for Loop#

คำสั่ง for loop เป็นคำสั่งวนซ้ำที่ใช้ควบคุมการทำงานซ้ำๆ ในจำนวนรอบที่แน่นอน

รูปแบบของการใช้งานคำสั่ง for loop ในภาษา Python

For Syntax:

for <var> in <iterable>:
    <statement(s)>

โดย in เป็นโอเปอร์เรตอร์ (Membership operators) สำหรับตรวจสอบว่าค่าหรือตัวแปร < var > อยู่ใน < iterable > หรือไม่ ถ้าเป็นจริง (True) ก็จะทำการรันโค้ดบรรทัดใหม่ที่เยื้องเข้าไปหลัง colon ใน Block-for-loop (บล็อกของโค้ด-for-loop) โดยจะทำการรันวนซ้ำๆ จนกว่าเงื่อนไข ( < var> in < iterable > ) จะเป็นเท็จ (False)

ถ้าเราต้องการรัน 10 ครั้ง เราจะเขียนโค้ด ในกรณีภาษา C

for (i = 0; i < 10; i++){
    <Block-for-loop>
}

ในกรณีภาษา Python

for i in range(10):
    <Block-for-loop>

Membership operators#

in และ not in เป็น Membership operators ใน Python

ตามชื่อของโอเปอร์เรตอร์ in ใช้ตรวจสอบว่าค่าหรือตัวแปรหรือออบเจ็กต์นั้นๆ เป็นส่วนประกอบหรือเป็นสมาชิกใน Iterable (เช่น ข้อมูลประเภท Container (string, list, tuple, set และ dictionary) ฯลฯ) หรือไม่ ส่วนโอเปอร์เรตอร์ not in ก็ทำงานตรงกันข้ามกับโอเปอร์เรตอร์ in

Operator Meaning Example
in True if value/variable is found in the sequence 5 in x
not in True if value/variable is not found in the sequence 5 not in x

Python Operators

ตัวอย่างการใช้โอเปอร์เรตอร์ in แสดงได้ดังต่อไปนี้

Note: for ของไพธอนจะต่างจากภาษาอื่นเล็กน้อย กล่าวคือ แทนที่จะใช้ตัวนับซึ่งเป็นตัวเลขในการวนรอบ ไพธอนกลับใช้ข้อมูลที่มีลำดับ เช่น สตริงก์ ลิสต์ หรือทูเปิล แทน
# Example: Membership operators in Python
x = 'Hello world'
y = {1:'a',2:'b'}

# Output: True
print('H' in x)

# Output: True
print('hello' not in x)

# Output: True
print(1 in y)

# Output: False ***
print('a' in y)
True
True
True
False

ถ้าต้องการเขียนภาษาซีให้แสดงตัวเลขจาก 0, 1,…ถึง 9 โค้ดจะเป็นดังนี้

#include <stdio.h>

int main() {
    int i;
    for(i=0;i<10;i++){
        printf("%d \n",i);
    }    
    return 0;
}

ลองเขียนโค้ดภาษาไพธอน โดยใช้คำสั่ง range ดู

# For loop
# Write your code below. Don't forget to press Shift+Enter to execute the cell
Click here for the solution
for i in range(10):
    print(i)
    

ถ้าเราต้องการลูปข้อมูลใน List (การ Iterate List) เช่น พิมพ์ทุกสมาชิกที่อยู่ใน List ออกหน้าจอ เราสามารถทำได้หลายวิธี

วิธีที่ 1: ใช้ฟังก์ชัน range( )

# For loop example

dates = [1982,1980,1973]
N = len(dates)
for i in range(N):
    print(dates[i])     
1982
1980
1973

โค้ดที่เยื้องเข้าไปจะถูกรัน N ครั้ง ในแต่ละครั้งที่รัน ค่าของ i จะเพิ่มขึ้นทีละ 1 และรันคำสั่ง print( ) ดังแสดงในรูป

เขียนให้สั้นลง ได้ดังนี้

# For loop example

dates = [1982,1980,1973]

for i in range(len(dates)):
    print(dates[i])     
1982
1980
1973

แต่! ในกรณีของ List ซึ่งเป็นอ็อบเจกต์ iterable เราสามารถเข้าถึงสมาชิกได้โดยตรง

วิธีที่ 2: ใช้โอเปอเรเตอร์ in เข้าถึงโดยตรง

# Exmaple of for loop, loop through list

for year in dates:  
    print(year)   
1982
1980
1973

ในกรณีนี้ จำนวนครั้งในการรันคำสั่ง print( ) จะเท่ากับจำนวนสมาชิกที่อยู่ใน dates และในการรันแต่ละครั้ง ตัวแปร year จะทำงานเหมือนกับ dates[i] ในโค้ดก่อนหน้า

นอกจากนี้ เรายังสามารถเข้าถึงเลขดัชนี (Index) และค่า (Value) ของสมาชิกของ List ได้โดยใช้ฟังก์ชัน enumerate( )

วิธีที่ 3: ใช้ฟังก์ชัน enumerate( )

ฟังก์ชัน enumerate( ) เป็น Built-in function ใช้สำหรับแจกแจงค่า index และข้อมูลที่อิงกับ index (Value) ในรูปแบบ Tuple (Index,Value) โดยต้องใช้กับข้อมูลชนิด list

ฟังก์ชัน enumerate( ) ส่งค่ากลับในรูปแบบของ Enumerate Object

# Enumerate Object

dates = [1982,1980,1973]

# Enumerate() method adds a counter to an iterable and returns it 
# in a form of enumerating object. 
enumerate(dates)

# This enumerated object can then be used directly for loops or 
# converted into a list of tuples using the list() function.
list(enumerate(dates))  
[(0, 1982), (1, 1980), (2, 1973)]
# The enumerate() function allows you to loop over an iterable object and 
# keep track of how many iterations have occurred.
# For loop example

dates = [1982,1980,1973]

for i,date in enumerate(dates):
    print('Index: ', i,', Value: ', date)
    
Index:  0 , Value:  1982
Index:  1 , Value:  1980
Index:  2 , Value:  1973

เราสามารถเปลี่ยนค่าของสมาชิกที่อยู่ใน List ได้

# Use for loop to change the elements in list

squares = ['red', 'yellow', 'green', 'purple', 'blue']

for i in range(0, 5):
    print("Before square[", i, '] is',  squares[i])
    squares[i] = 'white'
    print("After square[", i, '] is',  squares[i])
Before square[ 0 ] is red
After square[ 0 ] is white
Before square[ 1 ] is yellow
After square[ 1 ] is white
Before square[ 2 ] is green
After square[ 2 ] is white
Before square[ 3 ] is purple
After square[ 3 ] is white
Before square[ 4 ] is blue
After square[ 4 ] is white
# Loop through the list and iterate on both index and element value

squares=['red', 'yellow', 'green', 'purple', 'blue']

for i, square in enumerate(squares):
    print('Index: ', i,', Value: ', square)
Index:  0 , Value:  red
Index:  1 , Value:  yellow
Index:  2 , Value:  green
Index:  3 , Value:  purple
Index:  4 , Value:  blue

การใช้คำสั่ง for เขียนโปรแกรมภายในลิสต์ (List Comprehension)#

artists = ["Michael Jackson", "SPRITE x GUYGEEGEE", "Whitney Houston", "BNK48", "Maroon 5", "Bee Gees"]

newlist = [] # empty list

for x in artists:
    if "a" in x:
        newlist.append(x)

print(newlist)
['Michael Jackson', 'Maroon 5']

เราสามารถเขียนแทนด้วยบรรทัดเดียวได้

# Using list Comprehension

artists = ["Michael Jackson", "SPRITE x GUYGEEGEE", "Whitney Houston", "BNK48", "Maroon 5", "Bee Gees"]

newlist = [x for x in artists if "a" in x]

print(newlist)
['Michael Jackson', 'Maroon 5']
เมื่อใช้ list comprehension ไม่ต้องมี : หลังคำสั่ง for และหลังคำสั่ง if

คำสั่ง while loop#

คำสั่ง for loop เป็นคำสั่งวนซ้ำที่ใช้ควบคุมการทำงานซ้ำๆ ในจำนวนรอบที่แน่นอน แต่ถ้าเราไม่รู้จำนวนรอบล่ะ?

คำสั่ง while loop เป็นคำสั่งใช้ควบคุมโปรแกรมให้ทำงานบางอย่างซ้ำๆ ในขณะที่เงื่อนไขของลูปนั้นยังคงเป็นจริงอยู่

รูปแบบของการใช้งานคำสั่ง while loop ในภาษา Python

While Syntax:

while <expr>:
    <statement(s)>

เราสร้างลูปด้วยคำสั่ง while และตามด้วยเงื่อนไข <expr> ซึ่งเป็นเงื่อนไขที่จะให้โปรแกรมทำงาน โดยโปรแกรมจะตรวจสอบเงื่อนไข <expr> ก่อน ถ้าเงื่อนไขเป็นจริง (True) ก็จะทำการรันคำสั่งภายใน Block-while-loop ซ้ำๆ จนกว่าเงื่อนไขจะเป็นเท็จ (False) ซึ่งถือเป็นการสิ้นสุดการทำงานของลูป

สมมติว่าเราต้องการพิมพ์ข้อมูลปีที่อยู่ใน List dates ออกมาซ้ำๆ และให้หยุดเมื่อข้อมูลเป็นปี 1973 เราสามารถเขียนบล็อกของโค้ดได้ต่อไปนี้

# While Loop Example

dates = [1982, 1980, 1973, 2000]

i = 0
year = dates[0]

while(year != 1973):    
    print(year)
    i = i + 1
    year = dates[i]
    

print("It took ", i ,"repetitions to get out of loop.")
1982
1980
It took  2 repetitions to get out of loop.

โปรแกรมจะทำงานวนซ้ำๆ จนกว่าเงื่อนไขจะเป็น False เป็นการสิ้นสุดการทำงานของลูป ตามรูป

คอลัมน์พิเศษ: การใช้วิธีนิวตันในการคำนวณหาคำตอบของสมการ#

สมการ \(f(x) = 0\) เราสามารถหาคำตอบของสมการนี้ได้โดยวิธีง่ายๆ ดังนี้ สมมุติให้กราฟ \(y = f(x)\) มีกราฟดังในรูป

ขั้นตอนแรกคือเลือกจุดเริ่มต้น \(x_o\) โดยการสุ่ม จากนั้นทำการลากเส้นสัมผัสกับกราฟที่จุด \((x_o, f(x_o))\) ให้ตัดกับแกน \(x\) สมมุติว่าได้จุดตัดที่ \(x_1\) จากนั้นให้ \(x_1\) เป็นจุดเริ่มต้น ทำการลากเส้นสัมผัสกับกราฟให้ตัดกับแกน \(x\) อีกครั้งโดยจะทำวนอย่างนี้ไปเรื่อยๆก็จะได้รูปคล้ายๆกับฟันเลื่อนดังรูป จากรูปเราสามารถคาดการณ์ได้ว่า ค่าของ \(x\) ที่ได้จะเข้าใกล้คำตอบของสมการการ ค่า \(x_i\) หาได้จากค่า \(x_{i-1}\) ตามสมาการ

\[ x_i=x_{i-1}-\frac{f(x_i)}{f^{'}(x_i)} \]

ถ้าเขียนโปรแกรมให้มีการประมวลผลที่ดี ก็จะได้ค่าของ \(x\) ที่เข้าใกล้คำตอบของสมการ เราเรียกวิธีนี้ว่า Newton method

ตามหลักการของ Newton method ข้างต้น ถ้าหากเราเขียนโค้ดตาม flow chart ต่อไปนี้ แล้วรัน

จะเกิดปัญหาอะไรหรือไม่????????

ก่อนที่จะรันโค้ด ให้ลองคิดดูก่อน (ว่า จะเกิดปัญหาอะไรหรือไม่)

# Calculate the square root using Newton's Method
a = float(input(">>"))
x = a

while (x**2 != a) :
    print(x**2 - a)
    x = (x + a/x) / 2

print( "sqrt(",a,") =", x )

ถ้าแก้ใหม่เป็น

a = float(input(">>"))
x = a

error = 1e-10

while abs(x**2-a) > error:
    x = (x + a/x) / 2

print( "sqrt(",a,") =", x )
>> 5
sqrt( 5.0 ) = 2.236067977499978

คอลัมน์พิเศษ: หาค่าประมาณของ \(\pi\) ที่ดีกว่า 22/7#

from math import pi
pi-22/7
pi-355/113
-2.667641894049666e-07

The magic number: 113355

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
from math import pi
pi
22/7
3.141592653589793
3.142857142857143
from math import pi

error = 1e-6
n  = 22
d  = 7


while abs(pi-n/d) >= error :
    delN = abs(pi - (n+1)/d)
    delD = abs(pi - n/(d+1))

    if delN < delD :
        n = n + 1
    else :
        d = d + 1

print(n,"/",d,"=",n/d)
355 / 113 = 3.1415929203539825

[Exercise] For Loop & While Loop#

  1. จงใช้คำสั่งลูป for พิมพ์เลขจำนวนนับที่อยู่ระหว่าง -5 กับ 5 โดยใช้ฟังก์ชัน range

# Write your code below and press Shift+Enter to execute
  1. จงเขียนโค้ดแสดงสมาชิกที่อยู่ในลิส Genres=[ ‘rock’, ‘R&B’, ‘Soundtrack’, ‘soul’, ‘pop’] ออกหน้าจอ

# Write your code below and press Shift+Enter to execute
  1. ใช้คำสั่งลูป for พิมพ์สมาชิกที่อยู่ในลิส squares=[‘red’, ‘yellow’, ‘green’, ‘purple’, ‘blue’] ออกหน้าจอ

# Write your code below and press Shift+Enter to execute
  1. จงใช้คำสั่งลูป while แสดงค่าเรตติ้งของอัลบั้มที่เก็บอยู่ในลิส PlayListRatings. โดยกำหนดเงื่อนไขให้ออกจากลูปถ้าค่าเรตติ้งน้อยกว่า 6 และ PlayListRatings = [10, 9.5, 10, 8, 7.5, 5, 10, 10]

# Write your code below and press Shift+Enter to execute
  1. จงใช้คำสั่ง while loop ก็อปปี้สตริง ’orange’ ที่อยู่ในลิส squares เป็นลิสใหม่ที่ชื่อ new_squares. กำหนดให้ออกจากลูปและหยุดการก็อปปี้ถ้าค่าที่อยู่ในลิสไม่ใช่ ’orange’

# Write your code below and press Shift+Enter to execute

squares = ['orange', 'orange', 'purple', 'blue ', 'orange']
new_squares = []

คำสั่ง break และคำสั่ง continue (break and continue Statements)#

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

คำสั่ง continue เป็นคำสั่งที่ใช้ร่วมกับคำสั่งวนลูปเช่นเดียวกับคำสั่ง break เมื่อมีการประมวลผลคำสั่ง continue โปรแกรมจะหยุดการทำงานที่จุดนั้น แล้วกลับไปเริ่มวนรอบใหม่ถัดไป ดังนั้น คำสั่ง continue จึงมักถูกกำกับด้วยเงื่อนไขพิเศษบางอย่างเพื่อให้ไปตรวจสอบเงื่อนไขใหม่ ดังแสดงในรูป

![](images/break_continue.png0

# a script demonstrates the break statement

n = 5
while n > 0:
    n -= 1
    if n == 2:
        break
    print(n)
    
print('Loop ended.')
4
3
Loop ended.
# a script demonstrates the continue statement

n = 5
while n > 0:
    n -= 1
    if n == 2:
        continue
    print(n)
    
print('Loop ended.')
4
3
1
0
Loop ended.

คำสั่ง pass ( pass Statements)#

คำสั่ง pass เป็นคำสั่งที่ไม่ทำอะไรเลย แต่มีไว้เผื่อเวลาเราวางโครงสร้างโค้ดไว้แล้ว แต่ยังไม่ได้เขียนท่อนนั้น ก็บรรจุคำสั่งนี้ไว้เพื่อให้สามารถทดสอบการรันได้ เช่น

while True:
    pass # Busy-wait for keyboard interrupt

Infinite Loop (Endless Loop)#

การวนลูปที่ไม่มีที่สิ้นสุด

กดคีย์เพื่อขัดจังหวะ (KeyboardInterrupt): กด Control-C หรือ DEL (Interactive Mode), กด i สองครั้ง (Jupyter Nootbook)

Warning

กดคีย์เพื่อขัดจังหวะ (KeyboardInterrupt): กด Control-C หรือ DEL (Interactive Mode), กด i สองครั้ง (Jupyter Nootbook)

# A while loop that theoretically never ends
# You can press 'I' twice to interrupt the kernel!
# or try 'Ctrl-m i' to interrupts the kernel. (press letter 'i' after Ctrl-m) 

while True:
    print('foo')

“Everybody should learn to program a computer, because it teaches you how to think”” - Steve Jobs 1995


Author#

S.C.

Change Log#

Date

Version

Change Description

08-08-2021

0.1

First edition