Tutorial

รวม 3 Decorator ที่ใช้บ่อยใน Python

By Arnon Puitrakul - 02 กันยายน 2021

รวม 3 Decorator ที่ใช้บ่อยใน Python

ตอนก่อน เรามาเล่าเรื่อง Decorator ใน Python กันไปแล้ว มาในตอนนี้เราอยากจะมาเล่าถึง 3 Decorator ที่เราใช้บ่อย ๆ ส่วนใหญ่จะเป็น Snippet เขียนเองทั้งนั้น วันนี้มาดูกันว่าจะมี Decorator ตัวไหนบ้าง

timeme

ตัวแรกที่เราใช้บ่อยมาก ๆ คือการวัดเวลาในการทำงานของส่วนต่าง ๆ ของ Code โดยเฉพาะช่วงทำ Thesis อยากรู้ว่า Function มันใช้เวลาเท่าไหร่ เลยลองเขียนเป็น Decorator ง่าย ๆ ขึ้นมาตัวนึง เพื่อวัดเวลา

import time
import functools

def timeme (func) :
    
    @functools.wraps(func)
    def measure_time (*args,**kwargs) :
        start_time = time.time()
        result = func(*args,**kwargs)
        elapsed = time.time() - start_time
        
        print(func.__name__, 'ran for', elapsed, 'sec(s)')
        return result        

    return measure_time

@timeme
def cal_result (max_num) :
    result = 0
    for num in range(max_num) :
        result += num

cal_result(10000000)

เราสร้างเป็น Wrapper Function ง่าย ๆ เอา ส่วนของตัววัดเวลามาคล่อมเอาเลย ทำให้เราได้เวลาในการรัน Function นั้น ๆ ออกมาได้เลย หรือจริง ๆ แล้ว ถ้าเราไม่อยากให้มัน Print ออกมา เมื่อ Function รันเสร็จ เราอาจจะเก็บใส่ไว้ใน Decorator แล้วเราก็ค่อยเรียกออกมาเวลาที่เราต้องการก็ทำได้เหมือนกัน แต่ปกติเวลาเราใช้งาน เราจะใส่เพื่อ Test เฉย ๆ เลยให้มัน Print ออกมาเลย จะได้ง่าย ๆ

dataclass

อันถัดไปใช้บ่อยไม่แพ้กันคือ dataclass ตัวนี้เราไม่ต้องเขียนเอง เพราะมันมีมากับ Python แล้ว ก่อนจะเข้าเรื่องของ Decorator นี้ เราจะต้องเกริ่นก่อนว่า เวลาเราเขียน Class เราจะต้องเขียนสิ่งที่เรียกว่า Constructor ซึ่งถ้าเราจะต้องทำอะไรในนั้นนอกจาก การ Init พวก Attribute ต่าง ๆ เขียนเองมันก็โอเคแหละ แต่ถ้าเราทำแค่นั้นละ เขียนแค่นั้นทุกครั้งมันก็น่าเบื่อแย่เลย dataclass เข้ามาช่วยแก้ปัญหาเรื่องนี้ได้เป็นอย่างดีเลย

from dataclass import dataclass

@dataclass
class Person:
    name: str
    surname: str
    age: int = 1
        
    def full_name(self) -> str:
        return name + ' ' + surname

thomas = Person('Thomas', 'Edison', 84)

จะเห็นว่า ใน Class Person เราไม่ได้เขียน Constructor เลย แต่ตอนที่เราเอา Class ออกมาสร้างเป็น Object เราใช้ Constructor ที่ใส่ของเข้าไป 3 อย่าง ซึ่งเราไม่ได้ประกาศเอง เป็นสิ่งที่ dataclass มันทำให้เราเอง จะเห็นได้เลยว่า การใช้ dataclass ทำให้การสร้าง Constructor ง่ายขึ้นเยอะ เพราะเราไม่ต้องเขียนเอง ฮ่า ๆ

Singletons

และตัวสุดท้ายของวันนี้คือ Singletons ก่อนเราจะไปเข้าใจว่ามันทำอะไร เรามาเข้าใจ Concept ของ Singleton อย่างง่าย ๆ ก่อน ตามชื่อของมันเลยคือ Single ที่ไม่ได้แปลว่าโสด แต่แปลว่า หนึ่ง หรือก็คือ เป็น Object หรือตัวแปรอะไรบางอย่างที่เราจะกำหนดให้มันมีเพียงตัวเดียวเท่านั้น เช่น Pointer ในการอ่านไฟล์ หรือ Object บางอย่างที่เราต้องการ Sync ระหว่างส่วนต่าง ๆ ของโปรแกรมเรา Concept นี้ เราอาจจะไม่เคยได้ยินบน Python เท่าไหร่ แต่ถ้าเขียนพวก C/C++ มา อาจจะเคยได้ยินมาก่อน มันใช้เยอะมาก ๆ ช่วยชีวิตเรามาเยอะละ มาเขียน Python เราเลยอยากพา Concept นี้มาใช้ด้วย แต่นางไม่มี เราก็ต้องเขียนเองไป

def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class AnyClass:
    pass

ด้านในของ Singleton เราสร้าง instances เป็น Dict มาเพื่อเก็บ Object ที่เราสร้างเอาไป เพื่อให้ใน wrapper() ก่อนที่เราจะสร้าง Object เราจะเอาไปเช็คก่อนว่าใน instances มันมีอยู่แล้วมั้ย ถ้ามี ก็คืน Instance ที่เคยสร้างไว้ไป แต่ถ้าไม่มี มันก็จะสร้างอันใหม่ลงไป ในการใช้งาน เราก็แค่ยัด Decorator ลงไปบน Class ได้เลย

x = AnyClass()
y = AnyClass()

เรามาลองสร้าง Object จาก Class ที่เราใส่ Decorator Singleton เอาไว้ จาก Code ด้านบน ถ้าเราทำแบบนี้ปกติ เราน่าจะได้ Object 2 อันออกมาแต่เราใส่ Singleton มาแล้ว แปลว่า x และ y ควรจะเป็น Instance เดียวกัน เราลองมาเช็คกันดีกว่า

>>> x == y
True

เราลองเช็คดู เราจะเห็นได้เลยว่า x และ y เป็นตัวเดียวกันเลย ถ้าเราลอง Mutate x ตัว y ก็จะต้องเปลี่ยนตามด้วย เพราะมันคือตัวเดียวกัน นี่แหละคือความ Singleton อย่างง่ายใน Python

สรุป

3 Decorator ที่เราเอามาให้ดูกันในวันนี้จริง ๆ เป็นแค่ส่วนนึงของ Decorator ที่เราเขียนเอาไว้ใช้งานทั่ว ๆ ไป จริง ๆ มีอีกเป็นร้อยตัวเลย แต่เอาอันที่ใช้บ่อย ๆ ออกมาเล่า ถ้าใครอยากก๊อปไปใช้ก็ได้เลย มันไม่ได้เขียนยากอะไรมาก ถ้าใครมี Decorator เจ๋ง ๆ เอามาแชร์กันได้

Read Next...

โหลด CSV วิธีไหนเร็วที่สุด ?

โหลด CSV วิธีไหนเร็วที่สุด ?

เมื่อหลายวันก่อนมีพี่ที่รู้จักกันมาถามว่า เราจะโหลด CSV ยังไงให้เร็วที่สุด เป็นคำถามที่ดูเหมือนง่ายนะ แต่พอมานั่งคิด ๆ ต่อ เห้ย มันมีอะไรสนุก ๆ ในนั้นเยอะเลยนี่หว่า วันนี้เราจะมาเล่าให้อ่านกันว่า มันมีวิธีการอย่างไรบ้าง และวิธีไหนเร็วที่สุด เหมาะกับงานแบบไหน...

ฮาวทู Sync Obsidian Note ด้วย LiveSync Plugin

ฮาวทู Sync Obsidian Note ด้วย LiveSync Plugin

ตั้งแต่ใช้ Obsidian เป็น App จด Note หลัก ชอบวิธีการจัดการมาก ๆ เมื่อใช้งานร่วมกับ Plugin ต่าง ๆ ยิ่งทำให้การใช้งานยืดหยุ่นมากกว่าเดิมอีกเยอะมาก ๆ ติดอยู่เรื่องเดียวคือ การใช้งานในหลาย ๆ อุปกรณ์ แต่เราเจอ Plugin ตัวนึงที่น่าสนใจมาก ๆ คือ LiveSync วันนี้เราจะมาเล่าวิธีการติดตั้ง และใช้งานมันกัน...

การสร้าง SSD Storage Pool บน Synology DSM

การสร้าง SSD Storage Pool บน Synology DSM

สำหรับคนที่ใช้ Synology NAS บางรุ่นจะมีช่อง M.2 สำหรับเสียบ NVMe SSD โดยพื้นฐาน Synology บอกว่ามันสำหรับการทำ Cache แต่ถ้าเราต้องการเอามันมาทำเป็น Storage ละ มันจะทำได้มั้ย วันนี้เราจะมาเล่าวิธีการทำกัน...

Multiprogramming, Multiprocessing และ Multithreading

Multiprogramming, Multiprocessing และ Multithreading

หลังจากที่เรามาเล่าเรื่อง malloc() มีคนอยากให้มาเล่าเรื่อง pthread เพื่อให้สามารถยัด Content ที่ละเอียด และเข้าใจง่ายในเวลาที่ไม่นานเกินไป เลยจะมาเล่าพื้นฐานที่สำคัญของคำ 3 คำคือ Multiprogramming, Multitasking, Multiprocessing และ Multithreading...