while choice.lower() != "q":
____ทำสิ่งที่เราต้องการให้ loop ทำ
print "Thank you for using my program"
จากโครงสร้างที่ได้ ก็จะเห็นชัดว่า ตรงไหนเป็นส่วน ลูป ตรงไหนไม่อยู่ในลูป (บรรทัดสุดท้าย)
ปัญหาคือ code ที่ใช้รับค่าของ choice (ในคำสั่ง raw_input) อยู่ใน loop แต่เราเรียกใช้มันใน condition โปรแกรม python ก็จะโวยวายว่า เร��ใช้ variable โดยที่ยังไม่ได้กำหนดค่า
เราแก้ไขได้ง่ายๆ ด้วยการให้ค่า choice เป็นอะไรก็ได้ที่ไม่ใช่ q เพื่อให้เข้าไปใน loop รอบแรกได้ โดยไม่มีปัญหา เมื่อเข้าไปใน loop แล้ว โปรแกรมของเราก็จะถามค่า choice ตามปกติ pseudocode จึงออกมาเป็น
choice = ""
while choice.lower() != "q":
____ทำสิ่งที่เราต้องการให้ loop ทำ
print "Thank you for using my program"
แต่วิธีนี้ มีข้อเสียอยู่ คือ เมื่อเราใส่ q เพื่อออกจาก loop นอกจากโปรแกรมจะพิมพ์ขอบคุณที่ใช้งานแล้ว ยังพิมพ์โวยวายออกมาก่อนว่าให้เราใส่ค่า r/t/c/z เสียอีก ที่เป็นอย่างนี้ เพราะว่าตัว q ไม่อยู่ในเงื่อนไขของ if และ elif ที่เรามีอยู่ โปรแกรมจึงทำงานในส่วนที่เป็น else ที่พิมพ์ค่าเตือนผู้ใช้ออกมา
ทางแก้คือเพิ่ม elif ตัว q ลงไป ดังนี้
choice = ""
while choice.lower() != "q":
____ทำสิ่งที่เราต้องการให้ loop ทำ
____...
____elif choice.lower() == "q":
________pass
____else:
________print ....
print "Thank you for using my program"
อันนี้ จะเห็นว่าเราใช้ keyword ตัวหนึ่งชื่อ pass เพื่อบอก python ว่าไม่ต้องทำอะไร ผ่านไปเฉยๆ
แต่วิธีนี้ก็ยังมีข้อเสียอยู่ ���พราะเราเห็น code ที่ซ้ำซ้อนกันชัดเจน ก็คือ condition ที่เปรียบเทียบค่า choice สองที่ ตรง while condition และ if condition ดูไม่ดีเลย แถมยังต้องกำหนดค่า choice ก่อนเข้า while loop อีก
อันที่จริง เราควรจะกำหนดให้วนลูปไปเรื่อยๆ เมื่อผู้ใช้กด q จึงค่อยหลุดออกจากลูป (break from the loop) ซึ่งเราสามารถทำได้ด้วยการใช้ keyword break ดังนั้น pseudocode ที่ได้จึงเป็น
while True:
____ทำสิ่งที่เราต้องการให้ loop ทำ
____...
____elif choice.lower() == "q":
________break
____else:
________print ....
print "Thank you for using my program"
เพียงเท่านี้ เราก็ได้โปรแกรมที่ทำงานตามที่ต้องการ ข้อสังเกตคือตรง condition ของ while เราต้องการให้เป็นจริงเสมอ ซึ่งเราสามารถทำได้ด้วยการใช้ keyword True โดยไม่จำเป็นต้องสร้างค่าตัวแปรใดให้วุ่นวาย
แบบฝึกหัด
ปรับโปรแกรมให้ใช้ condition True และใช้ break แล้วลองเปรียบเทียบกับโปรแกรมที่เคยเขียนไว้ก่อนหน้านี้ (ส่วนใครที่เขียนแบบนี้แล้วตั้งแต่แรก ก็ขอแสดงความยินดีด้วยครับ คุณมาได้ถูกทางแล้ว)
List
เราเคยพูดถึงตัวแปรที่เก็บค่าต่างๆ เช่น ตัวเลขจำนวนเต็ม เลขทศนิยม และตัวอักษรกันมาแล้ว
ในกรณีของตัวแปรที่เก็บตัวอักษร (string) เราสามารถมองได้ในอีกรูปแบบหนึ่งว่าประโยคที่อยู่ในตัวแปรนั้น ประกอบด้วยตัวอักษรต่างๆ มาเรียงตัวกัน อย่างเช่น
test = "hello"
ตัวแปร test เก็บค่าลำดับของตัวอักษรไว้ 5 ตัวคือ h, e, l, l และ o
ตัวแปรที่มีลักษณะแบบลิสต์นี้ เราสามารถอ่านตัวอักษรที่อยู่ในลิสต์ได้ทีละตัว ด้วยการกำหนดค่า index โดยในโปรแกรม python ค่า index จะเริ่มนับจากเลข 0 ตัวแปร test มี 5 ตัวอักษร index จึงมีได้ตั้งแต่เลข 0 ถึง 4 โดยมีรูปแบบการใช้ index ดังนี้
ชื่อตัวแปร ตามด้วยเลข index ที่อยู่ในเครื่องหมายวงเล็บใหญ่
เพราะฉะนั้น ถ้าเราใช้คำสั่ง
>>> test = “hello”
>>> print test[0]
h
>>> print test[1]
e
>>> print test[4]
o
เราจะทราบได้อย่างไรว่า ลิสต์นั้นเก็บค่าไว้ทั้งหมดกี่ค่า คำตอบคือเราสามารถทำได้ ด้วยการใช้ฟังก์ชัน len()
>>> print len(test)
5
>>> test1 = “goodbye”
>>> print len(test1)
7
มาลองดูว่าเราจะใช้ list ให้เป็นประโยชน์กันได้อย่างไร สมมติว่าเรามี DNA sequence อยู่หนึ่งเส้น และเราต้องการนับจำนวน G และ C ว่ามีเท่าไหร่ คิดเป็นกี่เปอร์เซ็นต์ เราสามารถเขียนได้ดังนี้
1 dna = rawinput("Please enter DNA seq")
2 num_g = 0
3 num_c = 0
4 for base in dna:
5 if base == "G":
6 num_g += 1
7 if base == "C":
8 num_c += 1
9 print "number of G =", num_g
10 print "number of C =", num_c
11 print "total number of G+C =", num_g + num_c
12 print "percentage of G+C =" (num_g + num_c) * 100 / len(dna)
บรรทัดแรกเรารับสาย DNA จากผู้ใช้
บรรทัดที่ 2-3 เป็นการกำหนดตัวแปรเพื่อเก็บค่าที่เราต้องการนับ
บรรทัดที่ 4 เป็นของใหม่สำหรับครั้งนี้ครับ เป็นการวนลูปด้วยคำสั่ง for คำสั่ง for จะมีรูปแบบดังนี้ครับ คือ
for ตัวแปรที่จะใช้ในลูป in ตัวแปรลิสต์:
หลังจากนั้น ทุกอย่างที่อยู่ในย่อหน้าภายใต้คำสั่ง for จะสามารถนำตัวแปรที่จะใช้ในลูปไปใช้ได้
ครั้งแรกที่เข้าลูป ตัวอักษรตัวแรกในตัวแปร dna จะเข้าไปอยู่ในตัวแปร base สมมติว่าเราให้ข้อมูล AGTC
ตอนที่โปรแกรมถาม เข้าลูปครั้งแรก ตัวแปร base จะมีค่าเป็น A ซึ่งจะไม่ตรงตามเงื่อนไขของบรรทัดที่ 5 โปรแกรมจะกระโดดไปทำงานที่บรรทัดที่ 7 ซึ่งก็ไม่ตรงเงื่อนไขอีก จึงกระโดดไปทำงานถัดไป แต่ว่าไม่มีประโยคใดเหลืออีกแล้วในย่อหน้านี้ โปรแกรมจึงกลับไปที่บรรทัดที่ 4 ใหม่ของลูป for ตัวอักษรตัวถัดไปก็จะเข้าไปอยู่ในตัวแปร base ในกรณีจะเป็น G มาที่บรรทัดที่ 5 ก็จะพบว่าเงื่อนไขเป็นจริง โปรแกรมไปทำงานต่อที่บรรทัดที่ 6 เพิ่มค่าในตัวแปร num_g ให้กลายเป็น 1 แล้วก็ไปทำงานต่อที่บรรทัดที่ 7 ซึ่งไม่จริง จึงข้ามบรรทัดที่ 8 ไป แล้วกลับไปที่บรรทัดที่ 4 ใหม่ ได้ค่า T อยู่ในตัวแปร base แล้วทำงานวนเช่นนี้ไปเรื่อยๆ จนกระทั่งตัวแปร base มีค่า C เมื่อเสร็จสิ้นการทำงานในรอบนี้แล้ว เมื่อโปรแกรมกระโดดกลับไปทำงานที่บรรทัดที่ 4 พบว่าไม่มีค่าอะไรที่สามารถใส่ให้ตัวแปร base อีกแล้ว ก็จะเป็นการจบลูป โปรแกรมจะกระโดดไปทำงานที่บรรทัดที่ 9
บรรทัดที่ 9-12 เป็นการพิมพ์ผลลัพธ์
แบบฝึกหัด
เขียนโปรแกรมเพื่อตรวจสอบดูว่า DNA sequence ที่ผู้ใช้ใส่เข้ามานั้น valid หรือไม่ ซึ่งจะ valid ได้นั้น คือมี base ได้แค่ A, T, G , C หรือ N โดยที่ตัวอักษรจะเป็นตัวเล็กหรือใหญ่ก็ได้