By Arnon Puitrakul - 16 กันยายน 2021
คำสั่งแรก ที่เราน่าจะเรียนกันเมื่อเราเรียนภาษาใหม่ น่าจะเป็นคำสั่งสำหรับการเอาข้อความ หรือค่าบางอย่างออกทางหน้าจอ ถ้าเป็นภาษา C ก็จะเป็น printf() หรือถ้าเป็น Python เองก็จะเป็น print() อะไรก็ว่าไป แต่ถ้าเราเขียนไปเรื่อย ๆ เราจะเจอเคสที่แปลกขึ้นเรื่อย ๆ จากเอาแค่ข้อความธรรมดาออกมาแล้ว อาจจะมีตัวแปรอะไรอีก จนมันมั่วไปหมด จนไปถึงเอาตารางออกมาเลย วันนี้เราจะไปไล่ดูเทคนิคการ Print หรือแสดงข้อความออกทางหน้าจอบน Python ตั้งแต่ง่ายสุดจน Advance สุด ๆ เลย
เรามาเริ่มจากอะไรที่เบสิกสุด ๆ ก่อนเลย นั่นคือการเอาข้อความธรรมดานี่แหละ ออกไปยังหน้าจอ
print('Hello World')
Hello World
ก็ใช้คำสั่ง print() ง่าย ๆ เลย เพียงแค่เราใส่ String เข้าไป เราก็จะได้ข้อความที่เราใส่ออกทางหน้าจอเลย
print('Hello World')
print('Hello \nArnon')
Hello World
Hello
Arnon
ความง่ายของ Python ที่เขาเตรียมมาคือ ในคำสั่ง print() มันจะใส่ตัว Newline มาให้เราเองเลย ทำให้ถ้าเรารัน print() ไปเรื่อย ๆ มันก็จะไม่ติด ๆ กันไปหมด เหมือนในภาษาพวก C,C++ ที่เราจะต้องใส่ Newline เอง ซึ่งแน่นอนว่า ความ Flexible ของ Python ก็ทำให้เราสามารถใส่ Newline หรือ Special Characters ได้ด้วยเช่นกัน เช่น เราใส่เป็น "\n" หรือก็คือ Newline Character หรือ เราอาจจะใส่เป็น "\t" ก็คือ Tab ลงไปก็ได้เช่นกัน ขึ้นกับที่เราจัดได้เลย
เพิ่มความ Advance เข้าไปอีก เราสามารถ Pass ตัวแปรลงไปได้เช่นกัน เพราะอย่าลืมว่า การที่เรา Pass String ลงไปตอนแรก มันก็เป็นตัวแปรเหมือนกัน ดังนั้น เราก็สามารถเอาค่าอะไรบางอย่างออกมาแสดงผลผ่านคำสั่ง print() ได้เช่นกัน
a = 1
print(a)
1
จากตัวอย่างด้านบน เราทำการสร้างตัวแปร ที่เก็บตัวเลข 1 ขึ้นมา และใช้ print() ใส่ a เข้าไป เราก็จะได้ค่าของ a ออกมานั่นคือ 1 นั่นเอง เราลองอะไรที่พีคกว่านั้นกันดีกว่า
a = 1
print("the result is " + a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
ถ้าเราเอาแค่ a หรือก็คือ 1 ออกมาเฉย ๆ ผู้ใช้น่าจะ งง ว่า แล้ว 1 นี่มันคืออะไรกัน เป็น Debug หรือ Result จริง ๆ กันนะ งั้นเราใส่ประโยคลงไปบอกผู้ใช้หน่อยละกันว่า มันคือผลลัพธ์นะ เราก็เลย เดา ๆ ละกัน งั้นเราก็บวก String ก็น่าจะได้ละมั่ง เอา the result is มาบวก กับ a เลย ปรากฏว่า ผลลัพธ์ ก็คือ Error พังนั่นเอง ถ้าเราลองดู Error มันบอกว่า มันสามารถต่อได้แค่ String กับ String เท่านั้น แต่เราใส่ int มา เราจะทำยังไงดีละ
a = 1
print("the result is " + str(a))
the result is 1
ในเมื่อ เราต่อ String กับ Int ไม่ได้ เราก็แปลงให้ Int เป็น String ซะก็สิ้นเรื่อง ใน Python มันมีคำสั่ง str() สำหรับการแปลงตัวแปร หรือ Object ต่าง ๆ ให้อยู่ในรูปแบบของ String จากนั้น เราก็สามารถเอาไปบวกเข้ากับ String ด้านหน้า และแสดงผลได้อย่างถูกต้องแล้ว
a = 1
print("the result is", a)
the result is 1
แต่การที่เราจะต้องมานั่งใส่ str() เพื่อแปลงทุกครั้ง เราว่ามันก็ไม่น่าตลกเท่าไหร่ ในคำสั่ง print() มันไม่ได้รับแค่ Argument เดียว แต่มันสามารถรับ Item ของ ๆ ที่เราต้องการแสดงได้เรื่อย ๆ เลย ตัวอย่างเช่นด้านบนนี้ เราก็เปลี่ยนจาก บวก เป็น Comma แทน และ ไม่เว้นวรรคหลัง is ซึ่งใน print() ตัว Python มันจัดการให้เราเสร็จเลย เราไม่ต้องมานั่งแปลงอะไรทั้งสิ้น
a = [1, 2, 3]
print('List A :', a)
List A : [1, 2, 3]
นอกจากที่เราจะใส่พวกตัวแปรธรรมดาได้แล้ว เรายังสามารถยัด Data Structure ที่ซับซ้อนกว่าตัวแปรลงไปได้เช่นกัน ดั่งตัวอย่างด้านบนที่เราเอา List มาใส่ซะเลย ก็ทำได้เหมือนกัน
a = [1, 2, 3]
print('List A :', str(a)[1:-1])
List A : 1, 2, 3
อีกทริกที่เราใช้บ่อย ๆ เวลาเรา print() List ออกมาคือ บางที เราไม่ได้อยากได้เครื่องหมายเปิดปิดปีกกา เราต้องเอาออก เรารู้ว่า ตัวเปิดและปิด มันจะอยู่ Character แรก และ สุดท้าย ของ String เมื่อ แปลงจาก List เป็น String แน่นอน เราก็ชิงแปลงก่อน และ Substring เอาตัวแต่ตัวที่ 2 จนถึงจบ String และไม่เอาตัวสุดท้ายไป ก็จะทำให้ปีกกาหายไปอย่างง่าย ๆ นั่นเอง
บางทีการคั่นด้วยเครื่องหมาย Comma หรือ การแปลงเป็น String แล้วทำ Concatenate ก็อาจจะไม่ตอบโจทย์ เพราะมันทำให้ Code ของเราอ่านยาก และ รก มาก ๆ แน่นอนว่า ความยืดหยุ่นของ Python เอง นางก็เตรียมอีก Function ที่จะมาช่วยเราจัดการเรื่องนี้คือ format()
a = 10
print("this is number {}".format(a))
This is number 10
คำสั่ง format() เป็นคำสั่งสำหรับการ Inject ค่าเข้าไปใน String สิ่งที่เราทำ เราก็แค่สร้าง String ขึ้นมาตัวนึง และเรียกคำสั่ง format() เข้าไป โดยมันจะเข้าไปหาว่ามันมี {} อยู่ใน String ที่เราใส่เข้ามาหรือไม่ ถ้ามีมันก็จะไป Replace {} ด้วยตัวแปรที่เราใส่ลงไป ทำให้เวลาเราเขียน เราสามารถเขียนได้ง่ายขึ้น ไม่ต้องมาระแวงเรื่องเครื่องหมายต่าง ๆ ที่อาจจะลืมได้ แถม ทำให้ดูเป็นธรรมชาติมากกว่าเยอะเลย
name = "Somchai"
surname = "Kiatkul"
print("Hello {} {}".format(name,surname))
Hello Somchai Kiatkul
แน่นอนว่าคำสั่ง format() สามารถรับตัวแปรกี่ตัวก็ได้เลย ขอแค่เราเรียงลำดับตัวแปรที่เราใส่ไปให้ตรงกับลำดับที่อยู่บน String ที่เราใส่เข้าไปก็เป็นอันเรียบร้อยแล้ว
print('{:,}'.format(1000))
1,000
นอกจากการ Inject Variable ลงไปใน String สิ่งที่ format() ทำคือการ Format String สมชื่อมันแหละ เพราะมันทำให้เราสามารถกำหนดรูปแบบของค่าต่าง ๆ ที่เราใส่ลงไปได้ด้วย ตัวอย่างด้านบน เราทำการใส่ 1,000 เข้าไป เราอยากให้มันใส่ Comma คั่นเพื่อให้อ่านง่ายขึ้น ถ้าเราเขียนเอง เราก็ต้องมาไล่ซอยเอาเองซึ่งเสียเวลาอยู่เหมือนกัน อันนี้เขาทำให้เราเรียบร้อยเลย และเป็น Built-in Function ใน Python เองเลย ไม่ต้องลงเพิ่มใด ๆ
print('{:,.2f}'. format(1000))
1,000.00
เรายังสามารถใส่จำนวนของทศนิยมลงไปได้อีก เช่น ถ้าเราคำนวณออกมาแล้ว เราอยากได้ทศนิยม 2 ตำแหน่ง เราก็สามารถใส่ .2f หรือ จุด แล้วตามด้วยจำนวนหลักทศนิยม และตามด้วยตัว f เราก็จะ Format ตัวเลขทศนิยมได้ง่าย ๆ
หรืออยากได้แปลงเป็นเลขฐาน 2, 16 ต่าง ๆ เราก็สามารถทำได้ การแปลงวันที่ต่าง ๆ การแสดงผล Scientific Notation ต่าง ๆ ก็สามารถใส่ Option ต่าง ๆ ลงไปได้เลย ถ้าอยากรู้ว่ามันมีอะไรบ้าง ลองไปอ่านใน Document ของ Python ได้
จากวิธีการ Format จริง ๆ มันเน้นตามชื่อเลยคือ การ Format ค่าเพื่อให้แสดงผลได้ตามต้องการ แต่ดูจาก Code คือ เราจะต้องรันคำสั่งไว้ด้านหลัง ซึ่งทำให้เวลาอ่านมันจะอิหยังว้าาา หน่อย ๆ ทำให้เราต้องหาวิธีอื่นที่ทำให้เราสามารถเขียน พวก String ไปพร้อม ๆ กับตัวแปรได้ตรง ๆ เลยโดยที่ไม่ต้องเขียนไป Apply Function อะไรเพิ่ม เพื่อมันให้มันสั้นลง ทำให้เราไปรู้จักกับ f-strings
a = 10
print(f'{a}')
10
ตามชื่อของ f-strings เลย คือ ก่อนที่เราจะใส่ String เข้าไป เราจะต้องใส่ตัว f กำกับไว้ เพื่อให้ Python รู้ว่ามันจะต้องอ่าน String นี้เป็น f-strings นะ จากนั้นภายใน String ถ้าเราต้องการที่จะใส่พวกตัวแปรลงไป เราก็สามารถใส่เครื่องหมาย {} ที่ด้านในเป็นชื่อตัวแปรเลย ก็ทำให้เราสามารถใส่ตัวแปรไปพร้อมกับข้อความอื่น ๆ ได้ง่ายขึ้น
a = 1000
print(f'{a:,}')
1,000
การที่ f-string เขียนอ่านง่ายกว่า ไม่ได้แปลว่ามันจะไร้ความสามารถไม่เท่ากับ .format() แต่มันแค่เป็นการลดรูปของ format() เท่านั้นเอง เพราะเรายังสามารถที่จะเขียนพวก Symbol เพื่อบอก Python ว่า จะให้มันทำอะไรเช่น การใส่ Comma เพื่อให้ผลที่ออกมันมี Comma คั่นด้วยนั่นเอง นั่นทำให้ถ้าเราไปอ่านหลาย ๆ เล่ม หรือ อ่านพวก Stackoverflow เราจะเจอคนใช้ f-stirng เยอะมาก เพราะมันทำให้อ่านง่าย และ ไม่ต้องอาศัยการเขียนการเรียก Function เพื่อ Inject Variable หรือ Object ลงไป
ถ้าใครที่เคยใช้พวก Pandas มาก่อน เวลาเราเอา DataFrame ออกมาดู เราจะเห็นได้เลยว่า มันทำออกมาเป็นตารางสวยมาก ๆ ถ้าให้เราทำเองมันก็ทำได้แหละ แต่แหม่ ก็ไม่ได้ว่างขนาดนั้นเนอะ ทำให้เราต้องมีตัวช่วย คือ Module ที่ชื่อว่า Tabulate
pip install tabulate
Module นี้ ก่อนที่เราจะใช้ เราจะต้องทำการติดตั้งลงไปก่อน ถ้าใครใช้ pip อยู่แล้วก็ใช้คำสั่งด้านบนนี้ได้เลย หรือถ้าใครใช้ Conda หรืออย่างอื่นก็ สามารถใช้ชื่อ Package นี้ในการหาได้เลย
from tabulate import tabulate
body = [['Somchart', 35], ['Takki', 50]]
header = ['Name', 'Age']
print(tabulate(body, header))
Name Age
-------- -----
Somchart 35
Takki 50
การใช้งานก็ไม่ได้ยากเลย เพียงแค่เรากำหนดตัว Body ของตาราง ทำง่าย ๆ เลยเป็น List ซ้อน List ที่ในนั้น จะเป็น List ของข้อมูลในแต่ละ Row ซึ่งใน Row ก็จะมีได้หลาย Item เลยเป็น List ซ้อน List จากนั้น เราก็กำหนด Header หรือหัวตารางไว้ สุดท้าย เราก็ใส่เข้าไปในคำสั่ง tabulate() ที่เราเรียกมา ก็แค่นั้นเลย เรียบน้อยแล้ว ซึ่งใน Tabulate เรายังสามารถ Format รูปแบบของตัวเลขได้อีก อันนี้ลองเข้าไปอ่านใน Document ได้
บางเคส เราอาจจะทำงานบางอย่างที่มันต้องใช้เวลานาน ๆ หน่อย ถ้าเราปล่อยให้มันทำงานนิ่ง ๆ เลย ผู้ใช้ งง แน่ ๆ ว่าทำไมมันค้างฟร๊ะ มันทำงานอยู่มั้ยนะ มันไปแล้วเหรอ อะไร งง ไปหมด ทำให้การมี Progress Bar ให้ดู ก็เป็นวิธีนึงที่ทำให้ผู้ใช้รู้ว่า โปรแกรมของเรามันทำงานไปถึงไหนแล้ว และ อีกประมาณเท่าไหร่กว่าจะเสร็จกัน ซึ่งใน Python ก็มีคนทำ Module ออกมาให้เราใช้หลายตัวมาก ๆ แต่ตัวที่เราใช้อยู่คือ tqdm น่าจะเป็นตัวที่ใช้ง่ายที่สุดแล้ว
pip install tqdm
การติดตั้ง ไม่ได้ยากเลย เราสามารถทำผ่าน pip ได้ตรง ๆ เลย ส่วนใครใช้อย่างอื่นก็เอาชื่อ Package ไปหาได้เลย เราว่าน่าจะติดตั้งได้หมด
from tqdm import tqdm
result = 0
for i in tqdm(range(10000)) :
result += i
การใช้งานนั้นง่ายมาก ๆ อันนี้เป็นตัวอย่างที่เราพยายามให้เครื่องบวกเลขไปเรื่อย ๆ เราเริ่มจากการ Import tqdm เข้ามาก่อน จากนั้น เราก็เขียน For-Loop ปกติเหมือนที่เราเขียนใน Python เลย แต่แทนที่เราจะใช้ range() ตรง ๆ เราก็จะเอา tqdm() มาครอบ ก็จะได้ Progress Bar ออกมาแล้ว
ถ้าไปอ่านใน Document จริง ๆ คือ สิ่งที่ tqdm() มันต้องการคือ Generator อะไรก็ได้เลย เราก็แค่ Pass Generator เข้าไปก็ใช้งานได้แล้ว ง่ายมาก ๆ ส่วนพวก Option อื่น ๆ มันมีให้เรา Custom ได้หลายอย่างมาก ๆ ลองไปอ่านใน Document ของมันได้ในเว็บ
วันนี้เราก็ไปพาดูการเอาค่า และ ข้อความต่าง ๆ ออกทางหน้าจอหลายรูปแบบด้วยกัน ตั้งแต่ง่ายสุดเลยคือการใช้คำสั่ง print() เพื่อเอาข้อความออกทางหน้าจอ ไปเรื่อยจนถึงการใส่ตัวแปรลงไปด้วยวิธีต่าง ๆ ไปที่การทำตารางสวย ๆ ด้วย Module ชื่อ tabulate และสุดท้ายก็เป็นการทำ Progress Bar เพื่อให้ผู้ใช้รับรู้สถานะของโปรแกรมของเราด้วย ก็สามารถนำวิธีที่เราเล่าไปลองทำกันได้ แต่ละวิธีมันก็มีข้อดีข้อเสียกันอยู่ แนะนำให้ลองไปอ่านเพิ่มหน่อยมันมีรายละเอียดอีกหลายจุดมากที่เราไม่ได้เขียนมาด้วย ไม่งั้นยาวกว่านี้ไม่มีใครอ่านแน่นอน ฮ่า ๆ
เราเป็นคนที่อ่านกับซื้อหนังสือเยอะมาก ปัญหานึงที่ประสบมาหลายรอบและน่าหงุดหงิดมาก ๆ คือ ซื้อหนังสือซ้ำเจ้าค่ะ ทำให้เราจะต้องมีระบบง่าย ๆ สักตัวในการจัดการ วันนี้เลยจะมาเล่าวิธีการที่เราใช้ Obsidian ในการจัดการหนังสือที่เรามีกัน...
หากเราเรียนลงลึกไปในภาษาใหม่ ๆ อย่าง Python และ Java โดยเฉพาะในเรื่องของการจัดการ Memory ว่าเขาใช้ Garbage Collection นะ ว่าแต่มันทำงานยังไง วันนี้เราจะมาเล่าให้อ่านกันว่า จริง ๆ แล้วมันทำงานอย่างไร และมันมีเคสใดที่อาจจะหลุดจนเราต้องเข้ามาจัดการเองบ้าง...
ก่อนหน้านี้เราเปลี่ยนมาใช้ Zigbee Dongle กับ Home Assistant พบว่าเสถียรขึ้นเยอะมาก อุปกรณ์แทบไม่หลุดออกจากระบบเลย แต่การติดตั้งมันเข้ากับ Synology DSM นั้นมีรายละเอียดมากกว่าอันอื่นนิดหน่อย วันนี้เราจะมาเล่าวิธีการเพื่อใครเอาไปทำกัน...
เมื่อหลายวันก่อนมีพี่ที่รู้จักกันมาถามว่า เราจะโหลด CSV ยังไงให้เร็วที่สุด เป็นคำถามที่ดูเหมือนง่ายนะ แต่พอมานั่งคิด ๆ ต่อ เห้ย มันมีอะไรสนุก ๆ ในนั้นเยอะเลยนี่หว่า วันนี้เราจะมาเล่าให้อ่านกันว่า มันมีวิธีการอย่างไรบ้าง และวิธีไหนเร็วที่สุด เหมาะกับงานแบบไหน...