Decorators in Python
דקורטורים הם כלי רב עוצמה ושימושי בPython מכיוון שהוא מאפשר למתכנתים לשנות את ההתנהגות של פונקציה או מחלקה. דקורטורים מאפשרים לנו לעטוף פונקציה נוספת על מנת להרחיב את התנהגות הפונקציה העטופה, מבלי לשנות אותה לצמיתות. אבל לפני שנצלול עמוק לתוך הנושא בואו נבין כמה מושגים שיועילו בלימוד הנושא.
אובייקט מחלקה ראשונה
ב-Python, פונקציות הן אובייקטים מהשורה הראשונה, מה שאומר שניתן להשתמש בפונקציות ב-Python או להעביר אותן כארגומנטים.
מאפיינים של פונקציות מחלקה ראשונה:
פונקציה היא מופע מסוג אובייקט.
אתה יכול לאחסן את הפונקציה במשתנה.
ניתן להעביר את הפונקציה כפרמטר לפונקציה אחרת.
אתה יכול להחזיר את הפונקציה מפונקציה.
אתה יכול לאחסן אותם במבני נתונים כגון טבלאות, רשימות, …
בדוק את הדוגמאות שלהלן להבנה טובה יותר…
# Python program to illustrate functions
# can be treated as objects def shout(text): return text.upper()
print(shout('Hello'))
yell = shout
print(yell('Hello')) |
Output:
HELLO
HELLO
בדוגמה לעיל, הקצינו את הפונקציה shout למשתנה. זה לא יקרא לפונקציה במקום זאת, הוא לוקח את אובייקט הפונקציה שאליו מתייחסים צעקה ויוצר שם שני שמצביע עליו
.
# Python program to illustrate functions
# can be passed as arguments to other functions def shout(text): return text.upper()
def whisper(text): return text.lower()
def greet(func): # storing the function in a variable greeting = func("""Hi, I am created by a function passed as an argument.""") print (greeting)
greet(shout) greet(whisper) |
Output:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.
בדוגמה שלמעלה, פונקציית הברכה לוקחת פונקציה נוספת כפרמטר (צעקה ולחש במקרה זה). הפונקציה שהועברה כארגומנט נקראת אז בתוך הפונקציה greet.
דוגמה 3: החזרת פונקציות מפונקציה אחרת.
# Python program to illustrate functions
# Functions can return another function
def create_adder(x):
def adder(y):
return x+y
return adder
add_15 = create_adder(15)
print(add_15(10))
Output:
25
בדוגמה שלמעלה, יצרנו פונקציה בתוך פונקציה אחרת ולאחר מכן החזרנו את הפונקציה שנוצרה בפנים.
שלוש הדוגמאות לעיל מתארות את המושגים החשובים הדרושים להבנת הנושא. לאחר שעברנו עליהם, תנו לנו עכשיו לצלול עמוק לתוך הנושא העיקרי ד.
מעצבים
כפי שצוין לעיל, המעצבים משמשים כדי לשנות את התנהגות הפונקציה או המעמד. ב-Decorators, פונקציות נלקחות כארגומנט לפונקציה אחרת ולאחר מכן נקראות בתוך פונקציית העטיפה.
תחביר עבור דקורטורים:
כפי שצוין לעיל, הדקורטורים משמשים כדי לשנות את התנהגות הפונקציה או המעמד. ב-Decorators, פונקציות נלקחות כארגומנט לפונקציה אחרת ולאחר מכן נקראות בתוך פונקציית העטיפה.
דקורטורים :
@gfg_decorator
def hello_decorator():
print("Gfg")
"'Above code is equivalent to –
def hello_decorator():
print("Gfg")
hello_decorator = gfg_decorator(hello_decorator)"'
בקוד שלמעלה, gfg_decorator היא פונקציה הניתנת להתקשרות, שתוסיף קוד כלשהו בחלק העליון של פונקציה נוספת, פונקציית hello_decorator ותחזיר את פונקציית ה-wrapper.
דקורטור יכול לשנות את ההתנהגות:
# defining a decorator
def hello_decorator(func):
# inner1 is a Wrapper function in
# which the argument is called
# inner function can access the outer local
# functions like in this case "func"
def inner1():
print("Hello, this is before function execution")
# calling the actual function now
# inside the wrapper function.
func()
print("This is after function execution")
return inner1
# defining a function, to be called inside wrapper
def function_to_be_used():
print("This is inside the function !!")
# passing 'function_to_be_used' inside the
# decorator to control its behaviour
function_to_be_used = hello_decorator(function_to_be_used)
# calling the function
function_to_be_used()
Output:
Hello, this is before function execution
This is inside the function !!
This is after function execution
בואו נראה את ההתנהגות של הקוד לעיל וכיצד הוא פועל שלב אחר שלב כאשר קוראים ל-"function_to_beused".
בואו נקפוץ לדוגמא נוספת שבה נוכל לגלות בקלות את זמן הביצוע של פונקציה באמצעות דקורטור.
בעוד דוגמאות קוד נעמיק ב קורס Python
# importing libraries
import time import math
# decorator to calculate duration # taken by any function. def calculate_time(func):
# added arguments inside the inner1, # if function takes any arguments, # can be added like this. def inner1(*args, **kwargs):
# storing time before function execution begin = time.time()
func(*args, **kwargs)
# storing time after function execution end = time.time() print("Total time taken in : ", func.__name__, end – begin)
return inner1
# this can be added to any function present, # in this case to calculate a factorial @calculate_time def factorial(num):
# sleep 2 seconds because it takes very less time # so that you can see the actual difference time.sleep(2) print(math.factorial(num))
# calling the function. factorial(10) |
Output:
3628800
Total time taken in : factorial 2.0061802864074707
מה אם פונקציה מחזירה משהו או ארגומנט מועבר לפונקציה?
בכל הדוגמאות לעיל הפונקציות לא החזירו כלום אז לא הייתה בעיה, אבל ייתכן שצריך את הערך המוחזר.
def hello_decorator(func):
def inner1(*args, **kwargs):
print("before Execution")
# getting the returned value
returned_value = func(*args, **kwargs)
print("after Execution")
# returning the value to the original frame
return returned_value
return inner1
# adding decorator to the function
@hello_decorator
def sum_two_numbers(a, b):
print("Inside the function")
return a + b
a, b = 1, 2
# getting the value through return of the function
print("Sum =", sum_two_numbers(a, b))
Output:
before Execution
Inside the function
after Execution
Sum = 3
בדוגמה לעיל, ייתכן שתבחין בהבדל חד בפרמטרים של הפונקציה הפנימית. הפונקציה הפנימית לוקחת את הארגומנט בתור *args ו-**kwargs מה שאומר שניתן להעביר טופלה של ארגומנטים או מילון של ארגומנטים של מילות מפתח בכל אורך. זה הופך אותו למעצב כללי שיכול לקשט פונקציה עם כל מספר של ארגומנטים
שרשור של דקורטורים:
במונחים פשוטים יותר שרשור מעצבים פירושו לקשט פונקציה עם מספר דקורטורים..
דוגמא:
# code for testing decorator chaining
def decor1(func): def inner(): x = func() return x * x return inner
def decor(func): def inner(): x = func() return 2 * x return inner
@decor1 @decor def num(): return 10
print(num()) |
Output:
400
הדוגמה שלמעלה דומה לקריאת הפונקציה –
decor1(decor(num))