Python: decorator คืออะไร

Grassroot Engineer
3 min readJan 2, 2021

--

https://www.codeforests.com/2020/08/07/use-of-python-decorator/

ในบทความนี้จะแนะนำเกี่ยวกับ @ ที่เราเรียกมันว่า decorator ในภาษา Python จริงๆแล้วมันคือ ตัวที่เอาไว้ตกแต่ง function หรือ class ฉะนั้นในการใช้จึงต้องวางไว้ด้านบนของ function หรือ class นั่นเอง (เพราะมันคือ function ที่ครอบ function อีกที)

หลักการของมันคือ การ pass function เข้าไปใน function (ปกติการ pass argument เข้าไป เราจะนึกถึงแค่ค่าคงที่หรือตัวแปรเท่านั้น แต่จริงๆแล้ว function ก็สามารถ pass เข้าไปได้เช่นกัน)

หรือ อธิบายเชิงวิชาการ มันคือ design pattern ที่จะช่วย extend หรือ modify ความสามารถของ fucntion หรือ class นั้นๆ โดยที่เราไม่ต้องไปเปลี่ยน source code ในส่วนนั้น

Ex1:

import time

def logging_time(func):
def logger():
start = time.time() # The current Unix epoch time
print('start = ', start)
func()
print(f"Calling {func.__name__}: {time.time() - start:.5f}")
return logger

@logging_time
def calculate_sum():
return sum(range(100000000)) # This line just want to delay during calculate.

calculate_sum()

อธิบายตามนี้ครับ
การทำงานหลังจากที่มีการเรียกใช้ function calculate_sum() จะเร่ิมจาก
1. Function
calculate_sum() จะถูก pass เข้าไปที่ decorator logging_time() ก่อนโดยมีตัวแปร func มารับ
2. จากนั้นจะเข้าไปทำงานที่ function
logger() โดยหาค่า current Unix epoch time ออกมาในบรรทัดที่ 5
3. จากนั้นมาที่บรรทัดที่ 7 คือ execute function
calculate_sum() ผ่านทางตัวแปร func() เลย
4. มาที่บรรทัดที่ 13 เพื่อรอให้
sum(range(100000000)) ทำเสร็จก่อน (แค่ simulate ให้เหมือนว่ามีการคำนวณอะไรบางอย่างเฉยๆ)
5. เมื่อคำนวณในบรรทัดที่ 13 เสร็จแล้ว จะกลับไปทำงานที่บรรทัดที่ 8 ต่อ คือ คำนวณเวลาที่ใช้ไปโดยแสดงเป็นทศนิยม 5 ตำแหน่ง
6. กลับมาที่
calculate_sum() เป็นอันสิ้นสุดการทำงาน

อธิบายการเชื่อมโยงของ decorator ใน 3 steps นะคับ
ผลลัพธ์จากการรัน

Ex2: เป็นการพื้นที่รูปวงกลมและวงรี ซึ่งจะพบว่ามีจุดทศนิยมค่อนข้างเยอะเลย

ผลลัพธ์ปกติ เมื่อยังไม่ได้ใช้ decorator

เราสามารถ implement เพิ่มโดยสร้าง decorator มาครอบได้เลย โดยเริ่มจากสร้าง decorator function เป็น template แบบนี้ก่อน

def new_format_number(func):
def new_function():
func()
return new_function

จากนั้นให้ implement func ที่รับเข้าไปเพิ่ม โดยให้สามารถรับ argument ได้ด้วย *args, **kwargs เพื่อให้รับค่ากี่ตัวก็ได้ จากนั้นก้อ reformat ใหม่ตามบรรทัดที่ ​6 ก่อนจะ return ออกไป

ตัวอย่างการประยุกต์ใช้ในการจัดการ format ด้วย decorator

Ex3: เป็นการประยุกต์ใช้ timeในการตรวจเช็คเวลาทั้งหมด ที่ฟังก์ชันใช้ในการทำงาน

import time

def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
import pdb; pdb.set_trace()
end_time = time.time()
print(f"Executed {func.__name__} in {end_time - start_time:.6f} seconds.")
return result
return wrapper

@timer
def long_running_function():
time.sleep(2)

long_running_function()
# Output: "Executed long_running_function in 2.000208 seconds."
Step by step เลยนะ

สรุป : การใช้ decorator function เพื่อตกแต่งเปลี่ยน function นึงให้มีการทำงานมากขึ้น

PS: เราสามารถใช้งาน multi decorator ได้ด้วย โดยการทำงานจะ execute จากล่างขึ้นบนนะ เช่น

def lowercase_decorator(function):
def wrapper(arg):
func = function(arg)
string_lowercase = func.lower()
return string_lowercase
return wrapper

def splitter_decorator(function):
def wrapper(arg):
func = function(arg)
string_split = func.split()
return string_split
return wrapper

@splitter_decorator
@lowercase_decorator
def get_list_of_lowercase_word(input):
return input



print(get_list_of_lowercase_word('HeLLo WoRlD'))
print(get_list_of_lowercase_word('Q Electronics'))
แสดงการทำงานที่ตัวล่างก่อน

--

--

Grassroot Engineer
Grassroot Engineer

Written by Grassroot Engineer

ATM engineer who is interested in CODING and believe in EFFORT. — https://grassrootengineer.com

No responses yet