Home › Hindi › Python decorator Hindi में
Python Decorator — @ का असली मतलब और काम के examples
🌐 यह page Hindi में है · Read the English functions guide →
@ असल में क्या हैfunctools.wraps ज़रूरी हैArguments वाले decorator3 काम के examples
Decorator असल में क्या है
Decorator एक function है जो दूसरे function को लेता है और उसे बिना बदले extra behaviour देकर नया function लौटा देता है। @name सिर्फ एक shortcut है — नीचे दोनों बराबर हैं:
def shout(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print("हो गया!")
return result
return wrapper
@shout
def greet(name):
return f"नमस्ते {name}"
# यही चीज़ बिना @ के:
def greet2(name):
return f"नमस्ते {name}"
greet2 = shout(greet2) # @shout का पूरा मतलब यही एक line है
print(greet("Asha"))
तो decorator में कोई जादू नहीं है: यह function को function से बदलना है। तीन हिस्से याद रखो — बाहरी function decorator को लेता है, अंदर वाला wrapper असली काम करता है, और return wrapper नया function वापस देता है।
functools.wraps — यह मत भूलना
wrapper लपेटने के बाद असली function की पहचान खो जाती है — नाम, docstring, सब:
def shout(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@shout
def greet(name):
'''नमस्कार कहता है।'''
return name
print(greet.__name__) # 'wrapper' — असली नाम खो गया!
print(greet.__doc__) # None
Fix एक line का है, और हर असली decorator में होना चाहिए:
from functools import wraps
def shout(func):
@wraps(func) # नाम, docstring, signature सब बचा लेता है
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@shout
def greet(name):
'''नमस्कार कहता है।'''
return name
print(greet.__name__) # 'greet' ✅
print(greet.__doc__) # 'नमस्कार कहता है।' ✅
@wraps के बिना debugging बहुत मुश्किल हो जाती है — traceback में हर जगह wrapper दिखता है।
3 decorator जो रोज़ काम आते हैं
import time
from functools import wraps
# 1. कितना समय लगा — सबसे useful decorator
def timing(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
try:
return func(*args, **kwargs)
finally:
print(f"{func.__name__} ने {time.perf_counter() - start:.4f}s लिया")
return wrapper
# 2. हर call log करना
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"-> {func.__name__}{args} {kwargs}")
return func(*args, **kwargs)
return wrapper
# 3. कितनी बार call हुआ
def counted(func):
@wraps(func)
def wrapper(*args, **kwargs):
wrapper.calls += 1
return func(*args, **kwargs)
wrapper.calls = 0
return wrapper
@timing
@log
def work(n):
return sum(range(n))
work(1000)
print(work.calls)
वह stacking भी समझ लो: @timing ऊपर और @log नीचे है, तो पहले log लपेटता है और उसके बाद timing — यानी ऊपर वाला सबसे बाहर चलता है।
Arguments वाला decorator
अगर decorator को खुद setting लेनी हो (जैसे @retry(times=3)), तो एक level और गहरा जाना पड़ता है:
def retry(times=3):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
last = None
for attempt in range(1, times + 1):
try:
return func(*args, **kwargs)
except Exception as e:
last = e
print(f"कोशिश {attempt} नाकाम: {e}")
raise last
return wrapper
return decorator
@retry(times=2)
def flaky():
import random
if random.random() < 0.7:
raise ValueError("अभी नहीं")
return "चल गया"
याद रखो: @retry(times=2) में parentheses हैं, इसलिए retry(times=2) पहले चलकर decorator लौटाता है। @retry और @retry() अलग-अलग चीज़ें हैं।
Common गलतियाँ
@wrapsभूल जाना — नाम और docstring खो जाते हैं, traceback बेकार हो जाता है।return func(...)भूल जाना — wrapperNoneलौटाएगा और caller को कुछ नहीं मिलेगा। यह सबसे common decorator bug है।*args, **kwargsके बिना wrapper — decorator सिर्फ उन्हीं functions पर चलेगा जिनका signature मेल खाता है।- Decorator में भारी काम — decorator import/definition के वक्त एक बार चलता है, हर call पर नहीं। Setup वहाँ रखो, असली काम wrapper में।
🛠️ Practice करो (free, browser में)
पढ़ना काफी नहीं — यही bug खुद fix करके देखो। नीचे के problems browser में ही चलते हैं, कोई install नहीं, कोई login नहीं।
- Function returning nothing — return भूलना — decorator का नंबर-1 bug।
- Custom exception messages — retry decorator के साथ useful।
- Exception handling Hindi में — try/except/else/finally पूरा।
अक्सर पूछे जाने वाले सवाल
Decorator असल में क्या करता है?
यह एक function को लेता है और नया function लौटाता है जो पुराने को लपेटकर extra काम करता है। @name सिर्फ shortcut है — @shout के ऊपर लिखना और greet = shout(greet) लिखना बिल्कुल बराबर है। कोई जादू नहीं, सिर्फ function को function से बदलना।
functools.wraps क्यों ज़रूरी है?
क्योंकि उसके बिना लपेटे गए function का नाम 'wrapper' हो जाता है और docstring None — जिससे traceback और help() बेकार हो जाते हैं। @wraps(func) असली function का नाम, docstring और signature नए wrapper पर कॉपी कर देता है। हर असली decorator में यह होना चाहिए।
मेरा decorated function None क्यों लौटा रहा है?
क्योंकि wrapper में return func(*args, **kwargs) लिखना भूल गए। Wrapper का return ही caller को मिलता है; अगर wrapper कुछ return नहीं करता तो caller को None मिलेगा, भले ही असली function सही value बना रहा हो।
Decorator कब चलता है — definition पर या हर call पर?
दोनों हिस्से अलग वक्त चलते हैं। बाहरी decorator function import/definition के वक्त एक बार चलता है, और wrapper हर call पर। इसलिए कोई भी setup decorator के body में रखो और असली काम wrapper के अंदर।