November 29, 2011

Shell: พื้นฐานการใช้งาน

เนื่องจากเราสามารถเขียนโปรแกรมบน shell ของ terminal ได้ด้วย แน่นอนว่ามีคอมเมนท์ให้ใช้

ในการพิมพ์คำสั่งที่ยาวมากๆ อาจใช้ \ เพื่อบอกว่าบรรทัดถ้ดไปเป็นข้อความที่ต่อมาจากบรรทัดด้านบน (ไม่ใช่การขึ้นบรรทัดใหม่) เช่น

สังเกตว่าในกรณีหลายบรรทัด บรรทัดที่ถัดจาก $จะขึ้นต้นด้วย > เพื่อบอกว่ายังรอรับคำสั่งอื่นๆ ต่อไปอยู่

ปรกติแล้วเราจะพิมพ์ 1 คำสั่งต่อ 1 บรรทัด แต่ถ้าต้องการสั่งหลายๆ อย่างในบรรทัดเดียวก็ใช้ ; คั่นแต่ละคำสั่งได้



การกำหนดค่าให้ตัวแปรใน shell ทำได้โดย

แต่การจะเรียกตัวแปรนั้นๆ มาใช้ ต้องนำหน้าตัวแปรด้วย $ เสมอ

คำสั่งต่างๆ สามารถทำ completion ได้ โดยกดปุ่ม [Tab] เมื่อพิมพ์คำสั่งไปได้ซักระยะ เช่น

ถ้าระบบไม่ทำ completion ให้ นั่นหมายถึงไม่มีคำสั่งนั้น/มีคำสั่งมากกว่า 1 แบบ ซึ่งสามารถดูรายการคำสั่งได้โดยกด [Tab] อีกครั้งหนึ่ง



นอกจากนี้เราสามารถเลื่อนเลือกคำสั่งที่เคยพิมพ์ไปก่อนหน้านี้แล้วได้ด้วยปุ่มลูกศร [Up], [Down]

ส่วนการเลื่อนดูข้อความที่หลุดหน้าจอไปแล้ว ทำได้โดย [Shift]+[PgUp], [Shift]+[PgDn] หรือจะใช้ mouse wheel ก็ย่อมได้ครับ

November 27, 2011

Shell: ที่มาและเตรียมใช้งาน

1967 Datapoint 3000 terminal เครื่องแรก
1969 กำเนิด Unix
1991 กำเนิด Linux

Shell เป็นชั้นที่คั่นระหว่างผู้ใช้กับ Kernel ของคอมพิวเตอร์ โดยมี terminal emulator (tty) เป็นหนึ่งในโปรแกรมสำหรับเรียก command-line interface (CLI) ขึ้นมาเพื่อติดต่อกับ Kernel ซึ่งนอกจากจะเรียกโปรแกรมต่างๆ มาใช้งานได้แล้ว มันยังรองรับการเขียน script โปรแกรมอีกด้วย

แม้ว่า Windows จะเป็นระบบปฎิบัติการที่ได้รับความนิยมกว่า แต่เราจะสนใจ terminal (โปรแกรม+โครงสร้างไฟล์) ทางฝั่ง Unix/Linux กันครับ (อ้าว 55)



ผู้ใช้ Unix/Linux สามารถเรียกใช้โปรแกรมได้จาก menu เลย หรือจะกดปุ่มลัด [Ctrl]+[Alt]+[t] ก็ได้ (ส่วน [Ctrl]+[Alt]+[F2] และ [Ctrl]+[Alt]+[F7] จะเป็นการสลับ mode ระหว่าง GUI กับ CLI)

ผู้ใช้ฝั่ง Windows อาจลองใช้ผ่านทาง Cygwin แต่ทางที่ดีติดตั้ง Linux (เช่น Ubuntu) ไว้ด้วยเข้าจะท่ากว่าครับ



เมื่อเปิด terminal ขึ้นมา เราอาจพบข้อความต้อนรับอย่างใดอย่างหนึ่ง ประมาณนี้

เนื่องจากว่ามันมีความหลากหลายมาก จะเขียนย่อๆ ด้วยตัว $ เพียงตัวเดียวนะครับ

เอาหละ พร้อมแล้วก็ hello world กันหน่อยครับ

November 25, 2011

vi: แก้ไขเอกสารสำหรับโปรแกรมเมอร์

ลูกเล่นเล็กๆ น้อยๆ สำหรับคนใช้ vi เขียนโปรแกรมครับ

โดยปรกติ เวลาแก้ไขไฟล์ vi จะ auto-indent ให้อยู่แล้ว (สำหรับไฟล์ code ที่โปรแกรมรู้จัก) ถ้าต้องการ indent เอง ใช้ [<] หรือ [>] แล้วตามด้วย suffix เพื่อ indent เพิ่ม/ลดระดับความลึก code ของเรา
แต่ถ้าอยู่ใน insert mode การกด [Esc] บ่อยๆ เพื่อออกมาใช้คำสั่งเหล่านี้คงไม่เข้าท่าเท่าไหร่ ตรงนี้เราสามารถใช้ [Tab] (หรือ [Ctrl]+[t]) กับ [Ctrl]+[d] เพื่อเพิ่ม/ลดระดับความลึกของการ indent ได้ครับ
นอกจากนี้ เรายังสามารถใช้ [=] ตามด้วย suffix เพื่อสั่ง auto-indent code ที่ indent มั่วๆ ได้อีกด้วย

หมายเหตุว่าบางภาษาก็ไม่รองรับความสามารถนี้ เช่น Python ที่ต้อง indent เองครับ



ส่วนการเปลี่ยน case ของอักษรภาษาอังกฤษ ทำได้โดย [~]

Python: โครงสร้างโมดูล

ในงานขนาดเล็กๆ เราอาจมี module เพียง script.py แค่ไฟล์เดียว แต่ถ้า project มีขนาดใหญ่ขึ้น เราอาจจำเป็นต้องแยกมันออกเป็นหลายๆ ไฟล์

ตัวอย่างโครงสร้าง directory module ของ Python เป็นดังนี้ครับ

โดยที่ไฟล์ __init__.py เป็นไฟล์สำหรับบอก Python ว่า directory main เป็น module ตัวหนึ่ง แต่ Python ก็ยังไม่รู้ว่าใน directory main มีอะไรบ้างอยู่ดี ดังนั้น ภายในไฟล์ __init__.py ต้องประกาศ import ดังนี้

สังเกตว่า ตอนสั่ง import อย่าลืมชื่อ directory module นำหน้าไฟล์ด้วย และสมมติว่าถ้าต้องการเรียก function test ที่อยู่ในไฟล์ logic ใน interactive shell สามารถทำได้ดังนี้



ลองมาดูอีกซักตัวอย่าง

ต้องเขียนไฟล์ __init__.py แต่ละอันดังนี้

และ

หมายเหตุว่า ที่ไฟล์ __init__.py ไม่จำเป็นต้องมีแค่ import เท่านั้น เราอาจแทรก code ลงไปด้วยก็ได้ เช่น

November 21, 2011

vi: แก้ไขเอกสารขั้นสูง

เช่นเดียวกับตอนก่อน การแก้ไขเอกสารก็มีลูกเล่นอีกมากมาย เช่น [o], [O] จะขึ้นบรรทัดใหม่ด้านล่าง/บนแล้วเข้าสู่ insert mode

ส่วน [J] จะทำการเชื่อมบรรทัดด้านล่างของ cursor ขึ้นมา

สังเกตว่า ถ้าใส่เลขมากกว่าจำนวนบรรทัดที่เหลืออยู่ คำสั่ง [J] จะไม่สามารถทำงานได้ครับ



การแก้ไขตัวอักษรที่ผิดนั้น สามารถทำได้โดยการใช้ [r] ตามด้วยอักษรที่ต้องการเปลี่ยนให้มัน

นี่เป็นการแก้ไขทีละตัวๆ เท่านั้น ถ้าต้องการเปลี่ยนอักษรหลายตัวให้ใช้ [R]

ซึ่งจะเห็นว่าเป็นการพิมพ์ทับข้อความเดิม ถ้าต้องการลบตัวอักษรแล้วพิมพ์ใหม่ลงไป ให้ใช้ [s] แทน

หรือถ้าไม่ชอบใจทั้งบรรทัดเลย ก็กด [S] ครับ



เนื่องจาก [s] นั้นต้องนับอักษรแล้ววางตัวเลขเป็น prefix เท่านั้น ในกรณีนี้เราอาจใช้ [c] แล้วตามด้วย suffix เอาแทนได้

คำสั่งประเภทนี้ มักใช้การซ้ำตัวมันเองเพื่อกระทำการกับทั้งบรรทัด กรณีนี้ [c] [c] คือการเปลี่ยนทั้งบรรทัด

อีกคำสั่งใช้บ่อยที่ปรกติเราต้องนับอักษรเป็นตัวๆ คือ [x] ในกรณีนี้สามารถใช้ [d] เพื่อตามด้วย suffix ได้

เช่นกันครับ [d] [d] จะลบบรรทัดทิ้งทั้งบรรทัด


ถึงแม้ว่าการใช้คำสั่งที่มี suffix จะสะดวกมากกว่าพวกที่ใช้ prefix อย่างเดียว แต่ในบางกรณีเราก็ต้องการมากกว่านั้น คำสั่ง [v] จะเปิด visual mode เพื่อให้เรา highlight ตัวอักษรเอาได้ครับ

สังเกตว่า การใช้ [v] เพื่อ highlight สามารถใช้ได้กับคำสั่งได้ทั้ง prefix และ suffix เลยครับ (โดยที่ไม่ต้องส่งผ่านค่า prefix/suffix เข้าไปด้วย)



การคัดลอกข้อความ สามารถทำได้โดย [y] ตามด้วย suffix เลือกคำ (หรือทำใน visual mode ก็ได้) และวางโดยใช้ [p]

สิ่งที่ต้องระวังคือ การลบตัวอักษรด้วย [x] หรือ [d] จะเทียบเท่ากับการคัดลอกตัวอักษรนั้นไปเก็บไว้สำหรับ [p] ด้วยครับ

November 20, 2011

Python: เล่นกับเวลา

การเรียก tool เกี่ยวกับเวลามาใช้ทำได้โดย

ฟังก์ชันด้านบนนี้ถือเป็นพื้นฐานเวลาต้องการเวลาเครื่อง แต่ถ้าอ่านเลขเยอะๆ นี้ไม่รู้เรื่อง ก็สามารถใช้นี่ได้

หรือถ้ายังอ่านไม่รู้เรื่องอีก ก็สามารถขอเป็น string ได้

แต่ถ้าต้องการปรับแต่ง string ให้อยู่ใน format ที่เราต้องการ ต้องใช้

ส่วนการรับค่ากลับเพื่อสร้างเวลาที่คอมพิวเตอร์เข้าใจได้ง่าย สามารถใช้



สุดท้ายนี้ ไม่เกี่ยวกับเวลาอันน่าปวดหัวข้างบน แต่มันคือการหน่วงระบบครับ

November 18, 2011

Python: ใช้เรกูลาร์เอ็กเพรสชัน

จากตอนก่อนๆ แม้ว่าเราจะสามารถใช้การ slice และ .format() เล่นกับข้อความได้แล้ว แต่นั่นอาจไม่พอสำหรับการวิเคราห์ข้อความขั้นสูง ถ้าตรงนี้ถ้าใครเซียน regex แล้ว สามารถ import re เข้ามาใช้ได้ครับ

โดยสองคำสั่งนี้จะคืนค่าเป็น regex-object ถ้าตรวจเจอ pattern ที่ตรงครั้งแรก (และครั้งเดียว) และไม่คืนค่าถ้าหาไม่เจอ

ส่วนคำสั่งพวกนี้จะคืนค่าเป็น list ครับ

และสุดท้าย เราสามารถที่จะเปลี่ยน string ได้โดย

November 17, 2011

misc: นิพจน์ปรกติ (เรกูลาร์เอ็กเพรสชัน)

นิพจน์ปรกติ (regular expression นิยมย่อว่า regex) คือ pattern matching สำหรับข้อความชนิดหนึ่ง เรามักเจอการมันโดยทั่วไปเวลาทำงานเกี่ยวกับการ search/replace ข้อความ

กฏโดยทั่วไปของมันคือ (ในที่นี้สนเฉพาะภาษาอังกฤษก่อนนะ)

Pattern
Sample Pattern
Match Where
อธิบาย
alphanumeric
hell
hell, hello, neohellenic
เลือกคำนั้นไม่ว่าจะปรากฏที่ไหนในข้อความก็ตาม
42
42, 1342, 86420
.
hi.
him, hire, this, hi5, hi.
แทน . ด้วยอะไรก็ได้ (ยกเว้น \r, \n)
^
^hell
hell, hello ted
ขึ้นต้น/ลงท้ายบรรทัดนี้ด้วย (ตามลำดับ)
$
hell$
go hell, shell
|
ha|is
has, his, this
เลือกอันไหนก็ได้ระหว่าง | มา 1 ตัว
(some)
h(ea|il)l
hill, heal
ไว้ใช้จัดกลุ่มของคำเพื่อให้เลือก/ทำซ้ำได้ง่ายขึ้น
[some]
h[aeiou]l
hal9000, hell, alcohol
เลือกอันไหนก็ได้ใน [...]
h[a-z]l
shall, hcl, hyline
เลือกอักษรตัวไหนก็ได้ใน [...] ตั้งแต่ตัวแรกถึงตัวสุดท้าย (เรียงตามลำดับด้วย ASCII)
h[a-]l
hall, h-l
เมื่อเอา - ไว้สุดท้าย คือเลือกเครื่องหมาย - ด้วย
[^some]
h[^abc]l
hell, alcohol
เลือกอันไหนก็ได้ ที่ไม่อยู่ใน [...]
?
hello?
hell, hello
มีหรือไม่มีตัวก่อนหน้า ? ก็ได้
(toget)?her
together, her
+
hel+
hel, hell, helll
มีตัวก่อนหน้า + อย่างน้อย 1 ตัว
*
s*he
he, she, sshe
มีตัวก่อนหน้า * อย่างน้อย 0 ตัว (คือมีหรือไม่มีก็ได้ คล้ายๆ ? แต่อันนั้นจำกัดมีแค่ตัวเดียว)
{n,m}
hel{2}
hell
มีตัวที่เลือกจำนวนเท่านั้นพอดี แต่ถ้าเว้นตัวใดตัวหนึ่งไว้ หมายถึงขอบเขตด้านนั้นเป็นเท่าไหร่ก็ได้
hi{2,3}
hihi, hihihi
e{2,}
ee, eee, eeee
ok{,2}
ok, ok, okk
\
hi\.
hi.
escape char สำหรับยกเลิกความหมายอักขระพิเศษครั้งละตัว
"some"
"where?"
where?
ยกเลิกความหมายของอักขระพิเศษทั้งประโยค

หมายเหตุว่าจะเอาไปใช้ที่ใด ก็ลองดูกฏย่อยๆ ประจำที่อีกทีนึงนะครับ

เปิดหน้า Sitemap

เขียนมาได้ครึ่งเดือนแล้ว รู้สึก content เริ่มเยอะ เลยทำ sitemap (น่าจะเรียกว่าสารบัญมากกว่า) ไว้ดีกว่า เผื่อใครเพิ่งหลงเข้ามาตอนนี้จะได้เริ่มต้นถูกฮะ

กดดูได้เลยที่แถบข้างบน หรือเข้าผ่านตรงนี่ก็ได้

Python: การคำนวณขั้นสูงและการสุ่ม

นอกจากการคำนวณขั้นพื้นฐานที่ได้เขียนไปแล้ว Python ยังมีฟังก์ชันสำหรับการคำนวณติดมาอีกเล็กน้อยคือ

สงสัยฟังก์ชันไหน สามารถใช้ help(func_name) เพื่ออ่านข้อมูลเพิ่มเเติมได้ครับ



ถ้านี่ไม่พอ ต้อง import math มาใช้ ซึ่งมีค่าคงตัว/ฟังก์ชันสำคัญๆ ดังนี้

ลงไว้ไม่หมดนะฮะ ดูเพิ่มเติมด้วย help() โลด



นอกเหนือจากการคำนวณแล้ว การสุ่มยังแยกออกมาเป็นอีกโมดูลหนึ่งด้วย

ลงไว้ไม่หมดเช่นกันครับ

November 15, 2011

Python: แลมดาฟังก์ชันและส่วนปิดกั้น

แลมดาฟังก์ชัน (lambda function) เป็นมรดกตกทอดจากฝั่ง functional มันคือ syntax สำหรับประกาศฟังก์ชันในอีกรูปแบบหนึ่ง เช่น

และเรายังสามารถใช้มันได้โดยไม่ต้องประกาศชื่อ ใช้เสร็จครั้งเดียวก็จบ ไม่ต้องประกาศเป็นฟังก์ชันให้วุ่นวาย
ข้อดีคือ ใน code ที่มีขนาดใหญ่มากๆ จะช่วยลดความสับสนของเราไปได้ครับ
สำหรับส่วนปิดกั้น (closure) คือเหตุการณ์ที่เกิดขึ้นตอนประกาศฟังก์ชันที่เมื่อมีการขอใช้ตัวแปรจาก nonlocal มันจะ freeze ค่านั้นไว้ เพื่อให้การเรียกใช้ฟังก์ชันนี้ในอนาคตไม่มีผลข้างเคียง ไม่ว่าค่าของตัวแปรที่ไปอ้างอิงมานั้นจะเปลี่ยนแปลงไป
แม้ว่า Python จะไม่มี syntax เฉพาะสำหรับประกาศ closure เช่นภาษาอื่น แต่ด้วยการส่งผ่านตัวแปร by value และหน้าตาของ scope ตัวแปร ทำให้การสร้าง closure สามารถทำได้ดังนี้ครับ

November 13, 2011

Python: จัดการกับข้อผิดพลาด

จากหลายตอนที่ผ่านๆ มา ถ้าใคร code เอง คงผ่านตากับข้อความเตือน error อย่างเช่น

พวกนี้ เป็นความผิดพลาดจากการพิมพ์ของเราเอง แก้ไขได้โดยการไปฝึก code เยอะๆ ซะ จะได้พิมพ์ผิดน้อยลง



แต่ก็ยังมี error อีกประเภทที่อาจเกิดขึ้นได้แม้ว่าเราจะตรวจ syntax ว่าไม่มีที่ผิดแล้ว เช่น

ถ้าผู้ใช้ป้อนค่า 0 เข้ามาในครั้งที่สอง (ตัวแปร b) จะทำให้เกิด

เพื่อแก้ไขให้ code นี้ใช้งานได้ เราอาจดักเช็คค่าของ b ง่ายๆ เช่น

ก็ได้ แต่ในโลกความเป็นจริงแล้ว ผู้ใช้ยังสามารถป้อนตัวอักษรเข้ามาได้อีก (ซึ่งมันไม่สามารถเอาไปคำนวณแบบตัวเลขได้) แม้ว่าเราอาจดักไม่ให้ผู้ใช้สามารถกดแป้นตัวอักษรได้ แต่นั่นก็อาจแลกมากับการที่ code หนักขึ้น (มี maintainability ลดลง) เราจึงอาจหันมาพึ่ง exception เช่นนี้ครับ

หรือ เพื่อให้ code สวยงามยิ่งขึ้น



นอกจากนี้ เรายังสามารถสั่งให้เกิด exception error จากคำสั่ง raise ได้อีกด้วย เช่น


สำหรับ exception ที่ควรรู้จัก คือ

หรือถ้าอยากสร้าง exception ไว้ใช้เอง ก็สามารถทำได้โดยสืบทอดจาก Exception เช่น

November 11, 2011

Python: ตัวสร้างตัววนซ้ำ และกำรดำเนินการระดับบิต

ถึงตอนนี้ เราน่าจะวน for กันจนชินไปแล้ว ซึ่งจะเห็นว่าเราสามารถใช้ตัวแปร (เรียกว่า iterator) ได้หลากหลาย เช่น string, list, dictionary, file หรือจะใส่เป็นฟังก์ชัน range() เข้าไปก็ได้ ซึ่งถ้าเราอยากรู้ว่า range() นั้นมีหน้าตาลำดับเป็นยังไง ให้จับมันสร้าง list ดูครับ

แน่นอนว่าเราสามารถผ่าน range() แบบต่างๆ เข้าไปวน for ได้เช่นเคยครับ



อีกเทคนิคหนึ่งที่น่าสนใจ คือ generator expressions ซึ่งมีวิธีประกาศคล้ายการวน for มาก



เนื่องจาก Python ออกแบบมาให้เป็นภาษาระดับสูง การลงไปเล่นกับ bit จะค่อนข้างยุ่งยากแปลกกว่าปรกติ ความต่างจากภาษาอื่นๆ ที่ชัดเจนคือมันไม่มี overflow ครับ

เพื่อให้อ่านค่าได้ง่ายขึ้น เราอาจใช้ฟังก์ชันเหล่านี้ได้

ถ้าตัดเรื่องความแปลกๆ ของขนาด bit ออกไป ที่เหลือก็เหมือนๆ ภาษาอื่นเลยครับ

แต่เนื่องจากไม่มี circular shift ดังนั้นเราจึงต้องประยุกต์ท่านี้มาใช้ครับ

vi: บังคับเคอร์เซอร์ขั้นสูง

ในการจัดการกับข้อความจำนวนมากๆ การใช้ [h] [j] [k] [l] ค่อยๆ เลื่อนดูเอกสารอาจไม่ใช่ทางที่ดีที่สุด เราสามารถสั่งให้เลื่อนไปเป็นคำๆ ได้โดยปุ่ม [w], [W] ดังนี้

และสำหรับปุ่ม [e], [E]

สำหรับการเลื่อนย้อนกลับ ทำได้โดยปุ่ม [b], [B] โดยมันจะทำงานในทิศทางตรงข้ามกับปุ่ม [w], [W] และ [g] [e], [g] [E] ในทิศตรงข้ามกับ [e], [E] ตามลำดับ

หมายเหตุว่า ในกรณีที่มีหลายบรรทัด มันจะกระโดดไปยังคำในบรรทัดถัดไปด้วยนะครับ



ปุ่ม [g] เป็น command ประเภทที่ไม่ทำทันที มันต้องการคำสั่งอื่นมาเติมเต็มให้ถูกต้องถึงจะทำงานได้ (ซึ่งจริงๆ เราเคยเจอ command แบบนี้มาแล้ว คือปุ่มตัวเลข [Number] ที่ใช้เป็น prefix ต่างๆ) สำหรับปุ่ม [g] ที่ควรรู้คือ [g] [g] ซึ่งใช้สำหรับกระโดดข้ามไปบรรทัดแรกสุดของไฟล์

ส่วนการกระโดดไปบรรทัดต่างๆ ในไฟล์ สามารถทำได้โดยใช้ปุ่ม [Number] [G] หรือจะใช้ [Number] [%] เพื่อบอกตำแหน่งแบบคร่าวๆ ก็ได้ครับ

สังเกตว่า การกระโดดทั้งหมดนี้ cursor จะโผล่ไปที่ด้านหน้าของบรรทัดเสมอครับ



สำหรับปุ่ม [%] เปล่าๆ จะเป็นการเลื่อน cursor หาคู่ของวงเล็บของตัวถัดไปที่พบครับ



แม้ว่าเราจะสามารถใช้ [w] เพื่อเลื่อน cursor ไปยังคำต่างๆ ภายในบรรทัดได้อย่างรวดเร็ว แต่เรายังมีวิธีที่เร็วกว่าสำหรับการเลื่อนไปยังจุดเริ่ม/จบของบรรทัด คือการใช้ [0], [^] และ [$]

อาจจะจำยากหน่อย แต่ถ้าได้รู้จักกับ regex แล้วจะเข้าใจว่าทำไมครับ ;)



ส่วนการกระโดดไปยังอักษรที่ต้องการทันที ทำได้โดยปุ่ม [f], [F] และ [t], [T] ครับ

การ repeat การค้นหาเดิมซ้ำๆ สามารถทำได้โดยปุ่ม [;] (ไม่ค่อยมีประโยชน์กับ [t], [T] เท่าไหร่ เพราะมันจะหาได้เป็นตัวเดิม)

การหาแบบนี้จะไม่ข้ามไปยังบรรทัดอื่นครับ

November 10, 2011

Python: ว่าด้วยเรื่องขอบเขตตัวแปร

ใน Python ถึงแม้เราจะสามารถใช้ฟังก์ชันอ่านตัวแปรใน global scope ได้ เช่น

หรือแม้กระทั่งทำบางอย่าง

แต่เราจะเห็นว่า ค่าของตัวแปรดั้งเดิมนั้น ไม่เปลี่ยนแปลง (เพราะเป็นการส่ง by value ไม่ใช่ by reference) ถ้าต้องการอ้างตัวแปรนั้นๆ มาใช้ในฟังก์ชัน ต้องประกาศ global ครับ

ยกเว้นก็แต่พวก list, object นะครับ ที่ใช้การส่ง by reference เป็นปรกติอยู่แล้ว



นอกจากนี้แล้ว ยังมี nonlocal อีกด้วย



และด้วย scope ที่ต่างจากภาษาอื่นแบบนี้เอง ทำให้เราสามาถทำท่าแปลกๆ เช่นนี้ได้


November 8, 2011

vi: ปรับแต่งให้เหมาะกับการเขียนโปรแกรม

ใน vi มีโหมดหลักๆ อยู่ 3 โหมดด้วยกัน (ที่อื่นอาจบอกว่ามีมาก/น้อยกว่า) ดังนี้
  1. command mode เมื่อเปิดโปรแกรมมาก็จะเจอโหมดนี้ เราสามารถใช้ปุ่มอย่าง [j] [k] เพื่อเลื่อน cursor หรือกด [x] เพื่อลบอักษรบางตัวได้
  2. last line mode จริงๆ แล้วคือโหมดเดียวกับข้างบน แต่ต้องจบคำสั่งด้วย [Enter] เพื่อให้คำสั่งทำงาน เช่น :q [Enter] เพื่อออกโปรแกรม ซึ่งเราสามารถกด [Tab] เพื่อทำ auto-complete เหมือนได้ด้วย
  3. insert mode เป็นโหมดพิมพ์แก้ไขเอกสาร ซึ่งสามารถเปิดโหมดนี้ได้โดยปุ่มเช่น [i] [a] จาก command mode และออกจากโหมดนี้โดยปุ่ม [Ecs]
และสำหรับที่นี่ (สรุปจากตอนก่อนๆ)
  • เมื่ออยู่ใน command mode จะใช้ [ ] ล้อมปุ่ม เช่น [i] (หวังว่าคงไม่สับสนเวลาเจอ [[], []])
  • ถ้ามีการกดปุ่มตัวเลข จะรวบเลขหลายๆ ตัวอยู่ใน [ ] เดียว เช่น [20] [i]
  • ส่วนที่ last line mode จะไม่ล้อมรอบการกดปุ่มต่างๆ ยกเว้นตอนจบจะแสดง [Enter] เสมอ
  • ปุ่มที่ต้องกด [Shift] จะใช้ตัวใหญ่ไปเลย เช่น [Shift]+[a] ย่อเป็น [A]
  • แต่ [Ctrl]+[ ] และ [Alt]+[ ] ไม่ย่อครับ



ปรกติ (เมื่อทำงานกับไฟล์ที่มีนามสกุลเป็น source code ของ programming language ต่างๆ) โปรแกรม Vim จะทำ syntax highlighting ให้อยู่แล้ว ถ้าไม่ได้ทำให้ ลองพิมพ์คำสั่ง

ดูครับ (ถ้ายังไม่ได้อีก ให้ลองหาโปรแกรม Vim รุ่นใหม่มาติดตั้งดู)

อีกเรื่องคือการตั้งค่าให้แปลงการ indent ด้วย tab เป็น space สามารถใช้คำสั่งนี้

แต่การใส่คำสั่งนี้ลงไป จะส่งผลแค่ตอนที่เราเปิดโปรแกรมเท่านั้น เมื่อปิดโปรแกรมแล้วต้องพิมพ์คำสั่งเหล่านี้ใหม่ตลอด ทางแก้คือการเข้าไปแก้ไขไฟล์ vimrc ซึ่งสามารถทำได้โดย

เมื่อเปิดไฟล์ขึ้นมา ให้เพิ่มบรรทัดนี้เข้าไปด้านบนสุดครับ
เท่านี้ เราก็มีความสุขกับการเขียนโปรแกรมแล้วครับ ;)

Python: สร้างคลาส

การประกาศ class สามารถทำได้โดย

และเมื่อต้องการสร้าง object จาก class ก็สามารถประกาศได้ดังนี้

การเพิ่ม attribute เข้าไปใน object ก็สามารถทำได้ง่ายๆ เช่น

และเราสามารถดักการ init object ได้โดย

ทั้งนี้ การประกาศฟังก์ชันภายใน class จะต้องส่งผ่าน self เข้าไปด้วยนะครับ

ส่วนการสืบทอด class ทำได้เช่นนี้

อนึ่ง การประกาศตัวแปรแบบ private ทำได้ดังนี้

อย่างไรก็ตาม เรายังสามารถเข้าถึงตัวแปรแบบ private ได้อยู่ดี โดย

November 7, 2011

Python: สร้างฟังก์ชันเก็บไว้ใช้

ใน Python การสร้างฟังก์ชันสามารถทำได้โดยคำสั่ง def เช่นนี้ครับ

ด้วยความที่เป็น dynamic type ทำให้เราไม่ต้องบอกประเภทของตัวแปรที่รับ/คืนจากฟังก์ชัน แต่ก็ทำให้เสียความสามารถของ method overloading ไป (ซึ่งถ้าอยากได้จริงๆ อาจลงมือเช็คเองโดยใช้คำสั่ง type() ก็ได้)

และเช่นกันกับตอนแรกๆ ที่เราวน for แทบทุกอย่างที่ตามหลังเครื่องหมาย : ต้องขึ้นย่อหน้าใหม่พร้อม indent เพิ่ม และต้องมีคำสั่งด้วย ... ถ้ายังคิดไม่ออก อย่าลืม pass ไปก่อนนะครับ

อนึ่ง การแทรก string ไว้ทันทีหลัง def ฟังก์ชัน Python จะเก็บมันไว้เป็น docs ด้วยครับ

ซึ่งเราสามารถอ่าน docs ประจำ function ได้ในโหมด interactive shell โดยใช้คำสั่ง help()

และถ้าเราต้องการรู้ว่าเราได้สร้างฟังก์ชันอะไรขึ้นมาใช้แล้วบ้าง ก็สามารถเรียกดูได้โดยคำสั่ง dir()



การสร้างฟังก์ชันเพื่อ import มาใช้งาน ต้องเขียนไฟล์เก็บไว้เป็น filename.py ครับ

โดยเมื่อตอนใช้งาน เราสามารถเรียกได้จาก import เช่น สมมติเราเซฟงานด้านบนไว้ในชื่อ test.py

หรือถ้าเรารู้สึกว่าชื่อเหล่านี้ยาวไป

หรือจะทำอย่างนี้ก็ได้ (แต่ไม่แนะนำ เพราะอาจเกิดการ lost ของ docs ประจำไฟล์)

ทั้งนี้ มีข้อควรจำไว้อย่างหนึ่งว่า เมื่อเรา import สำเร็จ การแก้ไข code ที่ไฟล์ต้นฉบับจะไม่ส่งผลต่อ code ที่ได้ import เข้ามาแล้วนะครับ ถ้าอยากได้ใหม่ต้อง restart Python shell เอง



ถึงแม้ Python จะไม่รองรับ method overloading แต่ก็ได้จุดแข็งที่สามารถ init ตัวแปรได้นะครับ

และเรายังมี *args และ **kwargs ให้ใช้ด้วย

November 5, 2011

vi: แก้ไขข้อความขั้นพื้นฐาน

การเพิ่มข้อความ ทำได้โดยกดปุ่ม [i] (จะเห็นว่าบรรทัดล่างสุดบอก -- INSERT --) แล้วค่อยพิมพ์ข้อความ

สังเกตว่า ถ้าที่มีข้อความอยู่ก่อนแล้ว มันจะเป็นการแทรกข้อความใหม่ด้านหน้าข้อความเดิมที่ cursor ชี้อยู่ เช่น

ในกรณีนี้ ให้ใช้ปุ่ม [a] เพื่อเพิ่มข้อความแทน ข้อความใหม่จะไปอยู่ด้านท้ายครับ

เรายังสามารถใช้ prefix number กับการพิมพ์ข้อความได้เช่นกัน (ในกรณีที่ต้องกดปุ่มตัวเลขมากกว่า 1 ครั้ง ขอครอบไว้ใน [Number] เดียวนะครับ)

หมายเหตุว่าพิมพ์เสร็จ ต้องกดปุ่ม [Esc] ก่อนถึงจะเห็นผลนะครับ



ในกรณีที่เราต้องการเพิ่มข้อความไว้ด้านหลังสุดของบรรทัด เราสามารถทำได้อย่างรวดเร็วไม่ว่า cursor จะอยู่จุดไหนในบรรทัดนั้น โดยกด [Shift]+[a] (ต่อไปนี้จะเรียกปุ่มที่ต้องกด [Shift] ก่อนด้วยตัวใหญ่นะครับ เช่นกรณีนี้คือ [A]) แล้วเพิ่มข้อความครับ

เช่นเดียวกันกับการกด [I] จะเป็นการเพิ่มข้อความใหม่ไว้ด้านหน้าสุดของบรรทัดครับ (ในกรณีที่บรรทัดนั้นมีการ indent จะเป็นการเพิ่มข้อความหลัง indent ครับ)



ในกรณีที่พิมพ์ผิด เราสามารถกดปุ่ม [i] หรือ [a] แล้วค่อยใช้ปุ่ม [Backspace] หรือ [Delete] เพื่อลบข้อความตามปรกติก็ได้ (เมื่อลบเสร็จแล้วก็กด [Esc]) แต่เรามีวิธีที่รวดเร็วกว่านั้นคือใช้ [x] และ [X] ครับ



ถ้าแก้ไขข้อความแล้วไม่ชอบ สามารถ undo ได้โดยปุ่ม [u] และ redo ด้วย [Ctrl]+[r]ครับ



เนื่องจากว่าคราวนี้เราได้ทำการแก้ไขไฟล์ไปบ้างแล้ว การเซฟงานสามารถทำได้โดยการพิมพ์ :w filename หรือไม่ต้องมี filename ก็ได้ในกรณีที่เราเรียก vi โดยใส่ filename ตามตั้งแต่ต้น หรือถ้าต้องการเซฟงานแล้วออกโปรแกรมทันที ก็สามารถเรียก :wq filename ได้อีกด้วยครับ

Python: ตัวแปรแบบพจนานุกรม, เซ็ตและทูเพิล

ใน Python ตัวแปร dictionary คือตัวแปรแบบ list ที่ใช้ "ข้อความ" แทน index ในการเรียกตัวแปรนั่นเอง (เทียบเท่ากับ associative array, hash table ในภาษาอื่นๆ)

การประกาศ และการใช้งานก็สามารถทำได้หลายวิธี เช่น

แต่เนื่องจากว่า dictionary ไม่มีการเรียงลำดับข้อมูล เราจึงไม่สามารถใช้การ slice มันได้เหมือน list ดังนั้นเราต้องใช้คำสั่งเหล่านี้แทน

สังเกตว่าการวน for จะมีตัวแปรรับค่าเพิ่มขึ้นมาเป็น 2 ตัว (คือ key, value) ครับ

ส่วนการตรวจสอบว่ามี key อยู่ใน dictionary หรือไม่ ก็สามารถใช้ in/not in ได้ครับ



ส่วนตัวแปรแบบ set จะเหมือนกับ set ทางคณิตศาสตร์เลย คือไม่สนลำดับ/ค่าที่ซ้ำ

การดำเนินการพื้นฐานของ set



ตัวแปรชุดอย่างสุดท้าย (แต่ไม่ท้ายสุด) คือ tuple คุณอาจคิดว่าไม่เคยได้ยิน แต่ถ้าบอกว่ามันคือ "คู่อันดับ" (สำหรับกรณีสามาชิก 2 ตัว) คงร้องอ๋อแน่ ซึ่ง tuple นี้คือกรณีที่ขยายไปใช้กับ n(คู่)ลำดับ ครับ

เนื่องจาก tuple ใน Python เป็น immutable type แก้ไขไม่ได้ เวลาเอามาใช้ต้อง unpack ไปใส่ตัวแปรก่อน

ดูแล้วอาจไม่ค่อยได้ใช้มากเท่าไหร่ แต่จะเห็นประโยน์ตอนเตรียม raw input ครับ

November 4, 2011

vi: เปิดไฟล์มาบังคับซ้ายขวาบนล่าง

จุดเด่นของ vi อยู่ที่การบังคับ cursor เพราะในการใช้งานจริง เราไม่ได้พิมพ์เพิ่มไปเรื่อยๆ เพียงอย่างเดียว บางทีต้องย้อนกลับไปแก้ไขจุดเก่าๆ บ้าง การที่ต้องยกมือออกจาก home row ไปยังปุ่มลูกศร/จับเมาส์จึงดูไม่ค่อยเข้าท่าเท่าไหร่ vi ตอบโจทย์ตรงนี้ด้วยการเอาปุ่มบังคับทิศทางมาอยู่บน home row ซะเลย (โมเดลต้นแบบ: ADM-3A) ตอนนี้เราจะยังไม่รีบร้อนพิมพ์ข้อความกันครับ เอาการบังคับ cursor ให้คล่องๆ ก่อนดีกว่า

ก่อนอื่น หาไฟล์เอกสาร (เอาแบบที่พิมพ์มาแล้วเยอะๆ นะ ไม่งั้นเลื่อน cursor ไม่สนุก) มาซักไฟล์ แล้วเปิดอ่านเอกสารทาง terminal ด้วยคำสั่ง

... ถ้าใครพลาดตรงนี้ไป ไม่ต้องออกโปรแกรมก็ได้ครับ ใน vi ให้พิมพ์

แล้วกด [Enter] ก็เปิดไฟล์ได้เช่นกัน หรือถ้าจำไม่ได้ว่าไฟล์ชื่ออะไร พิมพ์แค่

เพื่อเป็นการเปิด shell สำหรับดูไฟล์ของ vi (แต่การเลื่อน cursor เลือกไฟล์ก็จะเป็นแบบ vi ด้วย) ก็ย่อมได้ครับ



การเลื่อน cursor จริงๆ แล้วไม่ได้ยุ่งยากอะไรเลยครับ เหมือนกับการใช้ [w] [a] [s] [d] เล่นเกมนั่นแหละ ขออย่างเดียวคือให้เปิดใจรับมัน แค่นั้นเองจริงๆ!

ลองฝึกเลื่อน cursor โดยใช้ [h] [j] [k] [l] ให้ชิน ไม่ต้องพึ่งปุ่มลูกศรตามที่เคยทำมานะครับ



ใน vi มีระบบ prefix number สำหรับ command แทบทุก command ซึ่งส่วนใหญ่แล้ว มันจะหมายถึงการทำสิ่งนั้นๆ เป็นจำนวนกี่เท่าจากปรกติ

เช่น ถ้าเรากด [l] จะเป็นการเลื่อนลูกศรไปด้านขวา 1 ตัวอักษร การกด [5] [l] จะหมายความว่า ให้ทำการเลื่อนไปด้านขวา 5 ตัวอักษรนั่นเองครับ

อันนี้ก็ลองฝึกให้ชินด้วยเช่นกันนะ



เนื่องจากไม่มีการแก้ไขไฟล์ เราสามารถป้อนคำสั่ง :q [Enter] โดยไม่ต้องมีเครื่องหมาย ! ต่อท้าย (เหมือนตอนที่แล้ว) เพื่อออกโปรแกรมก็ได้ครับ

Python: ตัวแปรชุดแบบรายการ

ใน Python ตัวแปรแบบ list เป็นตัวแปรชุดที่ง่ายที่สุด เราสามารถประกาศมันได้ดังนี้

ความสามารถบางอย่างของ list นั้น จะคล้ายๆ กับ string เช่น

ความแตกต่างของ list กับ string คือ มันเป็น mutable type ทำให้เรายังสามารถแก้ไขมันได้อยู่ เช่น

แต่เนื่องจากว่า list เป็นการอ้างตัวแปรแบบ reference ดังนั้นเราจะเจอเหตุการณ์เช่นนี้แน่นอน

ทางออกคือการสไลด์ list ในขนาดเท่าเดิม เมื่อต้องการสำเนา list ครับ



จริงๆ แล้ว ด้วยเทคนิคการสไลด์นี้ มันครอบคลุมทุกท่าเท่าที่จะคิดออกอยู่แล้ว แต่ถ้ายังสไลด์ไม่คล่อง ก็สามารถเล่นกับ method ที่คุ้นเคยพวกนี้ได้ครับ



สิ่งที่เจ๋งจริงๆ ใน Python คือ การ unzip list ไป map กับตัวแปรอื่นๆ เช่น

ซึ่งเราจะได้เห็นความสามารถเหล่านี้กับตัวแปรชุดแบบอื่นๆ อย่าง dictionary และ tuple ซึ่งจะเล่าในตอนหน้าครับ



ป.ล. ส่งท้ายด้วยของเล่นสนุกๆ ดังนี้

November 3, 2011

vi: ที่มาและเตรียมตัวใช้งาน

1954 กำเนิด Bill Joy
1961 กำเนิด Bram Moolenaar
1976 Joy ให้กำเนิด vi
1991 Moolenaar ให้กำเนิด Vim
2006 Vim เดินทางมาถึงรุ่นที่ 7

vi (วีไอ) คือ text editor ตัวหนึ่งที่ไม่ว่ามือใหม่หน้าไหนก็บ่นว่าใช้ยาก...

ที่มาของชื่อได้มาจากคำสั่ง visual ในโปรแกรม ex (ซึ่งก็คิดค้นโดย Joy นั้นแหละ) เพราะเป็นการเปิดโหมดดูเอกกสาร ส่วน Vim (Vi IMproved) ซึ่งเป็นเวอร์ชันพัฒนาของ vi อีกทีหนึ่ง ในที่นี้จะเขียนเกี่ยวกับ Vim เพราะมีลูกเล่นเยอะกว่า แต่โดยทั่วๆ ไปจะขอเรียกโปรแกรมนี้ว่า vi ตามแบบฉบับดั้งเดิม เพราะว่ามันสั้นและดูขลังดีครับ



ผู้ใช้ฝั่ง Windows ใช้ gVim ครับ download ได้ที่นี่

ส่วนฝั่ง Linux จะมี vi ติดมากับอยู่ทุกเครื่องอยู่แล้ว แต่ทางที่ดีลองสั่งติดตั้งโปรแกรม Vim ทับไปอีกทีนะครับ ไม่งั้นจะใช้บางฟังก์ชัน (ที่โคตรสำคัญ) อย่าง syntax highlight ไม่ได้ (ส่วน Mac OS X มี Vim ติดมาให้ด้วยเลยครับ)



เมื่อเข้าโปรแกรม เราจะเห็นหน้าตาต้อนรับประมาณนี้

(ตรงเครื่องหมาย _ คือตำแหน่ง cursor นะครับ)

ลอง hello world ซักหน่อย ขั้นแรก กดปุ่ม [i] บนคีย์บอร์ดก่อน (นิ้วกลางขวาบน) จะเห็นว่าบรรทัดล่างสุดเปลี่ยนเป็น

คราวนี้ พิมพ์ hello world! ลงไป เรียบแล้วกดปุ่ม [Esc] ก็เสร็จสิ้นกระบวนการทักทายชาวโลกแล้วครับ

สำหรับตอนแรกนี้ เอาแค่สวัสดีชาวโลก ง่ายๆ ก่อนนะครับ การออกโปรแกรมพิมพ์ :q! แล้วก็ [Enter] ครับ

ป.ล. ไม่ต้องกลัวงง ครั้งแรกผมก็เป็นเหมือนคุณนั่นแหละ

November 2, 2011

misc: ความแตกต่างระหว่างวินโดวส์กับลินุกซ์

ในโลกคอมพิวเตอร์เล็กๆ ใบนี้ ถ้าคุณเชี่ยวชาญ Windows ก็เหมือนคนพูดภาษาไทยคล่อง คุยกับคนรอบตัวได้รู้เรื่อง และถ้าคุณชำนาญ Linux (Unix) ก็เหมือนมีความรู้ภาษาอังกฤษติดตัว แม้ว่าอาจจะใช้กับคนรอบตัวได้ไม่มากเท่าไหร่ แต่เมื่อเจอฝรั่งกล้ามใหญ่แล้ว คุณก็สามารถสื่อสารกับเค้าได้เข้าใจทันที

ขึ้นชื่อว่าเป็นโปรแกรมเมอร์แล้ว อย่าพูดเป็นแค่ภาษาแม่ภาษาเดียว และก็อย่ากระแดะพูดฝรั่งกรอกหูเพื่อนครับ

เรามาดูดีกว่า ว่าความแตกต่างระหว่าง Windows กับ Linux มีอะไรบ้าง


WindowsLinux
ขึ้นบรรทัดใหม่ CR+LF (\r\n)LF (\n)
เส้นคั่นโฟลเดอร์\ (backslash)/ (slash)
โฟลเดอร์รากไม่มี (อาจถือว่าคือ C:\)/
โฟลเดอร์ส่วนตัวC:\users\usrname/home/usrname
ชื่อไฟล์case insensitivecase sensitive
ไฟล์ที่ซ่อนตั้งค่าที่ propertyเพิ่ม . (จุด) ไว้หน้าชื่อไฟล์
option argument/ เช่น shutdown /s- เช่น shutdown -h
แทรก EOFCtrl + Z + EnterCtrl + D
ขนาด tab4 ตัวอักษร8 ตัวอักษร

Python: อินพุทและไฟล์

การรับ input ทาง keyboard (stdio) ทำผ่านฟังก์ชัน input()

ง่ายๆ แค่นี้แหละครับ (สั้นจนเหลือเชื่อเนาะ?)



ส่วนการอ่านไฟล์ของ Python นั้น จะใช้ open() สร้าง file object ขึ้นมาก่อน

เมื่อเปิดไฟล์สำเร็จ ก็ต้องอ่านมัน

ส่วนการเขียนไฟล์ก็ทำได้ง่ายๆ เช่นนี้ครับ

หมายเหตุ ชาว Windows ไม่ต้องกังวลเรื่อง \n นะครับ Python จะจัดการมันให้เป็น \r\n โดยอัตโนมัติ



นอกจากนี้ เรายังสามารถใช้ with ในการเปิดไฟล์มาใช้แบบเร็วๆ ได้อีกด้วย

ซึ่งมีข้อดีในกรณีที่ทราบ scope การอ่านไฟล์ที่แน่นอนครับ และยังไม่ต้องสั่ง close() อีกด้วย

Python: เล่นกับข้อความขั้นสูง

จากตอนก่อน เราได้เห็นวิธีใช้ % (percent sign) เพื่อจัด format ข้อความไปแล้ว แต่เนื่องจากมันเป็นวิธีเก่าที่กำลังถูกเลิก support ดังนั้นเราควรใช้ .format() ซึ่งเป็นวิธีใหม่แทนครับ

การสลับตำแหน่ง สามารถทำได้โดยใส่เลขเรียกลำดับ arg ใน .format() ไว้ที่ {}

หรือจะตั้งชื่อให้กับตัวแปรใน .format() เพื่อการเรียกใช้ที่ง่ายขึ้นก็ย่อมได้



การใส่ format specifier ภายใน {} ต้องอยู่ตามหลัง : เช่น

ถ้าเป็นตัวเลขเฉยๆ จะเป็นการเผื่อความกว้างไว้ตามนั้น



นอกจากนี้ ยังสามารถจัดย่อหน้าด้วย .ljust(), .rjust() และ .center() ก็ได้ครับ



อ๋อ ลืมไปอย่าง การแปลงไป/กลับระหว่างตัวเลขกับตัวอักษรทำได้โดย ord() และ chr() ครับ