ماڈیول اسباق (4/4)
ڈیکوریٹر: فنکشنز جو فنکشنز کو تبدیل کرتے ہیں۔
A ڈیکوریٹر ایک فنکشن ہے جو ایک اور فنکشن لیتا ہے اور a واپس کرتا ہے۔ اس کا "سجا ہوا" ورژن۔ یہ رویے کو شامل کرنے کا ایک طاقتور طریقہ ہے۔ (لاگنگ، ٹائمنگ، کیشنگ، دوبارہ کوشش، توثیق) کے باڈی کو چھوئے بغیر اصل فنکشن.
اقدار کے طور پر کام کرتا ہے۔
Python میں، فنکشنز آبجیکٹ ہیں: آپ انہیں پاس کر سکتے ہیں، انہیں واپس کر سکتے ہیں، انہیں تفویض کر سکتے ہیں۔
def saluta():
print("ciao")
f = saluta # NIENTE parentesi: assegno la funzione
f() # 'ciao'ایک کم سے کم ڈیکوریٹر
def log(func):
def wrapper(*args, **kwargs):
print(f"chiamo {func.__name__}")
risultato = func(*args, **kwargs)
print(f"ho finito {func.__name__}")
return risultato
return wrapper
def somma(a, b):
return a + b
somma = log(somma) # ora somma è "wrapper"
somma(2, 3)
# chiamo somma
# ho finito somma
# 5@decorator نحو
اسائنمنٹ somma = log(somma) کو @ کے ساتھ زیادہ خوبصورتی سے لکھا گیا ہے:
@log
def somma(a, b):
return a + bیہ بالکل وہی چیز ہے۔ @log اوپر کی تعریف اس کے مساوی ہے:
"جیسے ہی اس فنکشن کی وضاحت ہو جائے، اسے log(function) سے بدل دیں۔"
*args, **kwargs: کوئی بھی دستخط قبول کریں۔
def wrapper(*args, **kwargs):
return func(*args, **kwargs)*args پوزیشن کے دلائل جمع کرتا ہے، **kwargs کلیدی الفاظ کے دلائل۔ انہوں نے اجازت دی۔
آپ ریپر لکھتے ہیں جو کسی بھی فنکشن کے ساتھ کام کرتے ہیں۔
functools.wraps: میٹا ڈیٹا کو محفوظ کریں۔
wraps کے بغیر، سجا ہوا فنکشن __name__، __doc__، اشارے کھو دیتا ہے:
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
...
return func(*args, **kwargs)
return wrapperمثال: @timeit
from functools import wraps
import time
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
t0 = time.perf_counter()
risultato = func(*args, **kwargs)
dt = time.perf_counter() - t0
print(f"{func.__name__} ha impiegato {dt*1000:.2f} ms")
return risultato
return wrapper
@timeit
def somma_grande():
return sum(range(10**6))
somma_grande()stdlib سے ڈیکوریٹر
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2: return n
return fib(n - 1) + fib(n - 2)
fib(100) # istantaneo grazie alla cache@lru_cache— خالص فنکشن کے نتائج کو یاد کرتا ہے۔@property— ایک طریقہ کو بطور وصف ظاہر کرتا ہے (OOP ماڈیول میں دیکھا گیا ہے)۔@staticmethod,@classmethod— تبدیل کریں کہselfکو کیسے منتقل کیا جاتا ہے۔
دلائل کے ساتھ سجانے والے
سجانے والے بھی دلائل قبول کر سکتے ہیں۔ اس کو نافذ کرنے کے لیے، آپ کو نیسٹڈ فنکشنز کی تین سطحیں لکھنی ہوں گی: سب سے باہر کا فنکشن ڈیکوریٹر کے آرگومنٹس وصول کرتا ہے، درمیانی فنکشن ڈیکوریٹڈ فنکشن وصول کرتا ہے، اور سب سے اندرونی فنکشن (wrapper) کالز کے دوران ڈیکوریٹڈ فنکشن کو بھیجے گئے اصل دلائل وصول کرتا ہے۔
خود ہی آزمائیں۔
ایک ڈیکوریٹر `ڈبل_رزلٹ` لکھیں جو ڈیکوریٹڈ فنکشن کو کال کرے اور اس کا نتیجہ واپس کرے * 2۔ اسے ایک فنکشن `f(x)` پر لاگو کریں جو x + 1 لوٹائے۔ `f(10)` کا اندازہ کریں۔
اشارہ دکھائیں۔
ریپر فنک کو کال کرتا ہے اور 2 سے ضرب دے کر نتیجہ لوٹاتا ہے۔
3 کوششوں کے بعد حل دستیاب ہے۔
ورزش کا جائزہ لیں۔
recursive fib(n) فنکشن کو تیز کرنے کے لیے functools.lru_cache استعمال کریں۔ fib(30) کی گنتی کریں اور `r` کو تفویض کریں۔ `r` کا اندازہ لگائیں۔
اشارہ دکھائیں۔
@lru_cache(maxsize=None) def کے اوپر۔
3 کوششوں کے بعد حل دستیاب ہے۔
اضافی چیلنج
Define a decorator `double_result` that doubles (multiplies by 2) the return value of the decorated function. Apply the decorator to the function `def sum_nums(a, b): return a + b`. Finally, evaluate `sum_nums(3, 4)`.
اشارہ دکھائیں۔
ریپر فنک (*args، **kwargs) کو کال کرتا ہے اور نتیجہ کو 2 سے ضرب دیتا ہے۔
3 کوششوں کے بعد حل دستیاب ہے۔