2. การค้นหาข้อมลู แบบพบั ครึ่ง (Binary Search) หลกั การ: การคน้ หาขอ้ มลู แบบพบั ครง่ึ น้ไี ดถ้ กู คดิ คน้ ขน้ึ มาเพอ่ื แกไ้ ขขอ้ เสยี ของการคน้ หา ขอ้ มลู แบบลาดบั ในกรณที ข่ี อ้ มลู ทต่ี อ้ งการคน้ หาอยตู่ วั ทา้ ยๆ ของขอ้ มลู แต่ขอ้ กาหนดของการคน้ หา ขอ้ มลู แบบพบั ครง่ึ น้ีจะสามารถทางานได้กบั ขอ้ มลู ทม่ี กี ารจดั เรยี งเรยี บรอ้ ยแลว้ (เรยี งจากมากไปน้อย หรอื เรยี งจากน้อยไปหามากกไ็ ด)้ หลกั การคน้ หาขอ้ มลู แบบพบั ครง่ึ จะทางานโดยการแบง่ ขอ้ มลู ออกเป็น 2 ส่วน แลว้ นาค่ากลาง มาเปรยี บเทยี บกบั ขอ้ มลู (Key) ทต่ี อ้ งการคน้ หา ถา้ ขอ้ มลู ทท่ี าการคน้ หาเรยี งลาดบั จากน้อยไปหามาก เมอ่ื เปรยี บเทยี บแลว้ ขอ้ มลู ทต่ี อ้ งการคน้ หามคี ่ามากกว่า แสดงว่าตอ้ งไปคน้ หาขอ้ มลู ต่อในสว่ นขอ้ มลู ครง่ึ หลงั ต่อ จากนนั้ ใหน้ าขอ้ มลู ครง่ึ หลงั พบั ครง่ึ หาค่ากลางอกี ทาอยา่ งน้ไี ปเรอ่ื ยๆ จนกว่าจะไดข้ อ้ มลู ท่ี ตอ้ งการ ดงั ตวั อยา่ งต่อไปน้ี ลาดบั ที่ แสดงการจดั เรยี งลาดบั 1 12 34 5 6 123456 2 123 456 123 456 |(1+6)/2| 3 123 456 123 456 5 3<5 4 123 45 6 123 45 6 |(4+6)/2| 5 123 45 6 123 45 6 5 5=5 6 123 45 6 123 45 6 จากรปู ดา้ นบน แสดงการทางานของ Binary Search ซง่ึ สามารถเขยี นโปรแกรมไดด้ งั น้ี Program Example 17.10: Binary Search 1 def binarySearch(data, key): 2 min = 0 3 max = len(data) - 1 4 5 while True: ห น้ า 431
6 if max < min: 7 return -1 8 m = (min + max) // 2 9 if data[m] < key: 10 min = m + 1 11 elif data[m] > key: 12 max = m - 1 13 else: 14 return m + 1 15 16 data = [1, 2, 3, 4, 5, 6, 7, 8, 9] 17 print(\"Data source = \", data) 18 print(\"Would like to search the 8 number.\") 19 position = binarySearch(data, 8) 20 print(\"The position of the 8 number is \", position) ผลลพั ธท์ เ่ี กดิ ขน้ึ จากการรนั โปรแกรมดงั น้ี Data source = [1, 2, 3, 4, 5, 6, 7, 8, 9] Would like to search the 8 number. OUTPUT The position of the 8 number is 8 การทางานของการคน้ หาขอ้ มลู แบบน้ี จะทาการรบั คา่ ขอ้ มลู (Key) สาหรบั คน้ หาแลว้ นาไปคน้ หากบั ขอ้ มลู ทเ่ี กบ็ อยใู่ นลกั ษณะพบั ครง่ึ ทาใหป้ ระสทิ ธภิ าพดกี วา่ แบบ Sequential Search สาหรบั วธิ กี ารน้ี สามารถสรุปประสทิ ธภิ าพในการคน้ หาไดเ้ ป็น 3 กรณี คอื 1. กรณที ด่ี ที ส่ี ดุ โปรแกรมทาการเปรยี บเทยี บขอ้ มลู เพยี ง 1 ครงั้ เท่านนั้ ถา้ ขอ้ มลู ทต่ี อ้ งการ คน้ หาอยใู่ นตาแหน่งทพ่ี บั ครง่ึ แลว้ พบในครงั้ แรก ฉะนนั้ ค่า BigO = O(1) 2. กรณที แ่ี ยท่ ส่ี ดุ โปรแกรมทาการเปรยี บเทยี บขอ้ มลู จานวน log(n) ครงั้ ฉะนนั้ ค่า BigO = O(log(n)) 3. กรณเี ฉลย่ี ทวั่ ไป โปรแกรมทาการเปรยี บเทยี บขอ้ มลู ประมาณ log(n) ครงั้ จบบทท่ี 17 ห น้ า 432
บทท่ี 18 ปกิณกะโปรแกรมม่ิง (Miscellaneous Programming) ในบทน้เี ป็นบทสดุ ทา้ ยของภาคท่ี 3 ซง่ึ เป็นบททผ่ี เู้ ขยี นไดร้ วบรวมเทคนิคการเขยี นโปรแกรม เพอ่ื แกป้ ัญไขหาต่างๆ ดว้ ยภาษาไพธอนไว้ หรอื พดู อยา่ งรวบรดั คอื เป็นการเกบ็ ตกหวั ขอ้ ทไ่ี มไ่ ดก้ ลา่ ว ไวใ้ นบทท่ี 1 ถงึ 17 นนั่ เอง เน่อื งจากเน้อื หาในบทน้ีบางสว่ นไมเ่ ขา้ กลุ่มกบั เน้อื หาในบทต่างๆ ทก่ี ล่าว มาแลว้ แต่กไ็ มส่ ามารถตดั ทง้ิ เน้อื หาในบทน้ไี ด้เชน่ กนั เพราะว่าเป็นเน้อื หาทม่ี คี วามสาคญั และมี ประโยชน์อยา่ งมากต่อการเขยี นโปรแกรม จงึ เรยี กช่อื บทน้วี ่า ปกณิ กะโปรแกรมมงิ่ (การเขยี นโปรแกรม เบด็ เตลด็ ) ซง่ึ จะเป็นบททผ่ี สมผสานเน้อื หาทห่ี ลากหลายเขา้ ไวด้ ว้ ยกนั โดยแยกเป็นหวั ขอ้ ๆ ดงั น้ี 1. วนั และเวลา (Date/Time) ไพธอนใชโ้ มดลู time เพ่อื ประมวลผลเกย่ี วกบั วนั และเวลาของระบบ โดยเวลาเรม่ิ ตน้ นบั ตงั้ แต่ เวลาเทย่ี งคนื ของวนั ท่ี 1 เดอื นมกราคม 1970 (Julian day) เป็นตน้ มา ซง่ึ รปู แบบของวนั เวลาจะแสดง อยใู่ นรปู แบบของเลขจานวนจรงิ (floating-point) มหี น่วยวดั เป็นวนิ าที เมธอดทส่ี าคญั ของโมดลู time คอื time() เมธอดดงั กลา่ วจะคนื ค่ากลบั มาเป็นเลขจานวนจรงิ ทเ่ี รมิ่ ตน้ นบั มาตงั้ แต่ 12:00am, January 1, 1970 ดงั ตวั อยา่ ง Program Example 18.1: time() method 1 import time # import the time module 2 3 dateAndTime = time.time() 4 print(\"Date and Time since 12:00am, January 1, 1970:\", dateAndTime) ผลลพั ธท์ เ่ี กดิ ขน้ึ จากการรนั โปรแกรมดงั น้ี ห น้ า 433
Date and Time since 12:00am, January 1, 1970: 1395544330.215419 OUTPUT จากตวั อยา่ งโปรแกรมดา้ นบนแสดงวนั และเวลาปัจจบุ นั ของระบบ (Current system time) โดยเวลา ดงั กลา่ วจะมรี ปู แบบเป็นเลขจานวนทศนิยม บรรทดั ท่ี 1 โปรแกรมนาเขา้ โมดลู time เพ่อื เรยี กใชง้ าน ฟังกช์ นั หรอื เมธอดทท่ี างานเกย่ี วกบั เวลาเขา้ มาทางานในโปรแกรม บรรทดั ท่ี 3 เรยี กใชเ้ มธอด time() ซง่ึ จะคนื ค่าเวลาปัจจบุ นั ของเครอ่ื งโดยมรี ปู แบบเลขทศนิยม ใหก้ บั ตวั แปร dataAndTime บรรทดั ท่ี 4 แสดงผลวนั และเวลาดงั กลา่ วบนจอภาพ เมธอด time() จะเกบ็ ขอ้ มลู เป็นชนิดทพั เพลิ ประกอบไปดว้ ย 9 ฟิลดค์ อื ตาแหน่ง ฟิ ลด์ ข้อมลู 0 tm_year: เกบ็ ขอ้ มลู ปี ค.ศ. มี 4 หลกั (Year) 2014 1 tm_mon: เกบ็ ขอ้ มลู เดอื น มกราคม – ธนั วาคม (Month) 1 - 12 2 tm_mday: เกบ็ ขอ้ มลู วนั ท่ี (Day) 1 - 31 3 tm_hour: เกบ็ ขอ้ มลู ชวั่ โมง (Hour) 0 - 23 4 tm_min: เกบ็ ขอ้ มลู นาที (Minute) 0 - 59 5 tm_sec: เกบ็ ขอ้ มลู วนิ าที (Second) 0 - 61 6 tm_wday: เกบ็ ขอ้ มลู วนั ในสปั ดาห์ (วนั จนั ทร์ = 0) 0-6 7 tm_yday: เกบ็ ขอ้ มลู วนั ใน 1 ปี 1 - 366 8 tm_isdst: เกบ็ ขอ้ มลู Daylight Savings Time (DST) -1, 0, 1 สาหรบั โมดลู time มเี มธอดทส่ี าคญั เชน่ time.localtime() สาหรบั แสดงขอ้ มลู วนั เวลาปัจจบุ นั ในรปู แบบ ทพั เพลิ , เมธอด time.asctime() แสดงวนั เวลาทผ่ี ใู้ ชง้ านสามารถอ่านไดง้ า่ ยๆ ดงั ตวั อยา่ งโปรแกรมท่ี 18.2 Program Example 18.2: localtime(), asctime() method 1 import time; 2 3 localtime = time.localtime(time.time()) 4 print (\"Local current time :\", localtime) 5 localtime = time.asctime(time.localtime(time.time())) 6 print (\"Local current time :\", localtime) ผลลพั ธท์ เ่ี กดิ ขน้ึ จากการรนั โปรแกรมดงั น้ี Local current time : time.struct_time(tm_year=2014, tm_mon=3, tm_mday=23, tm_hour=12, tm_min=30, tm_sec=58, tm_wday=6, OUTPUT tm_yday=82, tm_isdst=0) Local current time : Sun Mar 23 12:30:58 2014 บรรทดั ท่ี 3 เรยี กใชเ้ มธอด localtime() เพอ่ื แสดงโครงสรา้ งของวนั เวลา เช่น tm_year=2014 หมายถงึ ปี ค.ศ. 2014, tm_mon หมายถงึ เดอื นมนี าคม เป็นตน้ บรรทดั ท่ี 5 เรยี กใชเ้ มธอด asctime() เพอ่ื แสดงวนั เวลาทผ่ี ใู้ ชง้ านสามารถทาความเขา้ ใจไดโ้ ดยงา่ ย เช่น Sun Mar 23 12:30:58 2014 ห น้ า 434
ในโมดลู time มเี มธอดทถ่ี ูกใชง้ านบ่อยครงั้ ไดแ้ ก่ time.ctime() ทาหน้าทแ่ี ปลงวนั เวลาทเ่ี ป็น ทศนิยมเป็นสตรงิ ของวนั เวลาปัจจบุ นั , time.clock() คนื คา่ เป็นวนิ าทที ไ่ี ดจ้ ากนาฬกิ าของเครอ่ื ง คอมพวิ เตอร์ และ time.sleep(t) ทาหน้าทส่ี งั่ ใหโ้ พรเซสหยดุ การประมวลผล โดยค่า t มคี ่าเท่ากบั วนิ าที Program Example 18.3: ctime(), clock(), sleep() method 1 import time 2 3 t0 = time.clock() 4 print(\"Start : %s\" % time.ctime()) 5 print(\"Start Processing time (seconds) = \", t0) 6 time.sleep(5) 7 print(\"Stop Processing time (Start - Current time) =\", time.time() - t0) 8 print(\"End : %s\" % time.ctime()) ผลลพั ธท์ เ่ี กดิ ขน้ึ จากการรนั โปรแกรมดงั น้ี Start : Sun Mar 23 12:56:36 2014 Start Processing time (seconds) = 5.131631479069614e-07 OUTPUT Stop Processing time (Start - Current time) = 1395554201.3708725 End : Sun Mar 23 12:56:41 2014 จากตวั อยา่ งโปรแกรมท่ี 18.3 แสดงการเรยี กใชง้ านเมธอด ctime(), clock() และ sleep() บรรทดั ท่ี 3 โปรแกรมเรยี กใชง้ าน clock() ซง่ึ จะทาใหไ้ ดเ้ วลาจากนาฬกิ าของคอมพวิ เตอรม์ คี า่ เป็นเลขทศนิยมเกบ็ ไว้ ในตวั แปร t0 บรรทดั ท่ี 4 สงั่ พมิ พว์ นั เวลาดว้ ยเมธอด ctime() บรรทดั ท่ี 5 สงั่ พมิ พเ์ วลาทเ่ี กบ็ ไวใ้ นตวั แปร t0 ออกทางจอภาพ บรรทดั ท่ี 6 โปรแกรมสงั่ ใหโ้ ปรแกรมทก่ี าลงั ทางานอยหู่ ยุดพกั การทางาน ชวั่ คราวประมาณ 5 วนิ าที ดว้ ยเมธอด sleep(5) หลงั จากโปรแกรมกลบั มาทางานอกี ครงั้ จะสงั่ พมิ พ์ เวลาทห่ี ยดุ พกั (บรรทดั ท่ี 7) ไปโดยคานวณไดจ้ าก เวลาปัจจบุ นั (time.time()) – เวลาเรมิ่ ตน้ (t0) บรรทดั สดุ ทา้ ยโปรแกรมสงั่ พมิ พว์ นั เวลาในรปู แบบสตรงิ ออกทางจอภาพ 2. ส่งจดหมายอิเลก็ ทรอนิกส์ (Email) เมอ่ื ผเู้ ขยี นโปรแกรมตอ้ งการสง่ Email ไปยงั เพ่อื นๆ สามารถทาไดง้ า่ ยๆ โดยใชโ้ มดลู smtplib ทท่ี างานตามมาตรฐานของโพรโทคอล SMTP (Mail Transfer Protocol) มรี ปู แบบการใชง้ านคอื smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] ) โดยพารามเิ ตอรท์ ใ่ี ชง้ านมคี วามหมายดงั ต่อไปน้ี host: ระบุช่อื ของเซริ ฟ์ เวอรท์ ใ่ี หบ้ รกิ ารเป็นเมลเ์ ซริ ฟ์ เวอร์ เชน่ Hotmail.com, gmail.com และ yahoo.com เป็นตน้ (host เป็น option จะไมใ่ สก่ ไ็ ด้ ถา้ ไมใ่ ส่ขอ้ มลู ใหก้ บั host เครอ่ื งผใู้ ชง้ านจาเป็นตอ้ งตดิ ตงั้ โปรแกรมทท่ี าหน้าทเ่ี ป็นเมลเ์ ซริ ฟ์ เวอร)์ ห น้ า 435
port: ระบหุ มายเลขพอรต์ ของเมลเ์ ซริ ฟ์ เวอร์ โดยปกตจิ ะใชพ้ อรต์ หมายเลข 25 local_hostname: เมอ่ื ผเู้ ขยี นโปรแกรมใชเ้ ครอ่ื งทก่ี าลงั ทางานเป็นเมลเ์ ซริ ฟ์ เวอร์ ให้ กาหนดฟิลดด์ งั กล่าวเป็น localhost เมอ่ื โปรแกรมสรา้ งอนิ สแตนซข์ องคลาส SMTP แลว้ ไพธอนไดเ้ ตรยี มเมธอดสาหรบั ส่งขอ้ ความตดิ มากบั อนิ สแตนซด์ งั กล่าวดว้ ยทนั ที เรยี กว่าเมธอด sendmail() โดยมพี ารามเิ ตอร์ 3 ตวั คอื ชอ่ื ผสู้ ง่ อเี มล์ (sender), รายชอ่ื ผรู้ บั อเี มล์ (receviers) สามารถกาหนดไดม้ ากกว่า 1 คน และขอ้ ความท่ี ตอ้ งการสง่ (message) แสดงในตวั อยา่ งท่ี 18.4 Program Example 18.4: sendmail() method 1 import smtplib 2 3 sender = '[email protected]' 4 receivers = ['[email protected]', '[email protected]'] 5 6 message = \"\"\"From: webmaster <[email protected]> To: To every persons <[email protected]>,<[email protected]> Subject: SMTP e-mail test This is a test e-mail message.\"\"\" 7 8 try: 9 smtpObj = smtplib.SMTP('localhost') 10 smtpObj.sendmail(sender, receivers, message) 11 print (\"Successfully sent email\") 12 except SMTPException: 13 print (\"Error: unable to send email\") ผลลพั ธท์ เ่ี กดิ ขน้ึ จากการรนั โปรแกรมดงั น้ี Successfully sent email OUTPUT จากตวั อยา่ งโปรแกรมท่ี 18.4 แสดงวธิ สี ง่ เมลโ์ ดยใชเ้ มธอด sendmail() เรม่ิ ตน้ โปรแกรมนาเขา้ โมดลู smtplib ทาหน้าทเ่ี ชอ่ื มต่อกบั เมลเ์ ซริ ฟ์ เวอร์ บรรทดั ท่ี 3 กาหนดช่อื ผสู้ ง่ ในทน่ี ้ที ดสอบกาหนดเป็น '[email protected]' ซง่ึ ชอ่ื ดงั กล่าวตอ้ งเป็นสมาชกิ ของผใู้ หบ้ รกิ ารเมลเ์ ซริ ฟ์ เวอรด์ ว้ ย ในการ ทดสอบน้ผี เู้ ขยี นไดท้ าการตดิ ตงั้ เมลเ์ ซริ ฟ์ เวอรช์ ่อื hMailServer บนเครอ่ื ง localhost (ปัจจุบนั เมล์ เซริ ฟ์ เวอรส์ าธารณะทใ่ี หบ้ รกิ ารเมลท์ วั่ ๆ ไป เช่น gmail, hotmail ไมเ่ ปิดใหเ้ ชอ่ื มต่อเขา้ ไปไดโ้ ดยตรง) บรรทดั ท่ี 4 กาหนดรายช่อื ผรู้ บั อเี มลซ์ ง่ึ สามารถมไี ดม้ ากกวา่ 1 ช่อื โดยกาหนดไวใ้ นตวั แปลชนดิ ลสิ ต์ บรรทดั ท่ี 6 สรา้ งขอ้ ความทต่ี อ้ งการสง่ อเี มล์ บรรทดั ท่ี 9 โปรแกรมสรา้ งอนิ สแตนซข์ องคลาส SMTP พรอ้ มกบั พารามเิ ตอร์ 1 ตวั คอื ชอ่ื ของเซริ ฟ์ เวอรท์ ใ่ี หบ้ รกิ ารส่งเมล์ (ในทน่ี ้ใี ชเ้ มลท์ ต่ี ดิ ตงั้ อยใู่ น localhost) ออ็ ปเจก็ ตท์ ส่ี รา้ งขน้ึ ช่อื smtpObj จะถูกนาไปอา้ งถงึ เมธอด senmail() เพอ่ื สง่ จดหมาย (บรรทดั ท่ี 10) โดยเมธอดดงั กลา่ วตอ้ งการพารามเิ ตอร์ 3 ตวั คอื ชอ่ื ผสู้ ง่ (sender) รายช่อื ผรู้ บั จดหมาย ห น้ า 436
(receivers) และขอ้ ความทต่ี ้องการส่ง (message) ถา้ การสง่ อเี มลท์ าไดส้ าเรจ็ โปรแกรมจะพมิ พข์ อ้ ความ ว่า \"Successfully sent email\" แต่ถา้ เกดิ ขอ้ ผดิ พลาดใดๆ เกดิ ขน้ึ ในขณะทาการส่งเมลโ์ ปรแกรมจะพมิ พ์ ขอ้ ความวา่ \"Error: unable to send email\" ดงั ตวั อยา่ ง OUTPUT ดา้ นบน 3. การประยกุ ต์ใช้ฟังกช์ นั map, filter, reduce, lambda กบั ข้อมลู แบบลาดบั ฟังกช์ นั map(): เป็นฟังกช์ นั ทใ่ี ชส้ าหรบั ดาเนินการกบั ขอ้ มลู ประเภทลาดบั เช่น list หรอื tupple แต่นิยมใชก้ บั list มากทส่ี ดุ โดยฟังกช์ นั map() มหี น้าทจ่ี บั ค่ฟู ังกช์ นั หรอื เมธอดเขา้ กบั ขอ้ มลู แบบ ลาดบั เพ่อื ประหยดั เวลาในการเขยี นโปรแกรมลง ซง่ึ มรี ปู แบบคอื map(aFunction, aSequence) โดย aFunction คอื ฟังกช์ นั ใดๆ ทต่ี อ้ งการประมวลผล ฟังกช์ นั ดงั กลา่ วจาเป็นตอ้ งใชข้ อ้ มลู ใน aSequence เขา้ มาทางานจงึ จะสมบรู ณ์, aSequence คอื ลาดบั ของขอ้ มลู ทส่ี ่งใหเ้ ป็นพารามเิ ตอรข์ อง aFunction ตวั อยา่ งเช่น ถา้ ตอ้ งการเขยี นโปรแกรมยกกาลงั สองของขอ้ มลู จานวนหน่งึ โดยปกตจิ ะใช้ for ช่วยในการทางาน เช่น >>> items = [1, 2, 3, 4, 5] >>> squared = [] >>> for x in items: squared.append(x ** 2) >>> squared [1, 4, 9, 16, 25] จากตวั อยา่ งโปรแกรมขา้ งตน้ จะเหน็ วา่ โปรแกรมจะดงึ ขอ้ มลู ในลสิ ตม์ าทลี ะตวั จากนนั้ โปรแกรมจะยกกาลงั สองและเพมิ่ เขา้ ไปในตวั แปรช่อื squared ดว้ ยเมธอด append() จนกว่าจะครบ ขอ้ มลู ทุกๆ ตวั ใน items แต่ถา้ จะใหส้ ะดวกและประหยดั คาสงั่ การเขยี นโปรแกรม ใหส้ งั เกตุการใช้ ฟังกช์ นั map() ช่วยในการทางานเดยี วกนั ดงั น้ี >>> items = [1, 2, 3, 4, 5] >>> def sqr(x): return x ** 2 >>> lst = list(map(sqr, items)) >>> print(lst) [1, 4, 9, 16, 25] จากตวั อยา่ งโปรแกรมขา้ งบน แสดงใหเ้ หน็ ว่าฟังกช์ นั map() จะทาการจบั ค่ฟู ังก์ชนั sqr() ซง่ึ ทาหน้าทย่ี กกาลงั สองของ x โดย x คอื ค่าทป่ี ้อนเขา้ มาทลี ะค่าจากตวั แปร items นนั่ เอง ผลลพั ธท์ ไ่ี ดค้ อื การยกกาลงั สองของสมาชกิ ทงั้ หมดในตวั แปร items ผลลพั ธท์ ย่ี กกาลงั สองแลว้ จะเกบ็ ไวใ้ นตวั แปรชนิด ลสิ ตเ์ ช่นเดมิ ห น้ า 437
map sqr(x) Items[1, 2, 3, 4, 5] list[1, 4, 9, 16, 25] ฟังกช์ นั map() ยงั สามารถประยกุ ตใ์ ชก้ บั ฟังกช์ นั lambda ไดเ้ ช่นเดยี วกนั ดงั น้ี >>> lst = list(map((lambda x: x **2), items)) >>> print(lst) [1, 4, 9, 16, 25] ฟังกช์ นั lambda ดา้ นบนทาหน้าทห่ี าคา่ ยกกาลงั สองเช่นเดยี วกบั ฟังกช์ นั sqr() ฟังกช์ นั map() ยงั สามารถใชไ้ ดก้ บั ฟังกช์ นั ทางคณติ ศาสตรใ์ นไลบรารข่ี องไพธอนได้ เช่น การใชฟ้ ังกช์ นั ยกกาลงั pow() >>> import math >>> pow(3,5) 243 >>> pow(2,10) 1024 >>> pow(3,11) 177147 >>> pow(4,12) 16777216 >>> list(map(pow,[2, 3, 4], [10, 11, 12])) [1024, 177147, 16777216] จากโปรแกรมขา้ งบน โปรแกรมจะทาการยกกาลงั โดยนาเอาสมาชกิ ใน list ตวั แรก ([2, 3, 4]) เป็นฐานและนาสมาชกิ ใน list ตวั ทส่ี อง ([10, 11, 12]) เป็นเลขชก้ี าลงั ในค่สู มาชกิ ทต่ี รงกนั เช่น 210, 311, 412 ผลลพั ธท์ ไ่ี ดค้ อื 1024, 177147, 16777216 ตามลาดบั ถา้ พารามเิ ตอรต์ วั แรกของฟังกช์ นั map() เป็น none ฟังกช์ นั map() จะมองวา่ เป็นการสรา้ งคขู่ องขอ้ มลู ชนิดทพั เพลิ แทน เช่น >>> m = [1,2,3] >>> n = [1,4,9] >>> new_tuple = map(None, m, n) >>> new_tuple [(1, 1), (2, 4), (3, 9)] m = [1, 2, 3] n = [1, 4, 9] new_tuple = [(1,1),(2,4),(3,9)] ฟังกช์ นั filter(): เป็นฟังกช์ นั ทใ่ี ชส้ าหรบั กรองสมาชกิ ในลสิ ตห์ รอื ขอ้ มลู ชนดิ ลาดบั โดยมรี ปู แบบ ดงั น้ี filter(aFunction, aSequence) ห น้ า 438
โดย aFunction คอื ฟังกช์ นั ใดๆ และ aSequence คอื ลาดบั ของขอ้ มลู ทต่ี อ้ งการประมวลผลกบั aFunction ตวั อยา่ งเชน่ >>> list(range(-5,5)) [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] >>> list(filter((lambda x: x < 0), range(-5, 5))) [-5, -4, -3, -2, -1] จากตวั อยา่ งโปรแกรมขา้ งบน ผลลพั ธท์ เ่ี กดิ ขน้ึ จากฟังกช์ นั range(-5, 5) จะไดช้ ่วงขอ้ มลู ตงั้ แต่ - 5 ถงึ 4 เมอ่ื ตอ้ งการกรองขอ้ มลู จากผลลพั ธท์ เ่ี กดิ ขน้ึ โดยเอาเฉพาะค่าทเ่ี ป็นจานวนเตม็ ลบ ผเู้ ขยี น โปรแกรมสามารถใชฟ้ ังก์ชนั filter() ในการกรองขอ้ มลู โดยใช้ (lambda x: x < 0) หมายถงึ ค่า x ทเ่ี ป็น พารามเิ ตอรต์ อ้ งมคี า่ น้อยกว่า 0 เทา่ นัน้ ค่าอ่นื ๆ จะตดั ทง้ิ ทงั้ หมด เมอ่ื เขยี นโปรแกรมดว้ ยลปู for แบบ ธรรมดาซง่ึ จะใหผ้ ลลพั ธท์ เ่ี หมอื นกบั โปรแกรมดา้ นบนแสดงไดด้ งั น้ี >>> result = [] >>> for x in range(-5, 5): if x < 0: result.append(x) >>> result [-5, -4, -3, -2, -1] ฟังกช์ นั reduce(): เป็นฟังกช์ นั ทใ่ี ชส้ าหรบั ลดการประมวลผลของการวนลปู กบั ขอ้ มลู แบบ ลาดบั โดยมรี ปู แบบดงั น้ี reduce(aFunction, aSequence) โดย aFunction คอื ฟังกช์ นั ใดๆ และ aSequence คอื ลาดบั ของขอ้ มลู ทต่ี อ้ งการประมวลผลกบั aFunction แต่ก่อนการใชง้ านจาเป็นตอ้ งนาเขา้ โมดลู functools เขา้ มาก่อน ตวั อยา่ งเชน่ >>> from functools import reduce >>> reduce((lambda x, y: x * y), [1, 2, 3, 4]) 24 >>> reduce((lambda x, y: x / y), [1, 2, 3, 4]) 0.041666666666666664 จากตวั อยา่ งโปรแกรมขา้ งบนเป็นการการทางานของฟังกช์ นั reduce() โดยบรรทดั ท่ี 1 เป็นการ นาเขา้ ฟังกช์ นั reduce() ทอ่ี ยใู่ นโมดลู functools เขา้ มาทางาน บรรทดั ต่อมาเรยี กใชฟ้ ังกช์ นั (lambda x, y: x * y) ซง่ึ หมายถงึ การหาผลคณู ของ x กบั y โดยในรอบแรกฟังกช์ นั lambda นาเอาสมาชกิ ตวั ท่ี 1 (1) ในลสิ ตส์ ง่ เป็นพารามเิ ตอรใ์ หก้ บั ตวั แปร x และสมาชกิ ตวั ท่ี 2 (2) ส่งเป็นพารามเิ ตอรใ์ หก้ บั ตวั แปร y นามาคณู กนั ผลลพั ธท์ ไ่ี ดจ้ ากการคณู ซง่ึ มคี ่าเทา่ กบั 2 (1*2=2) จะกลายเป็นพารามเิ ตอรข์ อง x อกี ครงั้ และ lambda กจ็ ะดงึ สมาชกิ ตวั ท่ี 3 (3) ในลสิ ต์ ใหเ้ ป็นพารามเิ ตอร์ y จากนนั้ lambda จะนา x และ y มา คณู กนั อกี ครงั้ ผลลพั ธท์ ไ่ี ดเ้ ท่ากบั 6 (2*3=6) เกบ็ ไวใ้ นตวั แปร x และนาไปคณู กบั ตวั แปร y ซง่ึ มคี ่า ห น้ า 439
เทา่ กบั 4 อกี ครงั้ ผลลพั ธท์ ไ่ี ดเ้ ทา่ กบั 24 (6*4=24) การทางานของฟังก์ชนั reduce() ทางานค่อนขา้ ง ซบั ซอ้ น ดงั นนั้ จาเป็นตอ้ งดูภาพดา้ นล่างเพอ่ื ประกอบความเขา้ ใจดว้ ย reduce((lambda x, y: x * y), [1, 2, 3, 4]) (1)(2) reduce((lambda x, y: 1 * 2), [3, 4]) (2)(2) reduce((lambda x, y: 2 * 3), [3, 4]) (2)(3) reduce((lambda x, y: 2 * 3), [4]) (6)(3) reduce((lambda x, y: 6 * 4), [4]) (6)(4) reduce((lambda x, y: 6 * 4)) 24 สาหรบั ฟังกช์ นั (lambda x, y: x / y) จะทางานคลา้ ยกบั lambda การคณู ทแ่ี สดงในรปู ดา้ นบน แต่แตกต่างกนั คอื เปลย่ี นจากการคณู เป็นการหารแทน ผลลพั ธท์ ไ่ี ดเ้ ท่ากบั 0.04166 เมอ่ื เขยี นโปรแกรม โดยใชล้ ปู ธรรมดาเพอ่ื ประมวลผลการคณู เหมอื นฟังกช์ นั reduce() แสดงไดด้ งั น้ี >>> L = [1, 2, 3, 4] >>> result = L[0] >>> for x in L[1:]: result = result * x >>> result 24 ฟังกช์ นั lambda(): ทาหน้าทแ่ี ทนการสรา้ งฟังกช์ นั แบบปกติ โดยไมจ่ าเป็นตอ้ งประกาศช่อื ฟังกช์ นั แต่ใชค้ าว่า lambda แทน ใชส้ าหรบั ประมวลผลเพ่อื แกป้ ัญหาบางอยา่ งเหมอื นกบั การสรา้ งสตู ร หรอื สมการในตารางของโปรแกรม MS-Excel (เน้อื หาโดยละเอยี ดสามารถอ่านไดจ้ ากบทท่ี 7) โดยมี รปู แบบดงั น้ี lambda para1, para2,…,paraN: operation โดย lambda คอื ชอ่ื ของฟังกช์ นั , papa1 – paraN คอื พารามเิ ตอรท์ ส่ี ง่ ใหก้ บั lambda และ operation คอื คาสงั่ ท่ี lambda ตอ้ งประมวลผล เช่น ถา้ ตอ้ งการหาค่ายกกาลงั 3 ของ x สามารถเขยี นโปรแกรมดว้ ยฟังกช์ นั ปกตไิ ดค้ อื >>> def func(x): return x ** 3 >>> print(func(5)) 125 แต่ถา้ ใชฟ้ ังกช์ นั lambda โปรแกรมจะสนั้ และกระทดั ลดั กวา่ โดยไมต่ อ้ งใชค้ าสงั่ return ดงั น้ี ห น้ า 440
>>> lamb = lambda x: x ** 3 >>> print(lamb(5)) 125 4. ไพธอน Generators, yield Generators เป็นกลไกพเิ ศษทใ่ี ชส้ าหรบั ควบคมุ พฤตกิ รรมการทางานของลปู เพอ่ื สรา้ งชุดของ ขอ้ มลู ใหเ้ ป็นไปตามทผ่ี ใู้ ชต้ อ้ งการ ซง่ึ ในความเป็นจรงิ แลว้ Generator มลี กั ษณะการทางานทค่ี ลา้ ยคลงึ กบั ฟังกช์ นั เป็นอย่างมาก แตกต่างกนั คอื ฟังกช์ นั จะคนื ค่ากลบั ใหแ้ ก่ผเู้ รยี กใชง้ านทงั้ หมดในครงั้ เดยี ว เมอ่ื ทางานเสรจ็ (อาจจะเป็นขอ้ มลู เพยี งคา่ เดยี วหรอื เป็นชดุ ของขอ้ มลู กไ็ ด)้ ดว้ ยคาสงั่ return แต่สาหรบั Generators แลว้ ขอ้ มลู ทส่ี ่งคนื ใหแ้ ก่ผเู้ รยี กจะขน้ึ อยกู่ บั ความตอ้ งการใชง้ าน (On-demand) กลา่ วคอื ถา้ ผใู้ ชต้ อ้ งการ Generators จะสรา้ งขอ้ มลู ใหต้ ามทต่ี อ้ งการเทา่ นนั้ หลงั จากนนั้ Generators จะหยดุ พกั ทางานชวั่ คราว (Suspending) และจะกลบั มาทางานใหมอ่ กี ครงั้ เมอ่ื ผใู้ ชง้ านเรยี กใชง้ านอกี ครงั้ (Resuming) ทาอยา่ งน้ไี ปเรอ่ื ยๆ จนกวา่ ผใู้ ชจ้ ะยตุ กิ ารใชง้ าน ซง่ึ วธิ กี ารแบบ Genterators น้จี ะชว่ ยให้ คอมพวิ เตอรป์ ระหยดั หน่วยความจา ซง่ึ แตกต่างจากฟังกช์ นั ทจ่ี ะสรา้ งชดุ ขอ้ มลู ทม่ี คี ่าคงทเ่ี ช่น อาเรย์ ลสิ ต์ หรอื ทพั เพลิ เพอ่ื สง่ คนื ใหแ้ ก่ผใู้ ชง้ าน Generators แบง่ ออกเป็น 2 ประเภทคอื Generator functions คอื การใชค้ าสงั่ yield ทางานรว่ มกบั ฟังกช์ นั ปกติ โดยขอ้ มลู ทถ่ี ูก สรา้ งจะขน้ึ อยกู่ บั ความตอ้ งการของผใู้ ชง้ านขณะนนั้ ๆ โดยปราศจากคาสงั่ return เมอ่ื ผใู้ ชย้ งั ไมเ่ รยี กใชง้ าน ฟังกช์ นั ดงั กลา่ วจะหยดุ พกั (Suspending) และกลบั มาทางาน ใหมเ่ มอ่ื ผใู้ ชเ้ รยี กใชง้ าน (Resuming) อกี ครงั้ ทาอยา่ งน้ไี ปเรอ่ื ยจนกว่าจะยตุ โิ ปรแกรม Generator expressions เป็นการฝังนพิ จน์คณติ ศาสตรห์ รอื คาสงั่ ลงในตวั แปรประเภท ลสิ ต์ เพอ่ื สรา้ งชดุ ของขอ้ มลู เช่น >>> list(c * 3 for c in 'Python') ['PPP', 'yyy', 'ttt', 'hhh', 'ooo', 'nnn'] >>> list(x ** 3 for x in range(5)) [0, 1, 8, 27, 64] Generator functions จากทก่ี ล่าวมาแลว้ ขา้ งตน้ ว่า Generator functions สรา้ งขน้ึ จากคาสงั่ yield รว่ มกบั ฟังกช์ นั ปกติ โดยไมม่ คี าสงั่ return ปิดทา้ ยฟังกช์ นั จากตวั อยา่ งขา้ งล่าง แสดงการสรา้ งชดุ ขอ้ มลู เลขจานวนนบั ทย่ี ก กาลงั สอง def increment(): x=0 ห น้ า 441
while True: x += 1 yield x y = increment() print(y) print(next(y)) print(next(y)) print(next(y)) ผลลพั ธท์ ไ่ี ดจ้ ากโปรแกรมคอื <generator object increment at 0x0000000004008828> 1 OUTPUT 2 3 จากตวั อยา่ งโปรแกรมขา้ งบน โปรแกรมสรา้ งฟังก์ชนั ช่อื increment() ทาหน้าทเ่ี พมิ่ ค่าขอ้ มลู ขน้ึ ครงั้ ละ 1 เมอ่ื เรยี กใชง้ านฟังก์ชนั ดงั กลา่ ว การเรยี กใชค้ าสงั่ y = increment() จะส่งผลใหค้ ่าทค่ี นื กลบั มาจาก ฟังกช์ นั ดงั กล่าวคอื ทอ่ี ยขู่ องออ็ ปเจก็ ต์ Generator (<generator object increment at 0x0000000004008828>) ซง่ึ ไมใ่ ช่ขอ้ มลู ทส่ี รา้ งมาจากฟังกช์ นั ดงั กลา่ ว ผใู้ ชง้ านจาเป็นตอ้ งใชฟ้ ังกช์ นั next(y) เพ่อื ชว่ ยดงึ ขอ้ มลู จากฟังกช์ นั increment() มาแสดงผลทลี ะค่า แต่ถา้ ตอ้ งการเรยี กใชง้ านขอ้ มลู ทงั้ หมดอยา่ งต่อเน่อื งสามารถใชง้ านรว่ มกบั คาสงั่ ลปู for ได้ เช่น Program Example 18.5: yield, next 1 def increment(): 2 x=0 3 while True: 4 yield x 5 x += 1 6 7 def pow(n): 8 for i in range(n): 9 yield i**2 10 11 y = increment() 12 for j in pow(6): 13 print(\"The power of %d = %d\" %(next(y), j)) ผลลพั ธท์ ไ่ี ดจ้ ากโปรแกรมคอื The power of 0 = 0 The power of 1 = 1 OUTPUT The power of 2 = 4 The power of 3 = 9 The power of 4 = 16 The power of 5 = 25 จากการทางานของโปรแกรมท่ี 18.5 บรรทดั ท่ี 4 ในฟังกช์ นั increment() สงั เกตุวา่ คาสงั่ yield แตกต่าง จากคาสงั่ return เพราะถา้ ใชค้ าสงั่ return แทน yield แลว้ คาสงั่ x += 1 จะไมถ่ ูกทางานเลย (เพราะจะ กลบั ไปยงั โปรแกรมทเ่ี รยี กใชง้ านทนั ท)ี แต่สาหรบั คาสงั่ yield คาสงั x += 1 จะสามารถทางานได้ ห น้ า 442
หลงั จากฟังกช์ นั increment() กลบั มาทางานอกี ครงั้ บรรทดั ท่ี 7 เมธอด pow() สรา้ งชดุ ขอ้ มลู ทเ่ี ป็นเลข จานวนนบั ยกกาลงั สองรว่ มกบั คาสงั่ yield โดยรบั พารามเิ ตอร์ 1 ตวั คอื เลขจานวนนบั (n) บรรทดั ท่ี 12 และ 13 โปรแกรมสงั่ พมิ พค์ ่าเลขยกกาลงั สองออกจอภาพดว้ ยฟังกช์ นั print() ทางานรว่ มกบั ลปู for โดย ใชพ้ ารามเิ ตอร์ 2 ตวั คอื next(y) ซง่ึ เป็นชดุ ขอ้ มลู ทเ่ี กดิ จากฟังกช์ นั increment() และ j ซง่ึ เป็นชุดขอ้ มลู ท่ี เกดิ จากฟังกช์ นั power() Note: ผเู้ ขยี นโปรแกรมไมส่ ามารถใชค้ าสงั่ return ในการสรา้ งชดุ ขอ้ มลู ไดเ้ หมอื นคาสงั่ yield เชน่ def generator(n): for i in range(n): return i ** 3 for i in generator(5): print(i) TypeError: 'int' object is not iterable 5. การเขียนโปรแกรมไพธอนด้วย Eclipse Eclipse เป็นเครอ่ื งมอื ทไ่ี ดร้ บั ความนิยมเป็นอยา่ งมากสาหรบั โปรแกรมเมอรเ์ พอ่ื ใชพ้ ฒั นา โปรแกรมไดห้ ลากหลาย เช่น Java, C, C++ เป็นตน้ เน่ืองจากโปรแกรมดงั กล่าวมรี ปู แบบอนิ เตอรเ์ ฟสท่ี สามารถใชง้ านไดส้ ะดวก ในหวั ขอ้ น้ผี เู้ ขยี นจะแนะนาการใชง้ านโปรแกรมดงั กล่าว โดยมขี นั้ ตอนดงั น้ี 1) ดาวน์โหลดและตดิ ตงั้ Java JRE หรอื Java SDK ก่อน จาก URL: https://www.java.com/en/download/ หรอื จาก CD ซง่ึ อยใู่ นไดเรคทรอร่ี Ch18- Misc\\Softwares\\ jre-7u51-windows-x64.exe เมอ่ื ตดิ ตงั้ เสรจ็ แลว้ ตอ้ งกาหนด path ใน Environment Variables ในวนิ โดวสใ์ หช้ ไ้ี ปยงั C:\\Program Files (x86)\\Java\\jre7\\bin 2) ดาวน์โหลดโปรแกรม Eclipase มาตดิ ตงั้ บนเครอ่ื งก่อนจาก URL: https://www.eclipse.org/downloads/ โดยเลอื กแบบ Eclipse Standard x.x.x (x คอื หมายเลขของเวอรช์ นั ) ซง่ึ มขี นาดประมาณ 200 Mb หรอื สามารถตดิ ตงั้ โปรแกรมไดจ้ าก แผ่น CD ซง่ึ อยใู่ นไดเรคทรอร่ี Ch18-Misc\\Softwares\\eclipse-standard-kepler-SR2- win32-x86_64.zip สาหรบั สถาปัตยกรรมแบบ 64 บติ เมอ่ื ดาวน์โหลดมาแลว้ ใหท้ าการแตก แฟ้มทบ่ี บี อดั ไว้ แลว้ นาไปวางไวใ้ นไดรฟ์ C: 3) ดบั เบลิ คลกิ แฟ้มชอ่ื eclipse.exe ดงั รปู ท่ี 1 ห น้ า 443
รปู ท่ี 1 แสดงขนั้ ตอนเรม่ิ ตน้ การปรบั แต่ง eclipse 4) คลกิ เลอื ก OK จากนนั้ โปรแกรม eclipse จะเรมิ่ ต้นทางานดงั รปู ท่ี 2 รปู ท่ี 2 แสดงหน้าต่างเรมิ่ ตน้ ของโปรแกรม eclipse 5) เลอื กทเ่ี มนู Help Install New Software… ดงั รปู ท่ี 3 รปู ท่ี 3 แสดงการตดิ ตงั้ ซอฟตแ์ วรเ์ พม่ิ เตมิ 6) คลกิ เลอื ก Add… ดงั รปู ท่ี 4 ห น้ า 444
รปู ท่ี 4 เพมิ่ แหล่งทเ่ี กบ็ ตวั คอมไพลภ์ าษาไพธอนใหก้ บั eclipse 7) ใหเ้ พม่ิ URL ของเวบ็ ไซต์ pydev.org ในชอ่ ง Name: เพม่ิ ขอ้ ความว่า PyDev และช่อง Location: เป็น http://pydev.org/updates เพอ่ื ทาการเพมิ่ ภาษาไพธอนใหก้ บั eclipse ดงั รปู ท่ี 5 ต่อจากนนั้ กดป่มุ OK รปู ท่ี 5 เพม่ิ แหลง่ ขอ้ มลู ภาษาไพธอนจากเวบ็ ไซต์ pydev.org 8) รอสกั ครู่ โปรแกรมจะทาการ update ขอ้ มลู ใหก้ บั eclipse เมอ่ื โปรแกรมปรบั ปรงุ ขอ้ มลู สาเรจ็ โปรแกรมจะแสดงดงั รปู ท่ี 6 ใหค้ ลกิ เลอื ก PyDev และ PyDev for Eclipse แลว้ เลอื ก Next> ห น้ า 445
รปู ท่ี 6 คลกิ เลอื ก PyDev for Eclipse 9) ขนั้ ตอนต่อไปเลอื ก Next> เมอ่ื ถงึ เมนู Review Licenses เลอื ก I accept the terms…. และ คลกิ เลอื ก Finish 10) โปรแกรมจะเรมิ่ ทาการตดิ ตงั้ โปรแกรมเสรมิ คอื ไพธอนใหก้ บั eclipse ใหร้ อสกั ครู่ ดงั รปู ท่ี 7 รปู ท่ี 7 โปรแกรมเรม่ิ ตดิ ตงั้ ไพธอนสาหรบั eclipse 11) เมอ่ื โปรแกรมแสดงเมนู Selection Needed ใหค้ ลกิ เลอื ก Brainwy Software; PyDev;Brainwy แลว้ เลอื ก OK ดงั รปู ท่ี 8 ห น้ า 446
รปู ท่ี 8 แสดงหน้าต่าง Selection Needed 12) เมอ่ื ตดิ ตงั้ เสรจ็ โปรแกรมแจง้ ใหผ้ ใู้ ชท้ ราบว่าจาเป็นตอ้ งเรมิ่ ตน้ การทางานของ eclipse ใหม่ ใหผ้ ใู้ ชเ้ ลอื ก Yes ดงั รปู ท่ี 9 รปู ท่ี 9 แสดงโปรแกรมตดิ ตงั้ เสรจ็ และตอ้ งการเรม่ิ ตน้ โปรแกรมใหม่ 13) เมอ่ื เรม่ิ ตน้ โปรแกรมใหม่ จาเป็นตอ้ งปรบั แต่งให้ eclipse มองเหน็ ตวั แปรภาษาไพธอนก่อน เรม่ิ ตน้ ใชง้ าน eclipse คลกิ ท่ี Window Preferences PyDev Interpreter Interpreter - Python ดงั รปู ท่ี 10 ห น้ า 447
รปู ท่ี 10 แสดงหน้าต่าง Interpreter - Python 14) ในหน้าต่าง Python Interpreters เลอื ก Quick Auto-Config ซง่ึ จะทาใหโ้ ปรแกรมคน้ หา ตาแหน่งทอ่ี ย่ขู องไพธอนใหเ้ องโดยอตั โนมตั ิ แลว้ คลกิ OK ดงั รปู ท่ี 11 รปู ท่ี 11 แสดงผลลพั ธเ์ มอ่ื เลอื ก Quick Auto-Config ห น้ า 448
15) เมอ่ื eclipse ไดร้ บั การปรบั แต่งเรยี บรอ้ ยแลว้ ขนั้ ตอนต่อไปจะเป็นการสรา้ ง Project เพ่อื ใช้ สาหรบั เขยี นโปรแกรม โดยเลอื กท่ี File New Other… แลว้ เลอื กท่ี PyDev Project แลว้ คลกิ Next > ดงั รปู ท่ี 12 รปู ท่ี 12 แสดงการสรา้ ง Project 16) ทดสอบตงั้ ช่อื Project ช่อื test ซง่ึ Project ดงั กล่าวจะบนั ทกึ อยใู่ นไดเรคทรอร่ี C:\\Users\\Username\\workspace ต่อจากนนั้ ใหเ้ ลอื ก Grammar version เป็น 3.0 แลว้ เลอื ก Finish ดงั รปู ท่ี 13 ห น้ า 449
รปู ท่ี 13 เสรจ็ สน้ิ ขนั้ ตอนการสรา้ ง Project 17) ทดสอบการรนั โปรแกรม โดยเลอื กท่ี Test Project New Source Folder ตงั้ ชอ่ื วา่ test จากนนั้ คลกิ ขวาท่ี Source Folder ชอ่ื วา่ test แลว้ เลอื ก New File ตงั้ ช่อื แฟ้ม วา่ test.py แลว้ ทดสอบเขยี นโปรแกรมดงั รปู ท่ี 14 รปู ท่ี 14 สรา้ งไดเรคทรอรส่ี าหรบั เกบ็ โปรแกรม 18) เมอ่ื สงั่ รนั โปรแกรม โดยการกดทเ่ี มนู Run Run หรอื ป่มุ CTRL + 11 ถา้ โปรแกรม แสดงขอ้ ความผดิ พลาดว่า \"Fatal Python error: Py_Initialize: can't initialize sys standard streams LookupError: unknown encoding: MS874\" แสดงวา่ ฟอนตท์ ่ี ห น้ า 450
โปรแกรมกาหนดไว้ วนิ โดวสไ์ มส่ นบั สนุน ใหท้ าการกาหนดฟอนตใ์ หม่ โดยการคลกิ ขวาท่ี ช่อื Project (ในทน่ี ้คี อื Test) Properties Resource Text file encoding UTF-8 คลกิ OK แลว้ สงั่ รนั โปรแกรมใหมอ่ กี ครงั้ ถา้ ไมม่ ขี อ้ ผดิ พลาดใดๆ ผลลพั ธจ์ ะ แสดงดงั รปู ท่ี 15 รปู ท่ี 15 แสดงการรนั โปรแกรม Caution! เมอ่ื สงั่ รนั โปรแกรมไพธอนบน eclipse แลว้ เกดิ ขอ้ ผดิ พลาดคอื \"Fatal Python error: Py_Initialize: can't initialize sys standard streams LookupError: unknown encoding: MS874\" ใหแ้ กไ้ ขโดย คลกิ ขวาทช่ี อ่ื Project Properties Resource Text file encoding UTF-8 คลกิ OK 6. การแปลงไพธอนสคริปต์เป็น EXE (exceutable) ไพธอนเป็นภาษาสครปิ ต์ ดงั นนั้ เมอ่ื รนั โปรแกรมจาเป็นตอ้ งมตี วั แปรภาษาอยใู่ นเครอ่ื งทท่ี างาน เสมอ และมขี อ้ จากดั เรอ่ื งความเรว็ ในการทางานดว้ ยเพราะตอ้ งแปลภาษาทลี ะบรรทดั (Interpreting) จากปัญหาดงั กล่าวสามารถแกป้ ัญหาโดยการแปลงภาษาสครปิ ตเ์ ป็นแฟ้มประเภท exe เพ่อื ใหส้ ามารถ ประมวลผลไดเ้ รว็ ขน้ึ และสามารถทางานไดโ้ ดยปราศจากตวั แปรภาษา ซง่ึ มขี นั้ ตอนดงั น้ี 1) บนเครอ่ื งคอมพวิ เตอรต์ อ้ งมกี ารตดิ ตงั้ ภาษาไพธอน ในตวั อยา่ งน้เี ป็นเวอรช์ นั 3.4 2) ตอ้ งตดิ ตงั้ โปรแกรม py2exe สามารถดาวน์โหลดไดจ้ าก URL: http://www.py2exe.org/ สาหรบั ไพธอน 2.7 และ cx_Freeze สาหรบั ไพธอนเวอรช์ นั 2.7 ขน้ึ ไป ดาวน์โหลดได้ จาก URL: http://cx-freeze.sourceforge.net/ (โปรแกรมทงั้ หมดอยใู่ นแผ่น CD ทแ่ี นบ มากบั หนงั สอื เลม่ น้แี ลว้ ในโฟลเดอร์ Ch18\\Softwares) 1. การแปลงสคริปตไ์ พธอนเป็น exe ด้วย py2exe ห น้ า 451
สาหรบั โปรแกรม py2exe จะเหมาะกบั ผเู้ ขยี นโปรแกรมทย่ี งั ใชไ้ พธอนเวอรช์ นั ตงั้ แต่ 2.7 ลง ไป ซง่ึ มขี นั้ ตอนดงั น้ี หลงั จากตดิ ตงั้ โปรแกรม py2exe เสรจ็ เรยี บรอ้ ยแลว้ ใหเ้ ขยี นโปรแกรมทดสอบมชี ่อื ว่า testexe.py ดงั น้ี import math def cal(n): for i in range(n): print(math.pow(i, 2)) cal(5) ทดสอบรนั โปรแกรมผ่านทาง MS-DOS ดว้ ยคาสงั่ python testexe.py ดงั รปู ดา้ นลา่ ง อนั ดบั ต่อไป ใหท้ าการสรา้ งแฟ้มสาหรบั กาหนดสภาพแวดลอ้ มในการสรา้ งแฟ้ม exe ชอ่ื วา่ setup.py ซง่ึ มคี าสงั่ ดงั น้ี from distutils.core import setup import py2exe setup(console=['testexe.py']) จากโปรแกรม setup.py ทาการนาเขา้ คลาส setup จากโมดลู distutils.core เขา้ มาทางานเพอ่ื รวมรวมไลบรารต่ี ่างๆ ทจ่ี าเป็นสาหรบั การสรา้ งแฟ้ม exe บรรทดั ต่อมานาเขา้ โปรแกรม py2exe เพ่อื สรา้ งแฟ้ม exe บรรทดั สดุ ทา้ ยกาหนดชอ่ื แฟ้มไพธอนสครปิ ตท์ ต่ี อ้ งการแปลงเป็นแฟ้ม exe ไวภ้ ายใน เครอ่ื งหมาย […] เมอ่ื สรา้ งแฟ้มดงั กล่าวเสรจ็ แลว้ ใหส้ รา้ งแฟ้ม exe โดยใชค้ าสงั่ python setup.py py2exe ใน MS-DOS ผลลพั ธแ์ สดงดงั ภาพดา้ นล่าง Caution! ถา้ สงั่ คอมไพลโ์ ปรแกรมเป็น exe แลว้ เกดิ ขอ้ ผดิ พลาด คอื Traceback (most recent call last): File \"setup.py\", line 2, in <module> import py2exe ห น้ า 452
ImportError: No module named 'py2exe' แสดงวา่ ไม่ไดท้ าการ path โปรแกรม py2exe ไว้ ดงั นนั้ ใหย้ า้ ยแฟ้ม setup.py และ testexe.py ไวใ้ น path ของไพธอน เชน่ C:\\Python27 แทน ผลลพั ธจ์ ากการคอมไพลจ์ ะสรา้ งแฟ้ม exe และแฟ้มขอ้ มลู ทเ่ี กย่ี วขอ้ ง เช่น .dll, library.zip, .pyd เกบ็ ไวใ้ นไดเรคทรอรช่ี ่อื dist ดงั นนั้ เม่อื ผใู้ ชต้ อ้ งการนาแฟ้ม .exe ไปทางานบนเครอ่ื งอ่นื ๆ จาเป็นตอ้ งคดั ลอกไดเรคทรอรด่ี งั กลา่ วไปทงั้ หมด มิ เชน่ นัน้ แลว้ จะเกดิ ขอ้ ผดิ พลาดทนั ที ใหผ้ ใู้ ช้ทดลองดบั เบลิ คลกิ แฟ้ม testexe.exe หรอื สงั่ รนั ผ่าน MS-DOS ผลลพั ธแ์ สดงดงั รปู ดา้ นล่าง 2. การแปลงสคริปตไ์ พธอนเป็น exe ด้วย cx_Freeze ตดิ ตงั้ โปรแกรม cx_Freeze โดยดบั เบลิ คลกิ แฟ้มชอ่ื cx_Freeze-4.3.2*.msi ใหผ้ ใู้ ช้ เลอื ก Next > ไปเรอ่ื ยๆ จนกว่าโปรแกรมจะเสรจ็ สน้ิ การตดิ ตงั้ โปรแกรม cx_Freeze จะทาการ path ใหอ้ ตั โนมตั ิ ผใู้ ชง้ านสามารถเรยี กใชง้ านได้ ทนั ที การสรา้ ง exe ดว้ ย cx_Freeze ทาได้ 2 วธิ คี อื วธิ ที ่ี 1 สงั่ รนั ดว้ ยคาสงั่ cxfreeze testexe.py --target-dir dist ใน MS-DOS ซง่ึ จะทาใหไ้ ดแ้ ฟ้ม .exe ทนั ทแี ละเกบ็ แฟ้มดงั กลา่ วในไดเรคทรอรช่ี อ่ื dist วธิ ที ่ี 2 คอื การสรา้ งแฟ้มชอ่ื setup.py ซง่ึ มี คาสงั่ ดงั น้ี หรอื คน้ หาไดจ้ ากแผน่ CD from cx_Freeze import setup, Executable setup( name = \"hello\", version = \"0.1\", description = \"Sample cx_Freeze script\", executables = [Executable(\"testexe.py\")]) สงั่ คอมไพลโ์ ปรแกรมดว้ ยคาสงั่ python setup.py build ใน MS-DOS ผลจากการ คอมไพลโ์ ปรแกรมจะสรา้ งโฟลเดอรช์ ่อื built\\exe.win-xx และเกบ็ แฟ้ม .exe ไวใ้ น โฟลเดอรด์ งั กลา่ ว 7. Decorator Vs Function ห น้ า 453
ฟังกช์ นั (Function) คอื กลมุ่ ของชุดคาสงั่ ทท่ี างานเฉพาะกจิ เช่น คานวณเลขยกกาลงั หาค่าพน้ื เป็นตน้ แต่ Decorator คอื ฟังกช์ นั ทท่ี าหน้าทด่ี ดั แปลงหรอื ปรบั แต่งฟังก์ชนั อ่นื ๆ ใหเ้ หมาะสมตามท่ี ผเู้ ขยี นโปรแกรมตอ้ งการ ไพธอนมองทกุ ๆ สงิ่ เป็นออ็ ปเจก็ ตท์ งั้ หมด ไม่มขี อ้ ยกเวน้ แมแ้ ต่ฟังกช์ นั ซง่ึ สง่ ผลใหฟ้ ังกช์ นั ถูก มองวา่ เป็นพารามเิ ตอรต์ วั หน่งึ ในโปรแกรมกไ็ ด้ ตวั อยา่ งเช่น 1 def function_parameter(): 2 print (\"I am a parameter!\") 3 4 function_dict = {\"func\": function_parameter} 5 func_para = function_dict['func'] 6 func_para() ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื I am a parameter! OUTPUT จากตวั อยา่ งโปรแกรมขา้ งบน บรรทดั ท่ี 1 โปรแกรมสรา้ งฟังกช์ นั ช่อื function_parameter() ทา หน้าทพ่ี มิ พข์ อ้ ความวา่ \"I am a parameter!\" จากนนั้ บรรทดั ท่ี 4 โปรแกรมประกาศตวั แปรช่อื function_dic ซง่ึ เป็นตวั แปรชนดิ ดกิ ชนั นาร่ี ประกอบไปดว้ ยคยี ช์ อ่ื \"func\" และมขี อ้ มลู คอื function_parameter ซง่ึ กค็ อื ฟังกช์ นั function_parameter() นนั่ เอง เมอ่ื โปรแกรมดงึ ขอ้ มลู จากตวั แปร function_dict ในบรรทดั ท่ี 5 โดยการกาหนดคยี ์ \"func\" (function_dict['func']) คา่ ทส่ี ง่ คนื กลบั มาจะ เป็นออ็ ปเจก็ ตข์ องฟังกช์ นั function_parameter() ส่งผลใหต้ วั แปร func_para เป็นฟังกช์ นั function_parameter() ดว้ ย เมอ่ื เรยี ก func_para() ในบรรทดั ท่ี 6 จะทาใหไ้ ดผ้ ลลพั ธเ์ หมอื นกบั การเรยี ก function_parameter() เช่นเดยี วกนั การส่งฟังกช์ นั เป็นพารามิเตอร์ เมอ่ื ฟังกช์ นั สามารถใชเ้ ป็นขอ้ มลู หรอื พารามเิ ตอรใ์ หก้ บั ตวั แปรชนิดต่างๆ ได้ เชน่ ดกิ ชนั ราร่ี ลสิ ต์ ทพั เพลิ ฉะนนั้ ฟังกช์ นั กส็ ามารถกาหนดเป็นพารามเิ ตอรใ์ หก้ บั ฟังกช์ นั อ่นื ๆ ไดเ้ ช่นเดยี วกนั เรยี ก ฟังกช์ นั ทร่ี บั ฟังก์ชนั อ่นื ๆ เป็นพารามเิ ตอร์ หรอื คนื คา่ กลบั เป็นฟังกช์ นั ว่า \"higher order function\" ตวั อยา่ งเช่น 1 def self_absorbed_function(): 2 return (\"I'm an amazing function!\") 3 4 def printer(func): 5 print (\"The function passed to me says: \" + func()) 6 7 printer(self_absorbed_function) ห น้ า 454
ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื The function passed to me says: I'm an amazing function! OUTPUT จากตวั อยา่ งโปรแกรมขา้ งบน บรรทดั ท่ี 1 โปรแกรมสรา้ งฟังกช์ นั ช่อื self_absorbed_function() ทาหน้าทค่ี นื ค่าเป็นขอ้ ความว่า \"I'm an amazing function!\" ไปยงั ผเู้ รยี กใชง้ าน บรรทดั ท่ี 4 โปรแกรม สรา้ งฟังก์ชนั ช่อื printer() ทาหน้าทพ่ี มิ พข์ อ้ ความว่า \"The function passed to me says: \" ตามดว้ ย ขอ้ ความทเ่ี กดิ จากฟังกช์ นั ช่อื func() นนั่ กค็ อื ผลลพั ธท์ ไ่ี ดจ้ ากฟังก์ชนั self_absorbed_function() นนั่ เอง โดยฟังกช์ นั printer() ตอ้ งการพารามเิ ตอร์ 1 ตวั ซง่ึ เป็นฟังกช์ นั เมอ่ื ผใู้ ชง้ านเรยี กฟังกช์ นั printer(self_absorbed_function) พรอ้ มกบั สง่ ฟังกช์ นั เป็นพารามเิ ตอรใ์ หก้ บั ฟังก์ชนั ดงั กล่าว ทาให้ ไดผ้ ลลพั ธด์ งั แสดงในตวั อยา่ ง OUTPUT ดา้ นบน Decorator คือ wrapper (ผหู้ ่อห้มุ ) จากทก่ี ล่าวมาแลว้ วา่ ฟังกช์ นั สามารถเป็นพารามเิ ตอรใ์ หก้ บั ฟังกช์ นั อ่นื ๆ ได้ ซง่ึ หลกั การทางาน น้ถี ูกนาไปใชก้ บั Decorator ดว้ ย คอื เมอ่ื ส่งฟังกช์ นั ใดๆ ใหก้ บั Decorator ฟังกช์ นั เหลา่ นนั้ จะถูกแกไ้ ข ตดั ต่อ หรอื หอ่ หุม้ จากฟังกช์ นั Decorator นนั่ เอง ตวั อยา่ งเชน่ 1 def logging_decorator(func): 2 def wrapper(): 3 wrapper.count += 1 4 print(\"The function I modify has been called {0} 5 times(s).\".format(wrapper.count)) 6 func() 7 8 wrapper.count = 0 9 return wrapper 10 11 def a_function(): 12 print(\"I'm a normal function.\") 13 14 modified_function = logging_decorator(a_function) modified_function() modified_function() ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื The function I modify has been called 1 times(s). I'm a normal function. OUTPUT The function I modify has been called 2 times(s). I'm a normal function. จากตวั อยา่ งโปรแกรมขา้ งบน บรรทดั ท่ี 1 สรา้ งฟังกช์ นั Decorator ชอ่ื วา่ logging_decorator() ทาหน้าทห่ี ่อหุม้ ฟังกช์ นั ช่อื ว่า func() โดยมพี ารามเิ ตอรเ์ ป็นฟังกช์ นั ช่อื func() = a_function() นนั่ เอง บรรทดั ท่ี 2 โปรแกรมสรา้ งฟังกช์ นั ช่อื wapper() ทาหน้าทส่ี รา้ งขอ้ ความเพอ่ื ครอบก่อนทฟ่ี ังกช์ นั func() ห น้ า 455
จะทางาน โดยฟังกช์ นั ดงั กล่าวทาหน้าทเ่ี พม่ิ คา่ ใหก้ บั ตวั แปร wrapper.count ขน้ึ ครงั้ ละ 1 พรอ้ มกบั พมิ พ์ ขอ้ ความวา่ \"The function I modify has been called {0} times(s).\" โดย {0} หมายถงึ ขอ้ มลู ทถ่ี กู เมธ อด format() จดั รปู แบบให้ โดย {0} = wrapper.count นนั่ เอง บรรทดั ท่ี 5 โปรแกรมเรยี ก func() มา ทางาน ซง่ึ หมายถงึ เรยี กฟังกช์ นั a_function() มาทางานนัน่ เอง ในบรรทดั ท่ี 6 สรา้ งตวั แปรชอ่ื wrapper.count เพอ่ื ใชท้ างานกบั ฟังกช์ นั wrapper() เท่านนั้ โดยใชค้ านาหน้าเป็นช่อื ของฟังกช์ นั (wrapper) และตามดว้ ยชอ่ื ตวั แปร เช่น wrapper.count เป็นตน้ บรรทดั ท่ี 7 โปรแกรมคนื ค่ากลบั เป็น ฟังกช์ นั wrapper() ใหก้ บั ผเู้ รยี กใชง้ าน บรรทดั ท่ี 9 สรา้ งฟังกช์ นั แบบธรรมดาชอ่ื วา่ a_function() ทาหน้าทพ่ี มิ พข์ อ้ ความว่า \"I'm a normal function.\" บรรทดั ท่ี 12 เรยี กใชฟ้ ังกช์ นั logging_decorator() โดยสง่ ฟังกช์ นั a_function() เป็น พารามเิ ตอรใ์ หก้ บั ฟังก์ชนั ดงั กล่าว สง่ ผลใหต้ วั แปร modified_function = ฟังกช์ นั wrapper() เมอ่ื เรยี กใชง้ านตวั แปร modified_function ตามดว้ ยเครอ่ื งหมายวงเลบ็ (…) ต่อทา้ ยตวั แปรดงั กล่าว จะ สง่ ผลใหเ้ หมอื นกบั เป็นการเรยี กใชง้ านฟังกช์ นั wrapper() นนั่ เอง ผลลพั ธท์ ไ่ี ดแ้ สดงในตวั อยา่ งขา้ งบน สรปุ คอื โปรแกรมจะพมิ พข์ อ้ ความ \"The function I modify has been called 1 times(s).\" ก่อนแลว้ จงึ พมิ พข์ อ้ ความ \"I'm a normal function.\" ตามมา เมอ่ื เรยี กใชต้ วั แปร (ชนิดฟังกช์ นั ) modified_function อกี ครงั้ ค่า wrapper.count จะเพม่ิ ขน้ึ ไปเรอ่ื ยๆ จนกว่าจะยตุ กิ ารทางานของ โปรแกรม Decorator syntax (@) การเรยี กใชง้ าน Decorator ในหวั ขอ้ ก่อนหน้า ทาไดโ้ ดยการประกาศชอ่ื ตวั แปรเพอ่ื รบั ค่าออ็ ป เจก็ ตจ์ าก Decorator เชน่ modified_function = logging_decorator(a_function) จากนนั้ ใชต้ วั แปร ดงั กล่าวเรยี กใชง้ านฟังก์ชนั wrapper (modified_function()) ต่อไป แต่ผเู้ ขยี นโปรแกรมสามารถทาให้ โปรแกรมกระชบั ขน้ึ ได้ โดยใชส้ ญั ลกั ษณ์ @ นาหน้าช่อื ฟังกช์ นั ทต่ี อ้ งการสง่ เป็นพารามเิ ตอรใ์ หก้ บั Decorator และเรยี กใชฟ้ ังก์ชนั แบบปกตโิ ดยไมต่ อ้ งอา้ งถงึ ฟังกช์ นั Docorator อกี เช่น 1 def logging_decorator(func): 2 count = 0 3 def wrapper(): 4 wrapper.count += 1 5 print(\"The function I modify has been called {0} 6 times(s).\".format(wrapper.count)) 7 func() 8 9 wrapper.count = 0 10 return wrapper 11 12 @logging_decorator def a_function(): print(\"I'm a_function.\") ห น้ า 456
13 @logging_decorator 14 def some_function(): 15 print(\"I'm some_function.\") 16 17 a_function() 18 some_function() 19 ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื The function I modify has been called 1 times(s). I'm a_function. OUTPUT The function I modify has been called 1 times(s). I'm some_function. จากตวั อยา่ งดา้ นบน บรรทดั ท่ี 10 โปรแกรมประกาศวา่ @logging_decorator คอื การอา้ งถงึ ฟังกช์ นั Decorator ชอ่ื ว่า logging_decorator และจะใชฟ้ ังก์ชนั ช่อื a_function() ในบรรทดั ท่ี 11 เป็น พารามเิ ตอร์ เพอ่ื ให้ logging_decorator ทางาน และบรรทดั ท่ี 14 กท็ างานในลกั ษณะเดยี วกนั แต่ เปลย่ี นฟังกช์ นั ช่อื some_function() เป็นพารามเิ ตอรใ์ หก้ บั logging_decorator ทางานแทน สาหรบั การ เรยี กใชง้ าน โปรแกรมไมจ่ าเป็นตอ้ งสรา้ งตวั แปรใหมเ่ หมอื นในตวั อยา่ งทผ่ี ่านมา แต่ใหเ้ รยี กช่อื ฟังกช์ นั แบบปกติ เชน่ ในบรรทดั ท่ี 18 และ 19 ไพธอนจะรโู้ ดยอตั โนมตั วิ ่า เมอ่ื เรยี กฟังกช์ นั a_function() และ some_function() แลว้ จะตอ้ งส่งฟังกช์ นั ทงั้ สองเป็นพารามเิ ตอรใ์ หก้ บั ฟังกช์ นั Decorator ชอ่ื ว่า logging_decorator ทางานทนั ที 8. เมธอด .format() .format() เป็นเมธอดทใ่ี ชส้ าหรบั จดั รปู แบบการแสดงผลขอ้ มลู เช่น สตรงิ (String) และจานวน จรงิ (Floating-point) ซง่ึ มรี ปู แบบการทางานดงั น้ี การจดั รปู แบบของข้อความสตริง template.format(p0, p1, ... pN, k0=v0, k1=v1, ...) โดย template คอื ขอ้ ความสตรงิ ทต่ี อ้ งการแสดงผล, p0 – pN คอื ตาแหน่งทต่ี อ้ งการวางสตรงิ ใน template ซง่ึ โดยปกตสิ ามารถกาหนดได้ 2 แบบคอื กาหนดโดยใชเ้ ครอ่ื งหมาย {…} เชน่ {0}, {1}, …, {N} หรอื กาหนดโดยใช้ Keyword เช่น {city}, {name} และ k0=v0, k1=v1, kn=vn คอื การกาหนดค่า ใหก้ บั Keyword เช่น city= 'thailand', name = 'John' สาหรบั การใชง้ านแสดงไดด้ งั น้ี ตวั อย่างที่ 1: >>> \"We have {0} hectares planted to {1}.\".format(49, \"Apple\") 'We have 49 hectares planted to Apple.' ห น้ า 457
\"We have {0} hectares planted to {1}.\".format(49, \"Apple\") ตวั อย่างท่ี 2: >>> \"{monster} has now eaten {city}\".format(city='Tokyo', monster='Godzillar') Godzillar has now eaten Tokyo \"{monster} has now eaten {city}\".format(city='Tokyo', monster='Godzillar') ตวั อย่างที่ 3: >>> \"The {structure} sank {0} times in {1} years.\".format(3, 2, structure='castle') The castle sank 3 times in 2 years. การจดั รปู แบบของจานวนจริง {x:.yf}.format(floating-point) โดย {…} ใชร้ ะบุขอบเขตของจานวนจรงิ , x แสดงจานวนจรงิ หน้าจุดทศนิยม, : คอื จดุ เรมิ่ ตน้ ของ จดุ ทศนิยม, y คอื จานวนเลขทศนิยมหลงั จดุ ทศนิยม และ f คอื เลขจานวนจรงิ สาหรบั การใชง้ านแสดงได้ ดงั น้ี ตวั อย่างท่ี 1: >>> \"{0:.4f}\".format(0.1234567890) '0.1235' >>> \"{0:.4f}\".format(10.1234567890) '10.1235' ตวั อย่างที่ 2: >>> \"{0:8.4f}\".format(0.1234567890) #กำหนดเลขหน้ำจดุ ทศนิยมเทำ่ กบั 8 ตวั ' 0.1235' >>> \"{0:8.4f}\".format(10.987654321) ' 10.9877' ตวั อย่างที่ 3: ห น้ า 458
>>> \"{0:.4e}\".format(0.1234567890) #กำหนดเป็น exponential '1.2346e-01' ตวั อย่างที่ 4: >>> import math >>> \"sin({0:.4f}) = {1:.4e}\".format(0.1234567890, math.sin(0.123456789)) 'sin(0.1235) = 1.2314e-01' 9. อาเรยแ์ ละเมทริกซ์ (Array and Matrix) ไพธอนมพี นั ธมติ รทช่ี ว่ ยกนั พฒั นาความสามารถต่างๆ ใหก้ บั ไพธอนมากมาย ซง่ึ รวมถงึ ความสามารถในการประมวลผลคณติ ศาสตรช์ นั้ สงู ดว้ ย เช่น อาเรยห์ ลายมติ ,ิ เมทรกิ ซข์ นาดใหญ่, Optimization, Regression และ Fourier-transformation (มคี วามสามารถคลา้ ย MATLAB) เป็นต้น ซง่ึ โมดลู เหล่าน้คี อื SciPy (Scientific Python) และ NumPy โดยปกตโิ มดลู ทงั้ สองไมไ่ ดต้ ดิ ตงั้ มาพรอ้ มกบั ไพธอน จาเป็นตอ้ งตดิ ตงั้ เสยี ก่อน สามารถดาวน์โหลดไดจ้ าก URL: http://www.scipy.org/ หรอื จาก CD เมอ่ื ตดิ ตงั้ SciPy และ NumPy เสรจ็ เรยี บรอ้ ยแลว้ ทดสอบการใชง้ านดงั น้ี อาเรยก์ บั NumPy โมดลู สรา้ งอาเรยช์ นดิ จานวนเตม็ 1 มติ ทิ ม่ี ขี นาด 1 แถว 4 คอลมั ภ์ >>> import numpy as np >>> x = np.array([42,47,11, -55], int) >>> x array([42, 47, 11, -55]) >>> print(x[2]) #การเขา้ ถงึ อาเรยแ์ ถวท่ี 0 คอลมั ภท์ ่ี 2 11 สรา้ งอาเรยช์ นิดจานวนเตม็ 2 มติ ิ ขนาด 3 แถว 3 คอลมั ภ์ >>> x = np.array(((11,12,13), (21,22,23), (31,32,33))) >>> print(x) [[11 12 13] [21 22 23] [31 32 33]] >>> print(x[1][1]) #การเขา้ ถงึ อาเรยแ์ ถวท่ี 1 คอลมั ภท์ ่ี 1 22 สรา้ งอาเรยช์ นดิ จานวนเตม็ 3 มติ ิ ขนาด 2 แถว 2 คอลมั ภ์ และลกึ 2 หน่วย ห น้ า 459
>>> x = np.array((((111,112), (121,122)), ((211,212),(221,222)))) >>> print (x) [[[111 112] [121 122]] [[211 212] [221 222]]] >>> print(x[1][0][1]) #การเขา้ ถงึ อาเรยแ์ ถวท่ี 1 คอลมั ภท์ ่ี 0 และความลกึ 1 หน่วย 212 >>> print (x[1][1][1]) #การเขา้ ถงึ อาเรยแ์ ถวท่ี 1 คอลมั ภท์ ่ี 1 และความลกึ 1 หน่วย 222 Dep 1 212 222 Dep 0 Row 0 111 112 Row 1 121 122 Col 0 Col 1 Note: อาเรยใ์ นทางทฤษฎจี ะอา้ งถงึ ขอ้ มลู เรม่ิ จาก แถวท่ี 1, คอมลมั ภท์ ่ี 1 แต่ในทาง คอมพวิ เตอรจ์ ะอา้ ง แถวท่ี 0, คอมลมั ภท์ ่ี 0 แทน ในหนงั สอื เลม่ น้ีจะอา้ งตาแหน่งสมาชกิ ขอ้ มลู ในอาเรยแ์ บบคอมพวิ เตอร์ ฉะนนั้ ระวงั อยา่ สบั สน แสดงจานวนมติ ขิ องอาเรย์ โดยใชแ้ อตทรบิ วิ ต์ ndim >>> x = np.array( ((11,12,13), (21,22,23) )) >>> x.ndim 2 แสดงจานวนสมาชกิ ของอาเรย์ โดยใชเ้ มธอด shape >>> x = np.array(((7,3,0), (7,11,9), (15,3,7),(12,4,8))) >>> x.shape (4, 3) แสดงช่วงสมาชกิ ของอาเรยโ์ ดยใชส้ ญั ลกั ษณ์ [X:Y] โดย X คอื แถว และ Y คอื คอลมั ภ์ >>> x = np.array([42,47,11]) >>> x[:2] array([42, 47]) #แสดงสมาชกิ ตงั้ แต่คอลมั ภท์ ่ี 0 - 1 >>> x[0] #แสดงขอ้ มลู สมาชกิ ตาแหน่งคอลมั ภท์ ่ี 0 42 >>> x[1] = 49 #กาหนดค่าของขอ้ มลู สมาชกิ ในตาแหน่งคอลมั ภท์ ่ี 1 ห น้ า 460
>>> x array([42, 49, 11]) สรา้ งอาเรยช์ นดิ จานวนจรงิ 2 มติ ิ ขนาด 2 แถว 2 คอลมั ภ์ >>> x = np.array([[0.314, 0.5,17],[1.4142,0.67, 7]], float) >>> x array([[ 0.314 , 0.5 , 17. ], [ 1.4142, 0.67 , 7. ]]) >>> x[0]#แสดงขอ้ มลู สมาชกิ แถวท่ี 0 array([ 0.314, 0.5 , 17. ]) >>> x[1]#แสดงขอ้ มลู สมาชกิ แถวท่ี 1 array([ 1.4142, 0.67 , 7. ]) >>> x[0,2] #แสดงขอ้ มลู สมาชกิ แถวท่ี 0 คอลมั ภท์ ่ี 2 17.0 >>> x[:,0] #แสดงขอ้ มลู สมาชกิ ทกุ ๆ แถว คอลมั ภท์ ่ี 0 array([ 0.314 , 1.4142]) >>> x[:,1] #แสดงขอ้ มลู สมาชกิ ทุกๆ แถว คอลมั ภท์ ่ี 1 array([ 0.5 , 0.67]) >>> x[:,2] #แสดงขอ้ มลู สมาชกิ ทกุ ๆ แถว คอลมั ภท์ ่ี 2 array([ 17., 7.]) การเปลย่ี นรปู ร่างของอาเรยด์ ว้ ยเมธอด flatten() และ ravel() เมธอด flatten() และ revel() ทาหน้าทป่ี รบั เปลย่ี นรปู รา่ งของอาเรยใ์ หอ้ ยใู่ นแนวราบ >>> import numpy as np >>> x = np.array([[[ 0, 1], [ 2, 3], [ 4, 5], [ 6, 7]], [[ 8, 9], [10, 11], [12, 13], [14, 15]], [[16, 17], [18, 19], [20, 21], [22, 23]]]) >>> x.flatten() array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) การเปลย่ี นรปู รา่ งของอาเรยใ์ หม้ มี ติ ติ ามทต่ี อ้ งการดว้ ยเมธอด reshape() โดยอาเรยต์ น้ ฉบบั จะไมม่ กี ารเปลย่ี นแปลง >>> x = np.array(range(24)) #สรา้ งอาเรย์ 1 มติ ทิ ม่ี สี มาชกิ ตงั้ แต่ 0 - 23 >>> x ห น้ า 461
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) >>> y = x.reshape((3,4,2))#เปลย่ี นรปู รา่ งอาเรยเ์ ป็น 3 มติ ิ 4 แถว 2 คอลมั ภ์ ลกึ 3 >>> y array([[[ 0, 1], [ 2, 3], [ 4, 5], [ 6, 7]], [[ 8, 9], [10, 11], [12, 13], [14, 15]], [[16, 17], [18, 19], [20, 21], [22, 23]]]) >>> x array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) #อาเรยไ์ ม่เปลย่ี นรปู ร่าง Note: เมธอด reshape() จะปรบั ขนาดของอาเรย์ โดยมรี ปู แบบคอื reshape(deep, row, col) โดย deep = ขนาดความลกึ ของอาเรย,์ row = จานวนแถว, col = จานวนคอลมั ภ์ การเช่อื มอาเรยเ์ ขา้ ดว้ ยกนั โดยใชเ้ มธอด concatenate() >>> x = np.array([11,22]) >>> y = np.array([18,7,6]) >>> z = np.array([1,3,5]) >>> np.concatenate((x,y,z)) array([11, 22, 18, 7, 6, 1, 3, 5]) เพมิ่ มติ ใิ หมใ่ หก้ บั อาเรย์ โดยใชแ้ อตทรบิ วิ ต์ newaxis >>> x = np.array([2,5,18,14,4]) >>> x array([ 2, 5, 18, 14, 4]) >>> y = x[:, np.newaxis] >>> y array([[ 2], [ 5], [18], [14], [ 4]]) กาหนดค่าเรมิ่ ตน้ เป็น 0 และ 1 ใหก้ บั อาเรย์ >>> np.ones((2,3)) #กาหนดคา่ เรม่ิ ตน้ ใหก้ บั อาเรย์ 2 x 3 เป็น 1.0 (float) array([[ 1., 1., 1.], [ 1., 1., 1.]]) ห น้ า 462
>>> np.ones((3,4),dtype=int) #กาหนดค่าเรม่ิ ตน้ ใหก้ บั อาเรย์ 2 x 3 เป็น 1 (int) array([[1, 1, 1, 1], #กาหนดคา่ เรม่ิ ตน้ ใหก้ บั อาเรย์ 2 x 4 เป็น 0.0 (float) [1, 1, 1, 1], [1, 1, 1, 1]]) >>> np.zeros((2,4)) array([[ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]) รเี ซต็ (Reset) ขอ้ มลู สมาชกิ ในอาเรยใ์ หเ้ ป็น 1 หรอื 0 ดว้ ยเมธอด ones_like() และ zeros_like() >>> x = np.array([2,5,18,14,4]) >>> np.ones_like(x) array([1, 1, 1, 1, 1]) >>> np.zeros_like(x) array([0, 0, 0, 0, 0]) เลขคณิ ตเมตริกซ์ ในหวั ขอ้ ทผ่ี ่านมาไดก้ ล่าวถงึ การสรา้ งอาเรยใ์ นหลากหลายรปู แบบ ซง่ึ การสรา้ งอาเรยเ์ ป็น พน้ื ฐานของการสรา้ งเมตรกิ ซด์ ว้ ย ในบทน้จี ะกลา่ วถงึ การประมวลผลคณติ ศาสตรก์ บั เมตรกิ ซ์ เช่น การ บวกเมตรกิ ซ,์ การลบ, การคณู , Skalar product, Cross product และการดาเนินการอ่นื ๆ ไพธอนใชต้ วั ดาเนินการพน้ื ฐานคอื + (บวก), - (ลบ), * (คณู ), / (หาร), ** (ยกกาลงั ), % (modulo) กบั อาเรย์ การดาเนินการพน้ื ฐานใดๆ ขนาดของอาเรยจ์ ะตอ้ งมขี นาดเทา่ กนั >>> x = np.array([1,5,2]) >>> y = np.array([7,4,1]) >>> x + y array([8, 9, 3]) >>> x * y array([ 7, 20, 2]) >>> x - y array([-6, 1, 1]) >>> x / y array([0, 1, 2]) >>> x % y array([1, 1, 0]) การรวมเวกเตอร์ การรวมเวกเตอร์ หมายถงึ การบวกหรอื ลบกนั ของเวกเตอรต์ งั้ แต่ 2 เวกเตอร์ ขน้ึ ไป ผลลพั ธท์ ่ี ไดเ้ ป็นปรมิ าณเวกเตอร์ เรยี กวา่ เวกเตอรล์ พั ธ์ (Resultant Vector) ซง่ึ พจิ ารณาได้ ดงั น้ี ห น้ า 463
1234 y (8,3) 1234 (3,2) y x x (5,1) (-2,1) x+y y x-y 012345 012345 >>> x = np.array([3,2]) >>> y = np.array([5,1]) >>> z = x + y >>> z array([8, 3]) >>> z = x – y >>> z array([-2, 1]) การคณู สเกลาร์ (Scalar product หรอื dot product แทนดว้ ยเครอ่ื งหมาย \" . \" ) จากนยิ ามของการคณู สเกลาร์ ���⃗���. ���⃗⃗��� = |������||������|������������������������(���⃗��� , ���⃗⃗���) = ���⃗���. ���⃗⃗��� = ������1������1 + ������2������2 + ������3������3 >>> x = np.array([1,2,3]) >>> y = np.array([-7,8,9]) >>> np.dot(x,y) 36 >>> dot = np.dot(x,y) >>> x_modulus = np.sqrt((x*x).sum()) >>> y_modulus = np.sqrt((y*y).sum()) >>> cos_angle = dot / x_modulus / y_modulus #cosinus of angle between x and y >>> angle = np.arccos(cos_angle) >>> angle 0.80823378901082499 >>> angle * 360 / 2 / np.pi # angle in degrees 46.308384970187326 การคณู เมตรกิ ซส์ ามารถทาไดโ้ ดยการใชเ้ มธอด matrix() รว่ มกบั เครอ่ื งหมาย * >>> x = np.matrix( ((2,3), (3, 5)) ) >>> y = np.matrix( ((1,2), (5, -1)) ) >>> x * y matrix([[17, 1], [28, 1]]) Note: ไมส่ ามารถใชอ้ าเรยท์ าการคณู เมตรกิ ซไ์ ดโ้ ดยตรง เชน่ >>> x = np.array( ((2,3), (3, 5)) ) >>> y = np.array( ((1,2), (5, -1)) ) >>> x * y array([[ 2, 6], [15, -5]]) ห น้ า 464
10. การสร้างเน็ตเวิรค์ กราฟด้วย NetworkX NetworkX เป็นโมดลู ทเ่ี สรมิ ความสามารถของไพธอนทเ่ี กย่ี วขอ้ งกบั การบรหิ ารจดั การเน็ตเวริ ค์ กราฟ เพ่อื ใชส้ าหรบั วเิ คราะหข์ อ้ มลู ต่างๆ ท่จี าเป็นตอ้ งอาศยั ความสามารถของกราฟชว่ ยในการทางาน NetworkX ไมไ่ ดต้ ดิ ตงั้ มาพรอ้ มกบั ไพธอน ดงั นนั้ ผเู้ ขยี นจาเป็นตอ้ งตดิ ตงั้ โปรแกรม NetworkX เพม่ิ เตมิ โดยดาวน์โหลดไดจ้ าก URL: http://networkx.github.io/ หรอื จาก CD ซง่ึ เวอรช์ นั ลา่ สดุ คอื networkx- 0.33.win32 ใหท้ าการตดิ ตงั้ โดยคลกิ Next > ไปเรอ่ื ยๆ จนกว่าจะเสรจ็ สน้ิ การตดิ ตงั้ เมอ่ื ตดิ ตงั้ เสรจ็ จะ สามารถเรยี กใชจ้ ากไพธอนไดท้ นั ที เรม่ิ ตน้ การสรา้ งกราฟ ในอนั ดบั แรกจะแนะนาการสรา้ ง empty graph ซง่ึ มรี ปู แบบคาสงั่ ดงั น้ี (NetworkX_1.py) 1 import networkx as nx 2 3 G=nx.Graph() 4 5 print(G.nodes()) 6 print(G.edges()) 7 8 print(type(G.nodes())) 9 print(type(G.edges())) ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื [] [] OUTPUT <type 'list'> <type 'list'> จากตวั อยา่ งดา้ นบน บรรทดั ท่ี 1 นาเขา้ โมดลู networkx สาหรบั ใชส้ รา้ งกราฟ โดยเปลย่ี นเป็นชอ่ื เล่นคอื nx บรรทดั ท่ี 3 สรา้ งออ็ ปเจก็ ตข์ องกราฟชอ่ื วา่ G ซง่ึ เป็นกราฟว่าง บรรทดั ท่ี 5, 6 ทดสอบพมิ พค์ า่ ของ โหนดและเสน้ กราฟ ผลลพั ธท์ ไ่ี ดค้ อื กราฟทไ่ี ม่มโี หนดและเสน้ เชอ่ื มใดๆ ขอ้ มลู ทใ่ี ชเ้ กบ็ โหนดและเสน้ เชอ่ื มจะเป็นขอ้ มลู ชนิดลสิ ต์ การเพม่ิ โหนดใหก้ ราฟ การเพมิ่ โหนดใหก้ บั กราฟจะใชเ้ มธอด add_node(node_name) และเพม่ิ โหนดพรอ้ มๆ กนั หลายๆ โหนดจะใชค้ าสงั่ add_nodes_from(list_node) เชน่ (NetworkX_2.py) 1 mport networkx as nx 2 3 G=nx.Graph() 4 5 # adding just one node: 6 G.add_node(\"a\") ห น้ า 465
7 # a list of nodes: 8 G.add_nodes_from([\"b\",\"c\"]) 9 10 print(\"Nodes of graph: \") 11 print(G.nodes()) 12 print(\"Edges of graph: \") 13 print(G.edges()) ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื Nodes of graph: ['a', 'c', 'b'] OUTPUT Edges of graph: [] จากตวั อยา่ งดา้ นบน บรรทดั ท่ี 6 แสดงคาสงั่ สาหรบั เพม่ิ โหนดใหก้ บั กราฟเพยี ง 1 โหนดเท่านนั้ และ บรรทดั ท่ี 7 แสดงการเพม่ิ โหนดหลายๆ โหนดพรอ้ มๆ กนั การเพมิ่ เสน้ เชอ่ื ม (edges) ใหก้ ราฟ การเพม่ิ เสน้ เชอ่ื มของกราฟสามารถทาไดโ้ ดยใชเ้ มธอด add_edge(startnode, endnode) สาหรบั เพมิ่ 1 เสน้ แต่ถา้ ตอ้ งการเพมิ่ เสน้ เช่อื มมากกวา่ 1 เสน้ ใหใ้ ช้ * แทน เชน่ (NetworkX_3.py) 1 import networkx as nx 2 3 G=nx.Graph() 4 G.add_node(\"a\") 5 G.add_nodes_from([\"b\",\"c\"]) 6 7 G.add_edge(1, 2) 8 e = (\"d\", \"e\") 9 G.add_edge(*e) 10 e = (\"a\", \"b\") 11 G.add_edge(*e) 12 13 print(\"Nodes of graph: \") 14 print(G.nodes()) 15 print(\"Edges of graph: \") 16 print(G.edges()) ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื Nodes of graph: ['a', 1, 'c', 'b', 'e', 'd', 2] OUTPUT Edges of graph: [('a', 'b'), (1, 2), ('e', 'd')] จากตวั อยา่ งดา้ นบน บรรทดั ท่ี 7 แสดงการเพม่ิ เสน้ เช่อื มลงในกราฟโดยใชค้ าสงั่ G.add_edge(1, 2) (สรา้ งเสน้ เช่อื มระหวา่ งโหนดท่ี 1 และ 2) แต่ในตวั อยา่ งน้ยี งั ไมเ่ คยสรา้ งโหนด 1 และ 2 มาก่อน ดงั นนั้ เมอ่ื ใชค้ าสงั่ เพม่ิ เสน้ เชอ่ื ม โปรแกรมจะสรา้ งโหนด 1 และ 2 ใหอ้ ตั โนมตั ิ บรรทดั ท่ี 8 โปรแกรมสรา้ งเสน้ ห น้ า 466
เชอ่ื มจาก \"d\" ไป \"e\" ดว้ ยตวั แปรชนิดทพั เพลิ ชอ่ื e จากนนั้ นาตวั แปรดงั กล่าวเป็นพารามเิ ตอรใ์ หก้ บั เมธ อด add_edge(*e) ในบรรทดั ท่ี 9 ซง่ึ สญั ลกั ษณ์ * หมายถงึ สามารถเพมิ่ เสน้ เช่อื มไดม้ ากกวา่ 1 เสน้ บรรทดั ท่ี 10 และ 11 กเ็ ป็นวธิ กี ารเพม่ิ เสน้ เช่อื มเช่นเดยี วกนั แต่เชอ่ื มระหวา่ ง \"a\" ไป \"b\" แทน ดงั นนั้ ผลลพั ธท์ ไ่ี ดใ้ นตวั อยา่ ง OUTPUT ขา้ งบนคอื โหนดในกราฟจะมที งั้ หมด 7 โหนด ('a', 1, 'c', 'b', 'e', 'd', 2) และมเี สน้ เชอ่ื มทงั้ หมด 3 เสน้ คอื เสน้ เช่อื มจาก 'a' ไปยงั 'b', 1 ไปยงั 2 และ 'e' ไปยงั 'd' เมอ่ื ตอ้ งการเพม่ิ เสน้ เช่อื มมากกว่า 1 เสน้ สามารถใชเ้ มธอด add_edges_from() ดงั น้ี G.add_edges_from([(\"a\",\"c\"),(\"c\",\"d\"), (\"a\",1), (1,\"d\"), (\"a\",2)]) และสามารถ plot เป็นกราฟไดโ้ ดยใชง้ านรว่ มกบั โมดลู matplotlib ดงั น้ี (NetworkX_4.py) 1 import networkx as nx 2 import matplotlib.pyplot as plt 3 4 G=nx.Graph() 5 G.add_node(\"a\") 6 G.add_nodes_from([\"b\",\"c\"]) 7 8 G.add_edge(1,2) 9 e = (\"d\", \"e\") 10 G.add_edge(*e) 11 e = (\"a\", \"b\") 12 G.add_edge(*e) 13 G.add_edges_from([(\"a\",\"c\"),(\"c\",\"d\"), (\"a\",1), (1,\"d\"), (\"a\",2)]) 14 15 print(\"Nodes of graph: \") 16 print(G.nodes()) 17 print(\"Edges of graph: \") 18 print(G.edges()) 19 20 nx.draw(G) 21 plt.savefig(\"simple_path.png\") # save as png 22 plt.show() # display ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื ห น้ า 467
11. การพรอ็ ตกราฟ (Plot Graph) ด้วย MATPLOTLIB, NUMPY และ SCIPY ไพธอนไดร้ บั การสนบั สนุนดา้ นการพรอ็ ตกราฟโดยใชโ้ มดลู MATPLOTLIB, NUMPY และ SCIPY ทางานรว่ มกนั ซง่ึ โมดลู เหลา่ น้ไี มไ่ ดต้ ดิ ตงั้ มาพรอ้ มกบั ไพธอน จงึ จาเป็นตอ้ งตดิ ตงั้ เพม่ิ ทหี ลงั แต่ ในปัจจบุ นั ไดม้ กี ารรวบรวมโมดลู เหลา่ น้ไี วเ้ ป็นแพค็ เกจเดยี วกนั ช่อื ว่า Anaconda-1.9.1-Windows- x86_64.exe ขนาดประมาณ 370 MB หรอื คน้ หาไดจ้ าก CD หรอื สามารถโหลดไดจ้ าก URL: http://continuum.io/downloads เมอ่ื ดาวน์โหลดเสรจ็ เรยี บรอ้ ยแลว้ ใหท้ าการตดิ ตงั้ โปรแกรมซง่ึ สามารถ คลกิ Next> ไปเรอ่ื ยๆ จนกว่าจะเสรจ็ สน้ิ เมอ่ื ตดิ ตงั้ เสรจ็ สน้ิ แลว้ จะปรากฏโปรแกรมช่อื ว่า anaconda command prompt ใหผ้ ใู้ ชค้ ลกิ เพ่อื เปิดโปรแกรม และจะปรากฏ prompt เพอ่ื รบั คาสงั่ จากผใู้ ช้ ซง่ึ โปรแกรมดงั กล่าวมโี ปรแกรมทงั้ หมดรวมอยู่ คอื Python, MATPLOTLIB, NUMPY และ SCIPY เรมิ่ ตน้ การพรอ็ ตกราฟ ใหเ้ ขยี นโปรแกรมดงั ต่อไปน้ี แลว้ บนั ทกึ แฟ้มช่อื plot1.py และเกบ็ ไวใ้ นไดเรคทรอรข่ี อง anaconda เชน่ C:\\Users\\UserName\\Anaconda และสงั่ รนั โปรแกรมดงั น้ี python plot1.py 1 import matplotlib.pyplot as pyp 2 x = [0, 2, 4, 6, 8] 3 y = [0, 3, 3, 7, 0] 4 pyp.plot(x, y) 5 pyp.show() 6 pyp.savefig(\"MyFirstPlot.png\") ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื ห น้ า 468
เมอ่ื รนั โปรแกรมแลว้ กราฟทถ่ี กู สรา้ งขน้ึ จะบนั ทกึ เป็นไฟลร์ ปู ภาพช่อื วา่ \"MyFirstPlot.png\" ดว้ ย ในไดเรคทรอรป่ี ัจจุบนั แสดงการพรอ็ ตกราฟชนิด Sine Wave (plot2.py) 1 import numpy 2 import pylab 3 4 t = numpy.arange(0.0, 1.0+0.01, 0.01) 5 s = numpy.cos(numpy.pi*4*t) 6 pylab.plot(t, s) 7 8 pylab.xlabel('time (s)') 9 pylab.ylabel('cos(4t)') 10 pylab.title('Simple cosine') 11 pylab.grid(True) 12 pylab.savefig('simple_cosine') 13 14 pylab.show() ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื ห น้ า 469
แสดงการพรอ็ ต Contour (plot3.py) 1 import scipy 2 import pylab 3 import matplotlib.pyplot as plt 4 5 x,y = scipy.ogrid[-1.:1.:.01, -1.:1.:.01] 6 z = x**3-3*x*y**2 7 pylab.imshow(z, origin='lower', extent=[-1,1,-1,1]) 8 plt.contour(z, origin='lower', extent=[-1,1,-1,1]) 9 pylab.xlabel('x') 10 pylab.ylabel('y') 11 pylab.title('Saddle') 12 pylab.savefig('Saddle') 13 plt.show() ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื ห น้ า 470
แสดงการพรอ็ ตโดยใชข้ อ้ มลู จากแฟ้ม .CVS (plot4.py) 1 import scipy 2 import pylab 3 import matplotlib.pyplot as plt 4 5 x,y = scipy.ogrid[-1.:1.:.01, -1.:1.:.01] 6 z = x**3-3*x*y**2 7 pylab.imshow(z, origin='lower', extent=[-1,1,-1,1]) 8 plt.contour(z, origin='lower', extent=[-1,1,-1,1]) 9 pylab.xlabel('x') 10 pylab.ylabel('y') 11 pylab.title('Saddle') 12 pylab.savefig('Saddle') 13 plt.show() ผลลพั ธท์ ไ่ี ดเ้ มอ่ื สงั่ รนั โปรแกรมคอื ภาษาไพธอนสนบั สนุนใหส้ ามารถพฒั นาโปรแกรมเพ่อื แกป้ ัญหาไดม้ ากมาย ซง่ึ ผเู้ ขยี นไมส่ ามารถกล่าว ไวใ้ นหนงั สอื เล่มน้ไี ดท้ งั้ หมด แต่ผเู้ ขยี นหวงั เป็นอยา่ งยงิ่ วา่ เน้อื หาทงั้ หมดในหนงั สอื เล่มน้จี ะเพยี งพอต่อ การทาความเขา้ ใจและเป็นพน้ื ฐานใหก้ บั ผอู้ ่านสามารถนาไปต่อยอดไดใ้ นอนาคต จบบทท่ี 18 ห น้ า 471
จบภาค 3 ห น้ า 472
ภาคท่ี 4 การเขียนโปรแกรมกราฟฟิ กด้วยไพธอน ( Graphic Programming) บทท่ี 19 การเขยี นโปรแกรมกราฟฟิกดว้ ยไพธอน
บทท่ี 19 การเขียนโปรแกรมกราฟฟิ กด้วยไพธอน (Graphics Programming with Python) รปู แบบการปฏสิ มั พนั ธก์ บั ระบบคอมพวิ เตอรใ์ นปัจจบุ นั มี 2 รปู แบบใหญ่ๆ คอื แบบป้อนคาสงั่ ที ละบรรทดั (Command line interface) หมายถงึ การตดิ ต่อส่อื สารระหวา่ งผใู้ ชก้ บั ระบบคอมพวิ เตอรด์ ว้ ย การป้อนคาสงั่ (Command) จากแป้นพมิ พเ์ พอ่ื ใหร้ ะบบปฏบิ ตั กิ ารประมวลผลตามทผ่ี ใู้ ชต้ อ้ งการ เช่น MS-DOS และ ยนู ิกซ-์ ลนิ ุกซ์ เป็นตน้ และแบบกราฟฟิก คอื การตดิ ต่อสอ่ื สารกบั ระบบคอมพวิ เตอรโ์ ดย อาศยั อนิ เตอรเ์ ฟสแบบกราฟฟิก ซง่ึ ประกอบไปดว้ ยเมนู รปู ภาพ ไอคอน โดยการใชเ้ มาส์คลกิ เพอ่ื สงั่ งาน เช่น ระบบปฏบิ ตั กิ ารวนิ โดวส์ และระบบปฏบิ ตั กิ าร Machintosh เป็นตน้ ในบททผ่ี ่านๆ มาจะ เป็นการใชง้ านดว้ ยวธิ กี ารแบบป้อนคาสงั่ (Command line) เป็นส่วนใหญ่ แต่สาหรบั ในบทน้จี ะอธบิ าย การสรา้ งอนิ เตอรเ์ ฟสแบบกราฟฟิกดว้ ยภาษาไพธอนเป็นหลกั ไพธอนไดร้ บั การสนบั สนุนโมดลู สาหรบั พฒั นา GUI (Graphic User Interface) ไวม้ ากมาย เชน่ Tkinter, wxPython, JPython, wxWidgets, Qt, Gtk+, FLTK, FOX และ OpenGL เป็นตน้ ซง่ึ มี รายละเอยี ดเฉพาะโมดลู ทส่ี าคญั ๆ ดงั น้คี อื Tkinter เป็นโมดลู ทพ่ี ฒั นามาจาก Tk GUI Toolkit ซง่ึ ทางานอยบู่ นระบบปฏบิ ตั กิ ารยนู กิ ซม์ า ก่อน ไพธอนไดเ้ ลอื กโมดลู น้ใี นการพฒั นากราฟฟิกบนไพธอนเป็นหลกั wxPython เป็นโมดลู ทถ่ี ูกพฒั นาขน้ึ เพอ่ื ใหท้ างานอยบู่ นระบบปฏบิ ตั กิ ารวนิ โดวสเ์ ป็นหลกั และ เป็นลขิ สทิ ธแิ ์ บบ Open source อ่านขอ้ มลู เพมิ่ เตมิ ไดท้ ่ี http://wxpython.org ห น้ า 473
JPython เป็นโมดลู ทพ่ี ฒั นาขน้ึ เพ่อื ใหไ้ พธอนสามารถทางานรว่ มกบั กราฟฟิกของภาษาจาวาได้ อ่านขอ้ มลู เพม่ิ เตมิ ไดท้ ่ี http://www.jython.org อ่นื ๆ สามารถอ่านไดจ้ าก https://wiki.python.org/moin/GuiProgramming สาหรบั ในหนงั สอื เล่มน้จี ะเน้นการสรา้ ง GUI ดว้ ย Tkinter เป็นหลกั 1. แนวความคิดในการออกแบบ GUI ก่อนการพฒั นา GUI ดว้ ยไพธอน ผเู้ ขยี นโปรแกรมจาเป็นตอ้ งทาการออกแบบหน้าตาของ GUI เสยี ก่อน โดยการสเกต็ ช์ (Sketch) คอื การออกแบบโปรแกรมเป็นภาพบนกระดาษ หรอื ออกแบบดว้ ย โปรแกรมสาหรบั สรา้ งงานกราฟฟิกดว้ ยคอมพวิ เตอรอ์ ยา่ งคร่าวๆ เสยี ก่อน ดงั รปู ท่ี 19.1 รปู ท่ี 19.1 การสเกต็ ช์ GUI อยา่ งคร่าวๆ บนกระดาษ จากรปู ท่ี 19.1 แสดงการออกแบบ GUI บนกระดาษแบบหยาบๆ เพอ่ื ใหเ้ หน็ ภาพรวมของ โปรแกรมและหน้าตาครา่ วๆ ก่อนการเขยี นโปรแกรม ภาพทส่ี เกต็ ชค์ วรจะมรี ายละเอยี ดต่างๆ เชน่ หน้าต่างหลกั ของโปรแกรม (Main window) เมนูต่างๆ ทส่ี อดคลอ้ งกบั งาน ป่มุ แทป็ ไอคอน เมนูยอ่ ย และภาพ เป็นตน้ จากนนั้ ทาการเชอ่ื มโยงหน้าต่างหรอื เมนูต่างๆ เขา้ ไวด้ ว้ ยกนั โดยใชเ้ สน้ และลกู ศร ดงั รปู ท่ี 19.2 ห น้ า 474
รปู ท่ี 19.2 การเช่อื มโยงหน้าต่างหรอื เมนูต่างๆ ทส่ี มั พนั ธก์ นั สาหรบั ตวั อยา่ งการเช่อื มโยงระหวา่ งหน้าต่างเขา้ ดว้ ยกนั เชน่ เมอ่ื ผใู้ ชง้ านกดป่มุ Save as… โปรแกรมควรจะปรากฎหน้าต่างเพ่อื ใหผ้ ใู้ ชเ้ ลอื กตาแหน่งไดเรคทรอรท่ี ต่ี อ้ งการบนั ทกึ แฟ้มลงบน ฮารด์ ดสิ กเ์ ป็นตน้ ตวั อย่างการออกแบบ สมมตุ วิ า่ ผเู้ ขยี นโปรแกรมต้องการออกแบบ GUI อยา่ งงา่ ย เพ่อื ทาหน้าทแ่ี ปลงคา่ หน่วยวดั ระยะทางจากฟุต (feet) เป็นเมตร (meters) ตวั อยา่ งรปู ทส่ี เกต็ ชไ์ ดแ้ สดงดงั รปู ท่ี 19.3 Converting Feet to meters Is equivalent to Feet meters calculate รปู ท่ี 19.3 แสดงภาพสเกต็ ชข์ องโปรแกรมแปลงจาก feet เป็น meters จากรปู ท่ี 19.3 ผใู้ ชจ้ ะป้อนตวั เลขจานวนจรงิ ในชอ่ ง Feet เมอ่ื กดป่มุ calculate โปรแกรมจะทาการแปลงค่าจานวนจรงิ ทป่ี ้อนใหก้ บั โปรแกรมเป็นเมตรและแสดงใน meters ขนั้ ตอนต่อไป ใหผ้ เู้ ขยี นโปรแกรมทาการวาดเสน้ กรดิ เพ่อื ใชก้ าหนดขอบเขต สาหรบั จดั วางตาแหน่ง (Layout) ของอ๊อปเจก็ ตต์ ่างๆ ในโปรแกรม จากตวั อยา่ งดา้ นบน จะทาการ กาหนดเสน้ กรดิ เป็น 3 แถว 3 คอลมั น์ดงั รปู ท่ี 19.4 ห น้ า 475
1 Column Grid 3 2 Converting Feet to meters 1 Low Feet Grid 2 Is equivalent to meters 3 calculate (Column, Low) = 3, 1 = Feet รปู ท่ี 19.4 แสดงการวาดเสน้ กรดิ 3 x 3 ลงบนภาพสเกต็ ช์ สาหรบั ตวั อยา่ งโปรแกรมแปลงฟุตเป็นเมตร แสดงในตวั อยา่ งท่ี 19.1 Program Example 19.1: Converting Feet to Meters 1 from tkinter import * 2 from tkinter import ttk 3 4 def calculate(*args): 5 try: 6 value = float(feet.get()) 7 meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0) 8 except ValueError: 9 pass 10 11 root = Tk() 12 root.title(\"Converting Feet to Meters\") 13 14 mainframe = ttk.Frame(root, padding=\"3 3 12 12\") 15 mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) 16 mainframe.columnconfigure(0, weight=1) 17 mainframe.rowconfigure(0, weight=1) 18 19 feet = StringVar() 20 meters = StringVar() 21 22 feet_entry = ttk.Entry(mainframe, width=7, textvariable=feet) 23 feet_entry.grid(column=2, row=1, sticky=(W, E)) 24 25 ttk.Label(mainframe, textvariable=meters).grid(column=2, row=2, sticky=(W, E)) 26 ttk.Button(mainframe, text=\"Calculate\", command=calculate).grid(column=3, row=3, sticky=W) 27 28 ttk.Label(mainframe, text=\"feet\").grid(column=3, row=1, sticky=W) 29 ttk.Label(mainframe, text=\"is equivalent to\").grid(column=1, row=2, sticky=E) ห น้ า 476
30 ttk.Label(mainframe, text=\"meters\").grid(column=3, row=2, sticky=W) 31 32 for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) 33 34 feet_entry.focus() 35 root.bind('<Return>', calculate) 36 37 root.mainloop() เมอ่ื รนั โปรแกรมจะไดผ้ ลลพั ธด์ งั รปู ท่ี 19.5 ใหผ้ ใู้ ชง้ านใส่จานวนฟุตทต่ี อ้ งการแปลงเป็นเมตร และกดป่มุ calculate จะไดผ้ ลลพั ธด์ งั รปู รปู ท่ี 19.5 แสดงผลการรนั โปรแกรม Converting Feet to Meters จากตวั อยา่ งโปรแกรมท่ี 19.5 บรรทดั ท่ี 1 โปรแกรมทาการนาเขา้ โมดลู tkinter หรอื ไลบราร่ี Tk เพอ่ื ใชส้ าหรบั สรา้ ง GUI และบรรทดั ท่ี 2 เป็นคลาสทเ่ี พมิ่ เตมิ ความสามารถใหก้ บั tkinter สาหรบั สรา้ ง เครอ่ื งมอื ต่างๆ (themed widgets) สงั เกตวา่ โปรแกรมนาเขา้ ฟังชนั และเมธอดทงั้ หมดจากโมดลู tkinter โดยเรยี กใชค้ าสงั่ from tkinter import * ซง่ึ สง่ ผลใหส้ ามารถเรยี กใชฟ้ ังชนั และเมธอดโดยไมต่ อ้ งอา้ ง tkinter ก่อนการใชง้ าน แต่สาหรบั คาสงั่ from tkinter import ttk คอื โปรแกรมตอ้ งการโหลดคลาสช่อื ttk เขา้ มาเสรมิ การทางาน (โหลดซอ้ น) คลาสทโ่ี หลดเขา้ มาก่อนดว้ ยสญั ลกั ษณ์ * จากบรรทดั ท่ี 1 นนั่ เอง และตอ้ งอา้ งช่อื คลาส (ttk) ในการใชง้ านก่อนเสมอเพราะถา้ ไมอ่ า้ งช่อื ttk ก่อน โปรแกรมจะมองวา่ เรยี กใชง้ านเมธอดหรอื คลาสจากคาสงั่ * แทนนนั่ เอง บรรทดั ท่ี 4 สรา้ งเมธอดชอ่ื calculate() เพอ่ื คานวณการแปลงจากฟุตเป็นเมตร บรรทดั ท่ี 11 – 17 เป็นการสรา้ งหน้าต่างหลกั (Main window) ช่อื root โดยการหนด title ใหม้ ี ขอ้ ความวา่ \"Converting Feet to Meters\" บรรทดั ท่ี 14 โปรแกรมทาการสรา้ งเฟรม (Frame widget) ชอ่ื วา่ mainframe ในหน้าต่างหลกั เพ่อื รองรบั เครอ่ื งมอื หรอื tools ต่างๆ ทจ่ี ะสรา้ งขน้ึ ในลาดบั ต่อไป บรรทดั ท่ี 19 – 30 เป็นการสรา้ ง widgets ต่างๆ ลงบนเฟรม (mainframe) คอื Label, Entry และ Button โดยอยภู่ ายใตก้ รดิ (Grid) ทก่ี าหนด เชน่ feet_entry.grid(column=2, row=1, sticky=(W, E)) คอื Entry หรอื ช่องทเ่ี ตรยี มไวใ้ หผ้ ใู้ ชง้ านใสจ่ านวนฟุตทต่ี อ้ งการแปลง โดยวางในตาแหน่งแนว ระหวา่ งตะวนั ออก (E) และตะวนั ตก (W) ห น้ า 477
บรรทดั ท่ี 32 เป็นการกาหนดใหโ้ ปรแกรมทาการวาด Widgets ต่างๆ ทอ่ี ยใู่ นเฟรมลงบนกรดิ และบรรทดั ท่ี 34 โปรแกรมทาการตรวจจบั เมอ่ื ผใู้ ชก้ ดป่มุ enter บนแป้นพมิ พ์ (root.bind('<Return>', calculate)) จะทาใหโ้ ปรแกรมเรยี กเมธอด calculate() เพอ่ื ประมวลผลสมการแปลงหน่วยจากฟุตเป็น เมตรทนั ที ในบรรทดั สดุ ทา้ ย (37) โปรแกรมบอกให้ Tk ทางานในลกั ษณะวนลปู ไปเรอ่ื ยๆ เพ่อื รอรบั เหตุการณ์ (event) ต่างๆ ทจ่ี ะเกดิ ขน้ึ กบั โปรแกรม 2. การสร้าง GUI ด้วย Tk ก่อนการสรา้ งกราฟฟิกจาก Tk หรอื Tkinter ผเู้ ขยี นโปรแกรมจาเป็นตอ้ งเขา้ ใจถงึ แนวความคดิ และหลกั การทางานของ Tk เสยี ก่อน เพอ่ื เป็นพน้ื ฐานในการสรา้ ง GUI ทส่ี มบรู ณ์ต่อไป Tk ประกอบไป ดว้ ย 3 ส่วนทส่ี าคญั คอื widgets, geometry management และ event handling ซง่ึ มรี ายละเอยี ดดงั น้ี 1. Widgets Widgets คอื สง่ิ ต่างๆ (บางครงั้ เรยี กว่า อ๊อปเจก็ ต)์ ทป่ี รากฎอยบู่ นจอภาพ เชน่ Button, Label, Frame, checkbox, tree views, scrollbars, text areas เป็นตน้ ดงั รปู ท่ี 19.6 รปู ท่ี 19.6 แสดงตวั อยา่ ง Widgets บนระบบปฏบิ ตั กิ ารต่างๆ อา้ งองิ จาก http://www.tkdocs.com/ Widgets ต่างๆ เหล่าน้ีถกู ออกแบบใหม้ ลี กั ษณะการทางานแบบลาดบั ชนั้ นนั่ คอื การสรา้ ง GUI ใดๆ ใหป้ รากฎบนจอภาพ จะเรมิ่ ตน้ สรา้ งจากลาดบั ชนั้ ทเ่ี รยี กว่า root window (root) ขน้ึ เสยี ก่อน ดงั รปู ท่ี 19.7 ลาดบั ชนั้ ท่ี 2 จงึ สรา้ งเฟรม (Content frame) หรอื ผนื ผา้ (Canvas) เพ่อื บรรจุ widgets ต่างๆ ลงบน root window ในลาดบั ชนั้ ท่ี 3 เป็นการเพม่ิ Widgets ต่างๆ ทไ่ี ดอ้ อกแบบไว้ ห น้ า 478
(บนกระดาษ) ลงบนเฟรมหรอื Canvas ทไ่ี ดจ้ ดั เตรยี มไว้ สาหรบั การควบคมุ การทางานของ Widgets จะเป็นแบบลาดบั ชนั้ เช่นเดยี วกนั Root Content frame Feet entry Meters label Calculate button Feet label Meters label Is equivalent to (result) (label) calculate Feet meters Is equivalent to รปู ท่ี 19.7 แสดงลาดบั ชนั้ ของการสรา้ ง GUI ดว้ ย Tk จากรปู ท่ี 19.7 แสดงลาดบั ชนั้ การสรา้ ง GUI ของโปรแกรมแปลงหน่วยวดั ระยะทางจากฟุตเป็น เมตรทแ่ี สดงไวใ้ นรปู ท่ี 19.4 โดยเรมิ่ ต้นจากการสรา้ งหน้าต่างหลกั (Root) ขน้ึ ก่อนเสมอ เพอ่ื รองรบั Widgets ทท่ี าหน้าทต่ี ่างๆ กนั โดย Widgets จะถกู สรา้ งขน้ึ ลงบนเฟรม (Content frame) อกี ที ซง่ึ เฟรม ดงั กล่าวเปรยี บเสมอื นหน้ากระดาษบนคอมพวิ เตอรน์ นั่ เอง ซง่ึ แสดงในรปู ท่ี 19.8 Root (root window) Content frame Widgets รปู ท่ี 19.8 แสดงตวั อยา่ งความสมั พนั ธข์ อง Root (root window), Content frame และ Widgets 2. การเรยี กใช้งาน Widgets Widgets ในภาษาไพธอนถูกเขยี นขน้ึ ดว้ ยโปรแกรมเชงิ วตั ถุ ดงั นนั้ ทุกๆ Widget ทส่ี รา้ งขน้ึ จะถูกเรยี กวา่ อ๊อปเจก็ ต์ (Object) หรอื วตั ถุ เมอ่ื ทาการสรา้ งอนิ สแตนซข์ อง Widget ใดๆ ขน้ึ จะตอ้ ง ส่งพารามเิ ตอรใ์ หก้ บั คลาสแมต่ ามลาดบั ชนั้ ตามทก่ี ล่าวมาแลว้ ยกเวน้ Root ซง่ึ เป็นคลาสแมท่ อ่ี ยใู่ น ตาแหน่งบนสดุ (Toplevel window) ของลาดบั ชนั้ คลาสลกู ทุกๆ คลาสจะถกู สรา้ งภายใน root เทา่ นัน้ จากตวั อยา่ งต่อไปน้ีเป็นตวั อยา่ งการสรา้ ง Root, Content frame และ Widgets ห น้ า 479
Search
Read the Text Version
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 1 - 50
- 51 - 100
- 101 - 150
- 151 - 200
- 201 - 250
- 251 - 300
- 301 - 350
- 351 - 400
- 401 - 450
- 451 - 500
- 501 - 550
- 551 - 600
- 601 - 650
- 651 - 661
Pages: