فهم Decorators في بايثون
Decorators هي ميزة قوية في بايثون تتيح لك تعديل أو توسيع سلوك الدوال أو الأساليب دون تغيير كودها الفعلي. يتم ذلك عن طريق “تغليف” الدالة بدالة أخرى.
إنشاء Decorator بسيط
Decorator هو ببساطة دالة تأخذ دالة أخرى كوسيط، تضيف إليها بعض السلوك، وتعيد دالة جديدة. إليك مثال:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
my_decorator
: هذه هي دالة الـ decorator التي تأخذ دالة func
وتغلفها بسلوك إضافي.
wrapper
: الدالة الداخلية التي تضيف سلوكًا قبل وبعد استدعاء func
.
@my_decorator
: هذه هي صيغة كتابة مختصرة لتطبيق الـ decorator على say_hello
. إنها تعادل say_hello = my_decorator(say_hello)
.
استخدام Decorators مع الوسائط
إذا كانت دالتك الأصلية تأخذ وسائط، تحتاج إلى تعديل الـ decorator لقبول *
args و **kwargs
لتمرير تلك الوسائط إلى الدالة المغلفة:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
مثال عملي: قياس وقت تنفيذ الدالة
أحد الاستخدامات الشائعة للـ decorators هو قياس وقت تنفيذ دالة. إليك كيفية إنشاء decorator للوقت:
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time} seconds to execute.")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(2)
print("Function complete.")
slow_function()
التمارين
التمرين 1
اكتب Decorator يطبع “Before function call” و “After function call” قبل وبعد تنفيذ الدالة المزيّنة.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
التمرين 2
أنشئ Decorator يسجل اسم الدالة والوسائط الخاصة بها في كل مرة يتم فيها استدعاء الدالة.
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with arguments {args} and {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_decorator
def add(a, b):
return a + b
result = add(3, 5) # Output: Calling add with arguments (3, 5) and {}
print(f"Result: {result}")
التمرين 3
عدل الـ timing decorator لطباعة الوقت المستغرق بالميلي ثانية بدلاً من الثواني.
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {(end_time - start_time) * 1000} milliseconds to execute.")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(1)
print("Function complete.")
slow_function()
عمل رائع! لقد تعلمت كيفية استخدام Decorators في بايثون لتعديل وتوسيع سلوك الدوال بطريقة نظيفة وقابلة لإعادة الاستخدام. هذه أداة قوية لإضافة وظائف إلى كودك دون تعديل الدالة الأصلية.
اترك تعليقاً