Python decorators เป็น feature หนึ่งของภาษา Python ซึ่ง feature นี้ไม่ใช่ Decorator pattern นะครับ เพียงแต่ว่าสามารถนำไปใช้ทำ pattern แบบนั้นได้
ความสามารถของมันก็คือ มันสามารถที่จะเปลี่ยนแปลงพฤติกรรมการทำงานของฟังก์ชั่นหรือคลาสที่เราเอา decorator ที่เขียนขึ้นไปแปะไว้ได้ ประโยชน์ของมันคือเราไม่ต้องเข้าไปแก้ไขการทำงานของฟังก์ชั่นหรือคลาสนั้นๆ โดยไม่จำเป็น หรือถ้าเราไม่อยากจะเข้าไปแก้ไขการทำงานนั้นๆ เลย เราก็ใช้ decorator เข้ามาช่วยครับ บทความนี้จะขอยกตัวอย่างแค่การใช้ decorator กับฟังก์ชั่นธรรมดาง่ายๆ นะครับให้พอเห็นภาพ
สมมุติว่าเรามีฟังก์ชั่น fizzbuzz ตามนี้
def fizzbuzz(number):
if number % 3 == 0 and number % 5 == 0:
return 'fizzbuzz'
elif number % 3 == 0:
return 'fizz'
elif number % 5 == 0:
return 'buzz'
else:
return number
แล้วเราอยากจะให้แสดงผลออกมาแบบมีข้อความขึ้นสักหน่อยเช่น Your input is 3, so you get fizz. ถ้าเราสะดวกเราก็เข้าไปแก้ฟังก์ชั่นของเราเลยใช่ไหมครับ เราก็จะได้ฟังก์ชั่นหน้าตาแบบนี้
def fizzbuzz(number):
result = 'Your input is ' + str(number) + ', so you get '
if number % 3 == 0 and number % 5 == 0:
result += 'fizzbuzz'
elif number % 3 == 0:
result += 'fizz'
elif number % 5 == 0:
result += 'buzz'
else:
result += str(number)
return result + '.'
ดูแล้วไม่ค่อยน่าทำเลยใช่ไหมครับ? เรามาลองใช้ decorator กันดีกว่า ให้เราสร้าง nested function หรือ inner function ขึ้นมาตามนี้ (ที่ต้องทำตามนี้เพราะว่านี่เป็น syntax ของ Python decorator ครับ)
def have_nice_message(func):
def wrap(number):
result = 'Your input is ' + str(number) + ', so you get '
result += func(number)
result += '.'
return result
return wrap
วิธีใช้งานเราก็แค่เอาไปแปะไว้บนหัวของฟังก์ชั่นที่เราต้องการตามนี้
@have_nice_message
def fizzbuzz(number):
if number % 3 == 0 and number % 5 == 0:
return 'fizzbuzz'
elif number % 3 == 0:
return 'fizz'
elif number % 5 == 0:
return 'buzz'
else:
return number
ผลลัพธ์ที่ได้ก็จะเหมือนกันโค้ดที่เราเข้าไปเพิ่มข้อความ แต่โค้ดที่เราได้มาจะดูสะอาดตามากขึ้น ฟังก์ชั่นเราก็ยังคงทำหน้าที่เหมือนเดิมตามปกติ 🙂