ప్రధాన కంటెంట్‌కు వెళ్లండి
మాడ్యూల్ 9 · 4లో పాఠం 4కోర్సులో 36/36~14 min
మాడ్యూల్ పాఠాలు (4/4)

డెకరేటర్లు: ఫంక్షన్లను సవరించే విధులు

ఒక డెకరేటర్ అనేది మరొక ఫంక్షన్‌ని తీసుకొని aని తిరిగి ఇచ్చే ఒక ఫంక్షన్ దాని "అలంకరించిన" వెర్షన్. ప్రవర్తనను జోడించడానికి ఇది ఒక శక్తివంతమైన మార్గం శరీరాన్ని తాకకుండా (లాగింగ్, టైమింగ్, కాషింగ్, మళ్లీ ప్రయత్నించడం, ధ్రువీకరణ). అసలు విధి.

విలువలుగా విధులు

పైథాన్‌లో, విధులు వస్తువులు: మీరు వాటిని పాస్ చేయవచ్చు, వాటిని తిరిగి ఇవ్వవచ్చు, వాటిని కేటాయించవచ్చు.

Python
def saluta():
    print("ciao")

f = saluta   # NIENTE parentesi: assegno la funzione
f()          # 'ciao'

కనీస డెకరేటర్

Python
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) అసైన్‌మెంట్ @తో మరింత సొగసైనదిగా వ్రాయబడింది:

Python
@log
def somma(a, b):
    return a + b

ఇది సరిగ్గా అదే విషయం. నిర్వచనం పైన @log దీనికి సమానం: "ఈ ఫంక్షన్ నిర్వచించబడిన వెంటనే, దానిని log(function)తో భర్తీ చేయండి".

*args, **kwargs: ఏదైనా సంతకాన్ని ఆమోదించండి

Python
def wrapper(*args, **kwargs):
    return func(*args, **kwargs)

*args స్థాన ఆర్గ్యుమెంట్‌లను, **kwargs కీవర్డ్ ఆర్గ్యుమెంట్‌లను సేకరిస్తుంది. వారు అనుమతించారు మీరు ఏదైనా ఫంక్షన్‌తో పని చేసే రేపర్‌లను వ్రాస్తారు.

functools.wraps: మెటాడేటాను భద్రపరచండి

wraps లేకుండా, అలంకరించబడిన ఫంక్షన్ __name__, __doc__, సూచనలు:

Python
from functools import wraps

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        ...
        return func(*args, **kwargs)
    return wrapper

ఉదాహరణ: @timeit

Python
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 నుండి డెకరేటర్లు

Python
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) కాల్‌ల సమయంలో అలంకరించబడిన ఫంక్షన్‌కు పంపబడిన వాస్తవ ఆర్గ్యుమెంట్‌లను అందుకుంటుంది.

మీరే ప్రయత్నించండి

వ్యాయామం#python.m9.l4.e1
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

డెకరేటర్ `డబుల్_ఫలితం`ని వ్రాయండి, అది అలంకరించబడిన ఫంక్షన్‌ని పిలిచి దాని ఫలితాన్ని అందిస్తుంది * 2. దాన్ని x + 1ని అందించే ఫంక్షన్ `f(x)`కి వర్తింపజేయండి. `f(10)`ని మూల్యాంకనం చేయండి.

ఎడిటర్ లోడ్ అవుతోంది…
సూచనను చూపించు

రేపర్ ఫంక్‌ని పిలుస్తుంది మరియు ఫలితాన్ని 2తో గుణించబడుతుంది.

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది

వ్యాయామం సమీక్షించండి

వ్యాయామం#python.m9.l4.e2
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

పునరావృత fib(n) ఫంక్షన్‌ని వేగవంతం చేయడానికి functools.lru_cacheని ఉపయోగించండి. fib(30)ని గణించి, `r`కి కేటాయించండి. `r`ని మూల్యాంకనం చేయండి.

ఎడిటర్ లోడ్ అవుతోంది…
సూచనను చూపించు

@lru_cache(maxsize=nene) డెఫ్ పైన.

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది

అదనపు సవాలు

వ్యాయామం#python.m9.l4.e3
ప్రయత్నాలు: 0లోడ్ అవుతోంది...

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)`.

ఎడిటర్ లోడ్ అవుతోంది…
సూచనను చూపించు

రేపర్ ఫంక్ (*ఆర్గ్స్, **క్వార్గ్స్) అని పిలుస్తుంది మరియు ఫలితాన్ని 2తో గుణిస్తుంది.

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది