Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Function Decorators ใน Python: คู่มือฉบับสมบูรณ์

นักพัฒนา Python สามารถขยายและปรับเปลี่ยนพฤติกรรมของฟังก์ชัน เมธอด หรือคลาสที่เรียกใช้งานได้ (callable) โดยไม่ต้องแก้ไขโค้ดต้นฉบับอย่างถาวร โดยใช้ Decorators (ตัวตกแต่ง) โดยสรุปได้ว่า Decorators คือออบเจกต์ที่เรียกใช้งานได้ ซึ่งนำมาใช้เพื่อปรับเปลี่ยนฟังก์ชันหรือคลาส

Function Decorators คืออะไร?

Function Decorators คือฟังก์ชันที่รับการอ้างอิงฟังก์ชัน (function references) เป็นอาร์กิวเมนต์ เพิ่ม wrapper (คลาสหรือฟังก์ชันห่อหุ้ม) รอบๆ ฟังก์ชันนั้น และคืนค่าฟังก์ชันใหม่ที่ถูกห่อหุ้มไว้แล้ว

ไวยากรณ์พื้นฐาน

โค้ดต่อไปนี้:

@decorator
def func(arg):
    return "value"

เทียบเท่ากับ:

def func(arg):
    return "value"
func = decorator(func)

จากตัวอย่างข้างต้น เราจะเห็นว่า Decorator ก็คือฟังก์ชันอีกตัวหนึ่งที่รับฟังก์ชันเป็นอาร์กิวเมนต์ และคืนค่าฟังก์ชันกลับไป

Decorators "ตกแต่ง" หรือ "ห่อหุ้ม" ฟังก์ชันอื่น

Decorators ให้คุณรันโค้ดก่อนและหลังฟังก์ชันที่ถูกห่อหุ้มทำงาน ตัวอย่างเช่น:

def our_decorator(func):
    def function_wrapper(x):
        print("Before calling " + func.__name__)
        func(x)
        print("After calling " + func.__name__)
    return function_wrapper

def foo(x):
    print("Hi, foo has been called with " + str(x))

print("We call foo before decoration:")
foo("Hi")

print("We now decorate foo with f:")
foo = our_decorator(foo)

print("We call foo after decoration:")
foo(90)

ผลลัพธ์

We call foo before decoration:
Hi, foo has been called with Hi
We now decorate foo with f:
We call foo after decoration:
Before calling foo
Hi, foo has been called with 90
After calling foo

Decorator ที่เรียบง่ายที่สุด: Null Decorator

def null_decorator(func):
    return func

null_decorator เป็น callable ที่รับ callable อื่นเป็นอินพุต และคืนค่า callable เดิมนั้นๆ กลับไปโดยไม่ได้แก้ไขอะไรเลย

การใช้งาน Null Decorator

def null_decorator(func):
    return func

def greet():
    return "Hello, Python!"

greet = null_decorator(greet)
>>> greet()
'Hello, Python!'

ไวยากรณ์ @ (At Syntax) สำหรับ Decorators

วิธีที่สะดวกกว่าคือใช้ @ syntax เพื่อตกแต่งฟังก์ชันในขั้นตอนเดียว:

@null_decorator
def greet():
    return "Hello, Python!"

>>> greet()
'Hello, Python!'