ในบทที่ผ่านๆมาได้เรียนรู้ทั้งคำสั่งและฟังก์ชันต่างๆไปหลายรูปแบบหลายชนิด ทั้งหมดนั้นเป็นฟังก์ชันที่ถูกเตรียมไว้สามารถใช้ได้ทันทีโดยไม่ต้องมีการเตรียมการอะไรก่อน
แต่ก็ยังมีฟังก์ชันหรือคำสั่งบางส่วนที่ยังไม่สามารถใช้ได้ทันทีหากไม่มีการเรียกใช้ก่อน ซึ่งก็คือฟังก์ชันที่อยู่ภายในมอดูลต่างๆ
มอดูลภายในตัวและมอดูลเสริมภายนอก ฟังก์ชันและคำสั่งต่างๆที่สามารถเรียกมาเพิ่มเติมได้นั้นจะถูกเก็บในรูปของชุดคำสั่ง ซึ่งเรียกว่า
มอดูล (module) มีมอดูลมากมายที่ติดตัวมาตั้งแต่ติดตั้งภาษาไพธอน ซึ่งเรียกมอดูลเหล่านี้ว่
ามอดูลภายในตัว (built-in module) แต่ก็ยังมีมอดูลอีกประเภทที่ไม่ได้ติดตัวมาแต่แรก อาจถูกสร้างโดยนักเขียนโปรแกรมที่ไม่ได้มีส่วนเกี่ยวข้องกับกลุ่มผู้พัฒนาภาษาไพธอนโดยตรง แล้วก็ถูกนำมาแจกตามเว็บให้คนทั่วไปโหลด หรือเราเองก็อาจสามารถเขียนมันขึ้นมาเพิ่มเติมเองไว้ใช้เองได้ (เรื่องการสร้างมอดูลอ่านได้ใน
บทที่ ๓๔)
มอดูลเสริมเหล่านี้ต้องติดตั้งเพิ่มเติมเอาเองโดยโหลดตามเว็บ บางมอดูลแค่โหลดแล้วนำมาใส่ในโฟลเดอร์ก็สามารถใช้ได้ทันที แต่ก็มีอยู่หลายอันที่ต้องมีขั้นตอนในการติดตั้ง
อย่างไรก็ตามสำหรับ ใครที่ใช้โปรแกรมแพ็กเกจอย่าง anaconda จะมีมอดูลเสริมติดตัวอยู่แล้วเป็นจำนวนมาก สามารถเรียกใช้ได้ทันทีเช่นเดียวกับมอดูลภายในตัว
มอดูลเสริมมักถูกเก็บรวมอยู่แยกจากมอดูลภายในตัว โดยจะรวมอยู่ในโฟลเดอร์เดียว
เช่น สำหรับ python3.11 ที่ติดตั้งโดย anaconda ในแมคแล้วมอดูลเสริมถูกเก็บอยู่ใน
Users/<ชื่อผู้ใช้>/anaconda3/lib/python3.11/site-packages สำหรับในวินโดวส์จะเป็น
C:\Users\<ชื่อผู้ใช้>\Anaconda3\Lib\site-packages การเรียกใช้ คำสั่งที่ใช้ในการเรียกใช้มอดูลก็คือ
import
โดยพิมพ์
import
แล้วตามด้วยชื่อมอดูลที่ต้องการเรียกใช้
เช่น เรียกใช้มอดูลที่ชื่อ
math
ซึ่งเป็นมอดูลที่เก็บฟังก์ชันที่เกี่ยวกับการคำนวณทางคณิตศาสตร์
import math
เพียงเท่านี้ก็จะสามารถใช้ฟังก์ชันภายในมอดูล
math
ได้แล้ว
ขอยกตัวอย่างมาใช้ดูสักอัน เช่นฟังก์ชันชื่อ
sin
ซึ่งใช้คำนวณค่าไซน์ เวลาที่ใช้ก็ให้พิมพ์ชื่อมอดูลแล้วจึงตามด้วยชื่อฟังก์ชันนั้นโดยมีจุดคั่น
math.sin(1.57) # ได้ 0.9999996829318346
จะเห็นว่าชื่อฟังก์ชันในที่นี้อยู่ต่อจากจุด ดูแล้วคล้ายกับเมธอด แต่ความจริงแล้วไม่ใช่ ปกติจุด
.
เป็นตัวบอกถึงความสัมพันธ์แบบไล่เรียงหน่วยใหญ่ไปหาหน่วยเล็ก จุดในที่นี้แค่บอกว่าฟังก์ชันนี้เป็นฟังก์ชันในสังกัดของมอดูลไหนเท่านั้น
อย่างไรก็ตามจริงๆแล้วมอดูลก็ถือเป็นออบเจ็กต์ชนิดหนึ่ง ดังนั้นอาจมองว่าฟังก์ชันเป็นเมธอดของมอดูลก็ได้เช่นกัน เพราะเมธอดก็คือฟังก์ชันที่สังกัดอยู่กับออบเจ็กต์คลาสต่างๆนั่นเอง
หากใครเคยใช้ภาษาซีมาก่อนอาจคุ้นเคยกับคำว่า
include
คำสั่ง
import
ในภาษาไพธอนนี้เทียบเท่าได้กับ
include
ในภาษาซี คือเป็นการเรียกใช้ชุดคำสั่งที่จะมาใช้งานในโปรแกรม
เพียงแต่ในภาษา ไพธอนคำสั่งพื้นฐานต่างๆสามารถใช้ได้ทันทีโดยไม่ต้องเรียกใช้ก่อน ผิดกับภาษาซีซึ่งมักจะต้องเริ่มด้วยการเรียกใช้
stdio.h
และ
conio.h
เป็นประจำ
ดังนั้นทำให้การใช้งานในระดับพื้นฐานอาจไม่จำเป็นต้อง
import
อะไรเลย แต่พอต้องการใช้งานในระดับเฉพาะทางขึ้นมาหน่อยจึงจะเรียกใช้
หากลองเปรียบเทียบกับภาษาอื่นๆก็จะเห็นทั้งที่ใช้
include
และ
import
เช่นใน php ใช้
include
ในจาวาสคริปต์ใช้
import
ความหมายเหมือนกันเพียงแต่ในแต่ละภาษาใช้ต่างกันเท่านั้น
ในภาษาไพธอนมอดูลก็ถือว่าเป็นออบเจ็กต์ชนิดหนึ่ง คือออบเจ็กต์ชนิดมอดูล ลองใช้ฟังก์ชัน
type
เพื่อหาชนิดดูได้
print(type(math)) # ได้ <class 'module'>
ส่วนสิ่งที่มากับมอดูลนั้นอาจเป็นออบเจ็กต์ชนิดใดก็ได้มีได้หลายอย่าง ชนิดอาจแตกต่างกันออกไป โดยส่วนใหญ่แล้วจะเป็นฟังก์ชัน เช่น
print(type(math.sin)) # <class 'builtin_function_or_method'>
เนื่องจาก
math
เป็นมอดูลภายในตัว ดังนั้นฟังก์ชันที่อยู่ในนี้ก็เลยมีชนิดเป็นฟังก์ชันหรือเมธอดภายในตัว แต่หากเป็นฟังก์ชันในมอดูลชนิดอื่นก็อาจมีชนิดที่ต่างกันออกไป ซึ่งก็แล้วแต่ผู้สร้างมอดูลนั้นจะกำหนด
นอกจากฟังก์ชันแล้วมอดูลก็อาจประกอบด้วยข้อมูลหรือออบเจ็กต์ที่เป็นค่าตัวเลขหรือสายอักขระก็ได้ เช่น
print(math.pi) # ได้ 3.141592653589793
pi
นี้คือค่า π เป็นแค่ค่าคงที่ตัวหนึ่ง หากหาชนิดก็จะได้ว่าเป็น
float
การลบมอดูล หากไม่ต้องการใช้มอดูลไหนแล้วก็อาจลบทิ้งโดยใช้คำสั่ง
del
จากนั้นก็จะไม่สามารถใช้มอดูลนั้นได้อีกจนกว่าจำเรียกใช้ใหม่
del math
math.sin(1.57) # ได้ NameError: name 'math' is not defined
หรืออาจลบแค่ฟังก์ชันในมอดูลนั้นตัวเดียว เช่น
del math.sin
แบบนี้ก็จะใช้ไม่ได้แค่
math.sin
ส่วนฟังก์ชันอื่นเช่น
math.cos
ก็ยังใช้ได้อยู่
การละชื่อมอดูล โดยทั่วไปฟังก์ชันที่อยู่ภายในมอดูลที่เรียกเข้ามาด้วยคำสั่ง
import
ธรรมดานั้นเวลาจะใช้จะต้องมีชื่อมอดูลนำหน้าเสมอ
แต่ก็มีวิธีที่จะทำให้ไม่ต้องใส่ชื่อมอดูลนำหน้าก็ได้ ซึ่งทำได้โดยใช้คำสั่ง
from
เช่น
from math import *
เท่านี้ก็สามารถใช้ฟังก์ชันทั้งหมดในมอดูล
math
ได้โดยไม่จำเป็นต้องมี
math.
นำหน้าแล้ว เช่นพิมพ์แค่
sin(1.57)
ง่ายๆสั้นๆ
ดอกจัน
*
ในที่นี้มีความหมายว่าเรียกใช้ทุกสิ่งทุกอย่างที่อยู่ภายในมอดูลนั้นออกมา ให้หมด แต่ว่าถ้าหากอยากเรียกใช้แค่บางอันก็ทำได้โดยแค่เปลี่ยน
*
เป็นชื่อของสิ่งที่ต้องการใช้ เช่น
form math import sin
ถ้าทำแบบนี้ก็จะใช้ได้แค่ฟังก์ชัน
sin
ส่วนฟังก์ชันอื่นจะยังใช้ไม่ได้
อย่างไรก็ตามการใช้
from
กับ
*
นี้โดยทั่วไปแล้วจะไม่ใช้ถ้าไม่แน่ใจว่าจะไม่มีผลกระทบอะไร เนื่องจากแต่ละมอดูลอาจมีฟังก์ชันที่ชื่อเหมือนกัน ซึ่งจะทำให้เกิดการซ้อนทับกันได้ โดยฟังก์ชันจากมอดูลที่เรียกใช้ทีหลังจะไปทับของมอดูลตัวที่เรียกก่อน
สำหรับผู้เริ่มฝึกหัดแล้ว เพื่อความชัดเจนบางทีก็ควรจะเหลือชื่อมอดูลต้นทางเอาไว้น่าจะดีต่อการเรียน รู้มากกว่า ดังนั้นแนะนำว่าอย่าใช้
form
แต่ให้
import
โดยตรงดีกว่า
การย่อชื่อมอดูลและฟังก์ชัน หากชื่อยาวๆก็สามารถย่อลงได้ บ่อยครั้งที่ชุดคำสั่งยาวๆมักถูกย่อชื่อลง การย่อชื่อสามารถทำได้โดยเขียน as ต่อท้ายตามด้วยชื่อที่ต้องการย่อ เช่น
import random as rd
จากนั้นเวลาเรียกใช้มอดูลนี้ก็พิมพ์แค่ชื่อที่ถูกย่อแล้วตามด้วยชื่อฟังก์ชัน เช่น
rd.uniform(0,100) # จะได้ค่าเลขสุ่มซึ่งอยู่ในช่วง 0 ถึง 100
มอดูล
random
นี้เป็นมอดูลที่ประกอบด้วยฟังก์ชันที่เกี่ยวข้องกับการสุ่ม (รายละเอียดเกี่ยวมอดูล
random
อ่านได้ใน
https://phyblas.hinaboshi.com/20160508)
ฟังก์ชัน
uniform
นั้นจะคืนค่าเป็นจำนวนจริงสุ่มภายในช่วงระหว่างอาร์กิวเมนต์ ๒ ตัวที่ใส่ลงไป
สิ่งที่ย่อชื่อได้นั้นไม่เพียงแต่ชื่อมอดูลเท่านั้น แต่ชื่อฟังก์ชันภายในมอดูลก็สามารถย่อได้เช่นกัน เช่น
from random import uniform as unif
เพียงเท่านี้ก็สามารถใช้
random.uniform
ได้โดยพิมพ์แค่
unif(0,100)
ชื่อมอดูลที่ถูกเรียกขึ้นมานั้นมีสถานะเหมือนตัวแปรตัวหนึ่ง จะใช้ชื่อนี้เป็นตัวแปรทำอย่างอื่นอีกไม่ได้ ถ้าใช้จะถูกเขียนทับ เช่น
import math
math = 100
math.sin(1.57) # ได้ AttributeError: 'int' object has no attribute 'sin'
นั่นเพราะพอแทนค่าลงไปแบบนี้กลายเป็นว่าตัวแปรที่ชื่อ
math
ไปรับค่า
100
แล้วมันก็จะไม่ใช่เป็นมอดูลที่ชื่อ
math
อีกต่อไป กลายเป็นค่าจำนวนเต็มธรรมดา เราจะใช้มันไม่ได้อีกจนกว่าจะ
import
ใหม่
หรือแม้แต่เวลาที่ใช้ชื่อย่อก็เช่นกัน ต้องระวังไม่ให้ชื่อย่อนั้นไปซ้ำกับชื่อตัวแปรที่ต้องการจะใช้
มอดูลย่อยภายในมอดูลหลัก ปกติแล้วภายในมอดูลหนึ่งจะประกอบไปด้วยฟังก์ชันมากมายอยู่ บางทีฟังก์ชันภายในมอดูลนั้นเองก็อาจจะแบ่งเป็นหมวดหมู่ต่างๆซึ่งมีลักษณะ เฉพาะต่างกันออกไป
เมื่อเป็นแบบนี้บางมอดูลจึงได้มีการแบ่งมอดูลออก เป็นส่วนย่อยๆลงไปอีก เพื่อความเป็นระเบียบ มอดูลที่เป็นหน่วยย่อยลงไปอีกนั้นเรียกว่า
ซับมอดูล (submodule) ยกตัวอย่างเช่นมอดูลชื่อ
os
มอดูลนี้มีไว้สำหรับจัดการกับสิ่งที่เกี่ยวข้องกับระบบปฏิบัติการ เช่นฟังก์ชัน
os.uname
นั้นจะคืนค่าข้อมูลที่ใช้จำแนกบ่งบอกถึงตัวเครื่องนี้
os.getcwd
จะคืนค่าชื่อของโฟลเดอร์ที่ใช้ทำงานอยู่ (ที่อยู่ของไฟล์ที่รัน)
แต่ว่าภายในมอดูล
os
นี้ก็ยังประกอบไปด้วยมอดูลย่อยที่ชื่อว่า
path
อยู่ ภายในนี้มีฟังก์ชันที่เกี่ยวข้องกับพาธ (เส้นทางที่บ่งชี้ตำแหน่งของไฟล์หรือส่วนประกอบต่างๆ) เช่น
os.path.abspath
เป็นฟังก์ชันที่จะคืนค่าพาธสัมบูรณ์ของไฟล์
ตัวอย่างการใช้มอดูล
os
import os
print(os.uname())
print(os.getcwd())
print(os.path.abspath('untitled0.py'))
จะเห็นว่าเมื่อเรียกใช้มอดูล
os
โดย
import
เฉยๆเวลาที่ใช้
os.path.abspath
จะต้องพิมพ์ยาวไล่ตั้งแต่ชื่อมอดูลหลัก ตามด้วยชื่อมอดูลย่อย แล้วจึงจะเป็นชื่อฟังก์ชัน
อย่างไรก็ตามสามารถย่อได้โดยใช้
from
from os import path
แบบนี้ก็จะสามารถละ
os.
ด้านหน้าไปได้
path.abspath
หรือย่อกว่านั้นคือละชื่อมอดูลย่อยไปด้วย
from os.path import *
หรือ
from os.path import abspath
แบบนี้ก็จะใช้ฟังก์ชัน
abspath
ได้โดยพิมพ์แค่ชื่อ
abspath
มอดูลย่อยก็สามารถทำการย่อชื่อได้ เช่น
from os import path as op
หรือ
import os.path as op
สองแบบนี้มีค่าเท่ากัน คือเวลาเรียกใช้
abspath
จะต้องพิมพ์เป็น
op.abspath
จะเห็นได้ว่าการเรียกใช้มอดูลมีทางเลือกอยู่หลากหลาย มีความยืดหยุ่น ถือเป็นความสะดวกอย่างหนึ่งของภาษาไพธอน เพียงแต่อาจจะต้องเสียเวลาทำความเข้าใจกันสักเล็กน้อย
อนึ่ง มอดูลย่อยนั้นก็อาจจะมีมอดูลย่อยแยกเล็กลงไปอีก ซึ่งยิ่งย่อยก็จะยิ่งคั่นด้วยจุด . ไปเรื่อยๆ อาจมีย่อยลงไปอีกกี่ชั้นก็ได้ แล้วแต่คนออกแบบมอดูลจะออกแบบมา
คลาสที่มากับมอดูล สิ่งที่ได้มาจากการเรียกใช้มอดูลนั้นไม่ได้มีเพียงฟังก์ชันใหม่หรือตัวแปรใหม่ เท่านั้น แต่ยังทำให้สามารถใช้ออบเจ็กต์ชนิดใหม่ได้ด้วยหากในมอดูลนั้นมีการจำกัดความ คลาสใหม่เฉพาะขึ้นมา
เรื่องของการสร้างคลาสนั้นจะพูดถึงในบทหลังจาก นี้ไปอีกเพราะเป็นเรื่องที่ซับซ้อน แต่ในบทนี้จะพูดถึงคร่าวๆเกี่ยวกับการใช้ออบเจ็กต์จากคลาสที่ถูกสร้างภายใน มอดูลที่เรียกใช้
ในที่นี้ขอยกตัวอย่างมอดูล
fractions
ซึ่งเป็นมอดูลที่ใช้จัดการเลขเศษส่วน
การทำงานของมอดูลนี้ก็คือนิยามออบเจ็กต์ (หรือก็คือข้อมูล) ชนิดใหม่ขึ้นมาชนิดหนึ่ง ซึ่งก็คือ "เลขเศษส่วน"
แนวคิดของมอดูลนี้ก็คือ ปกติแล้วจะเห็นว่าตัวเลขจำนวนจริงต่างๆที่ถูกคำนวณภายในโปรแกรมนั้นจะอยู่ใน รูปของเลขทศนิยม แม้จะเป็นตัวเลขที่เขียนเศษส่วนแล้วดูเข้าใจง่ายกว่าก็ตาม
เช่น
1/3
ก็จะกลายเป็น
0.3333333333333333
ซึ่งค่าที่ได้ก็จะเป็นเพียงค่าประมาณเท่านั้น หากนำมาคำนวณก็อาจเกิดความคลาดเคลื่อนทีละเล็กน้อย
เพื่อรองรับความ จำเป็นในการใช้เลขในรูปของเศษส่วนซึ่งอาจเกิดขึ้นในบางสถานการณ์ มอดูล
fractions
จึงได้นิยามข้อมูลชนิดใหม่ ซึ่งสามารถเก็บตัวเลขให้อยู่ในรูปเศษส่วนได้
ตัวอย่างการใช้
import fractions
a = fractions.Fraction(1,3)
print(a) # ได้ 1/3
print(type(a)) # ได้ชนิดของข้อมูลเป็น <class 'fractions.Fraction'>
ในที่นี้จะเห็นว่าตัวแปร
a
กลายเป็นออบเจ็กต์ชนิดใหม่ ซึ่งก็คือชนิด
fractions.Fraction
ชื่ออาจจะดูยาวไปสักหน่อยเพราะต้องขึ้นต้นด้วยชื่อมอดูลก่อน
ตรงส่วน
a = fractions.Fraction(1,3)
นั้นเป็นการประกาศตัวแปรและใส่ค่าให้ โดยเวลาสร้างข้อมูลชนิดนี้ทำได้หลายวิธี แต่ในที่นี้ใช้วิธีที่ง่ายที่สุดก็คือใส่อาร์กิวเมนต์เป็นเลขเศษตามด้วยเลข ส่วน
มองดูแล้วอาจรู้สึกว่ายุ่งยากต้องพิมพ์ตั้งยาวขนาดนี้เพื่อแค่ให้ได้จำนวนเศษส่วนมาตัวหนึ่ง อย่างไรก็ตามสามารถย่อได้ เช่น
from fractions import Fraction as fr
a = fr(1,3)
แบบนี้จะดูง่ายขึ้นเยอะ เพียงแต่ว่าเวลาถามถึงชื่อชนิดข้อมูลโดย
print(type(a))
ก็ยังจะได้ผลเป็น
<class 'fractions.Fraction'>
เหมือนเดิม เพราะในที่นีคำว่า
fr
แค่มาแทน
fractions.Fraction
เพื่อความสะดวกเท่านั้น
ข้อมูลเลขเศษส่วนเวลาที่สั่ง print จะแสดงผลออกมาเป็นเลขเศษส่วน คือเป็นเลขเศษคั่นด้วย / แล้วตามด้วยเลขส่วน
นี่เป็นตัวอย่างคร่าวๆของการสร้างและใช้ออบเจ็กต์ชนิดใหม่ ที่จริงแล้วยังมีออบเจ็กต์อีกจำนวนมากมายหลายชนิดซึ่งจะต้องได้เจอต่อไปอีก เยอะ
ตัวอย่างมอดูลอื่นๆ หลังจากที่ได้ลองยกตัวอย่างมอดูลบางส่วนไปแล้ว คราวนี้จะลองยกตัวอย่างแนะนำมอดูลอื่นๆซึ่งเป็นมอดูลภายในตัว ที่จริงมีอยู่มากมายคงยกมาได้ไม่หมด เอาแค่ให้พอเห็นภาพโดยรวม
time
ทำหน้าที่จัดการเกี่ยวกับเวลา
datetime
ยามออบเจ็กต์ชนิดวันเวลาขึ้นมา ช่วยให้การคำนวณอะไรที่เกี่ยวกับวันเวลาเป็นไปได้อย่างสะดวก
decimal
นิยามเลขทศนิยมฐานสิบซึ่งมีความแม่นยำสูงกว่าเลขทศนิยมตามที่ต้องการ
sys
เก็บตัวแปรต่างๆที่ควบคุมจัดการระบบ
io
จัดการกับการรับเข้าและนำออกข้อมูล
re
สำหรับใช้เอ็กซ์เพรชชันแบบปกติ
platform
ให้ข้อมูลเกี่ยวกับแพล็ตฟอร์มที่ใช้อยู่
zipfile
สำหรับจัดการไฟล์ zip เช่นอัดรวมไฟล์และแตกไฟล์
นอกจากนี้ขอยกตัวอย่างมอดูลเสริมภายนอกที่เป็นที่นิยมจำนวนหนึ่งด้วย
numpy
นิยามออบเจ็กต์ชนิดแถวอาเรย์ที่สามารถคำนวณเมทริกซ์ ใช้ในการคำนวณได้อย่างมีประสิทธิภาพ
scipy
เครื่องมือสำคัญที่ใช้ในการคำนวณทางวิทยาศาสตร์
matplotlib
สำหรับวาดกราฟ
pandas
สำหรับจัดการกับข้อมูลอย่างเป็นระบบในรูปแบบตาราง
scikit-learn
สำหรับการเรียนรู้ของเครื่อง
mayavi
สำหรับวาดกราฟสามมิติ
py2exe
สำหรับเปลี่ยนโปรแกรมภาษาไพธอนให้เป็น .exe
xlrd
สำหรับจัดการไฟล์ excel
PyQt
/ PySide
สำหรับสร้างกราฟิกยูเซอร์อินเทอร์เฟซ (GUI)
OpenGL
สำหรับแสดงผลภาพกราฟิก
ในแพ็กเกจเช่น anaconda นั้นจะมีมอดูลเสริมอยู่หลายตัวติดมาตอนลงอยู่แล้ว แต่มอดูลไหนที่ไม่มีก็สามารถติดตั้งเพิ่มได้อย่างไม่ยาก
มอดูลเสริมมีอยู่มากมาย หากรู้ว่าตัวเองต้องการเขียนโปรแกรมสำหรับใช้งานด้านไหนก็ลองหามอดูลที่เกี่ยวข้อง จะมีประโยชน์สามารถใช้งานอะไรได้อย่างกว้างขวาง
สรุปเนื้อหา ในบทนี้ได้แนะนำให้รู้จักกับวิธีการเรียกใช้มอดูลและได้แนะนำมอดูลที่สำคัญไปส่วนหนึ่งแล้ว
การเรียกใช้มอดูลทำให้เราสามารถใช้ฟังก์ชันได้มากขึ้น หรือใช้คลาสใหม่ที่นิยามภายในมอดูลนั้นได้
มอดูลอาจประกอบไปด้วยมอดูลย่อย การเรียกใช้มอดูลมีอยู่หลายวิธี สามารถเลือกใช้ตามความเหมาะสม
อ้างอิง