ವಿಷಯಕ್ಕೆ ತೆರಳಿ

ಡೆಕೊರೇಟರ್‌ಗಳ ಪರಿಚಯ (Introduction to Decorators)

ಪೈಥಾನ್‌ನಲ್ಲಿ, ಡೆಕೊರೇಟರ್ (Decorator) ಒಂದು ವಿಶೇಷವಾದ ಫಂಕ್ಷನ್ ಆಗಿದ್ದು, ಅದು ಬೇರೆ ಫಂಕ್ಷನ್ ಅಥವಾ ಕ್ಲಾಸ್‌ನ ನಡವಳಿಕೆಯನ್ನು (behavior) ಅದರ ಮೂಲ ಕೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸದೆ ವಿಸ್ತರಿಸಲು ಅಥವಾ ಮಾರ್ಪಡಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಡೆಕೊರೇಟರ್‌ಗಳು ಪೈಥಾನ್‌ನ ಒಂದು ಶಕ್ತಿಯುತ ವೈಶಿಷ್ಟ್ಯವಾಗಿದ್ದು, ಕೋಡ್ ಅನ್ನು ಹೆಚ್ಚು ಕ್ಲೀನ್, ಮರುಬಳಕೆ ಮಾಡಬಲ್ಲ ಮತ್ತು ನಿರ್ವಹಿಸಲು ಸುಲಭವಾಗಿಸುತ್ತದೆ.

ಡೆಕೊರೇಟರ್‌ಗಳು ಹೆಚ್ಚಾಗಿ @ ಚಿಹ್ನೆಯೊಂದಿಗೆ ಬಳಸಲ್ಪಡುತ್ತವೆ.

ಫಂಕ್ಷನ್ ಡೆಕೊರೇಟರ್ (Function Decorator)

ಒಂದು ಫಂಕ್ಷನ್ ಅನ್ನು ಇನ್ನೊಂದು ಫಂಕ್ಷನ್‌ಗೆ ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ಪಾಸ್ ಮಾಡಿ, ಅದರ ಕಾರ್ಯವನ್ನು ವಿಸ್ತರಿಸುವುದೇ ಫಂಕ್ಷನ್ ಡೆಕೊರೇಟರ್.

ಸರಳ ಡೆಕೊರೇಟರ್ ರಚಿಸುವುದು

ಕೆಳಗಿನ ಉದಾಹರಣೆಯಲ್ಲಿ, ಒಂದು ಫಂಕ್ಷನ್ ಕಾರ್ಯಗತಗೊಳ್ಳುವ ಮೊದಲು ಮತ್ತು ನಂತರ ಸಂದೇಶವನ್ನು ಪ್ರಿಂಟ್ ಮಾಡುವ ಸರಳ ಡೆಕೊರೇಟರ್ ಅನ್ನು ರಚಿಸೋಣ.

def my_decorator(func):
    def wrapper():
        print("ಫಂಕ್ಷನ್ ಕಾರ್ಯಗತಗೊಳ್ಳುವ ಮೊದಲು...")
        func()
        print("ಫಂಕ್ಷನ್ ಕಾರ್ಯಗತಗೊಂಡ ನಂತರ.")
    return wrapper

@my_decorator
def say_hello():
    print("ಹಲೋ, ಮಗಾ ಕೋಡ್ ಮಾಡು!")

say_hello()

ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ? 1. @my_decorator ಸಿಂಟ್ಯಾಕ್ಸ್, say_hello ಫಂಕ್ಷನ್ ಅನ್ನು my_decorator ಫಂಕ್ಷನ್‌ಗೆ ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ಪಾಸ್ ಮಾಡುತ್ತದೆ. 2. my_decorator ಫಂಕ್ಷನ್, wrapper ಎಂಬ ಹೊಸ ಫಂಕ್ಷನ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ. 3. say_hello() ಅನ್ನು ಕಾಲ್ ಮಾಡಿದಾಗ, ವಾಸ್ತವವಾಗಿ wrapper() ಫಂಕ್ಷನ್ ಕಾರ್ಯಗತಗೊಳ್ಳುತ್ತದೆ. 4. wrapper ಫಂಕ್ಷನ್ ಒಳಗೆ, ಮೂಲ say_hello() ಫಂಕ್ಷನ್ (func()) ಕಾಲ್ ಆಗುತ್ತದೆ.

ಡೆಕೊರೇಟರ್‌ಗೆ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಪಾಸ್ ಮಾಡುವುದು

ಮೂಲ ಫಂಕ್ಷನ್‌ಗೆ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳಿದ್ದರೆ, ಡೆಕೊರೇಟರ್‌ನ wrapper ಫಂಕ್ಷನ್ ಕೂಡ ಆ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಬೇಕು.

def smart_divide_decorator(func):
    def wrapper(a, b):
        print(f"{a} ಮತ್ತು {b} ಅನ್ನು ಭಾಗಿಸಲಾಗುತ್ತಿದೆ.")
        if b == 0:
            print("ಸೊನ್ನೆಯಿಂದ ಭಾಗಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ!")
            return
        return func(a, b)
    return wrapper

@smart_divide_decorator
def divide(a, b):
    print(a / b)

divide(10, 2)
divide(10, 0)

@functools.wraps ಬಳಕೆ

ಡೆಕೊರೇಟರ್ ಬಳಸಿದಾಗ, ಮೂಲ ಫಂಕ್ಷನ್‌ನ ಮೆಟಾಡೇಟಾ (ಹೆಸರು, ಡಾಕ್‌ಸ್ಟ್ರಿಂಗ್, ಇತ್ಯಾದಿ) ಕಳೆದುಹೋಗುತ್ತದೆ. ಇದನ್ನು ತಡೆಯಲು functools ಮಾಡ್ಯೂಲ್‌ನ @wraps ಡೆಕೊರೇಟರ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ.

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """ಇದು ವ್ರ್ಯಾಪರ್ ಫಂಕ್ಷನ್‌ನ ಡಾಕ್‌ಸ್ಟ್ರಿಂಗ್."""
        print("ಕಾರ್ಯದ ಮೊದಲು...")
        result = func(*args, **kwargs)
        print("ಕಾರ್ಯದ ನಂತರ.")
        return result
    return wrapper

@my_decorator
def greet(name):
    """ಒಬ್ಬ ವ್ಯಕ್ತಿಯನ್ನು ಸ್ವಾಗತಿಸುವ ಫಂಕ್ಷನ್."""
    print(f"ನಮಸ್ಕಾರ, {name}!")

print(f"ಫಂಕ್ಷನ್ ಹೆಸರು: {greet.__name__}")
print(f"ಡಾಕ್‌ಸ್ಟ್ರಿಂಗ್: {greet.__doc__}")
@wraps(func) ಬಳಸುವುದರಿಂದ, greet ಫಂಕ್ಷನ್‌ನ ಮೂಲ ಹೆಸರು ಮತ್ತು ಡಾಕ್‌ಸ್ಟ್ರಿಂಗ್ ಹಾಗೆಯೇ ಉಳಿಯುತ್ತದೆ.

ಕ್ಲಾಸ್ ಡೆಕೊರೇಟರ್ (Class Decorator)

ಫಂಕ್ಷನ್‌ಗಳಂತೆ, ಕ್ಲಾಸ್‌ಗಳನ್ನು ಕೂಡ ಡೆಕೊರೇಟ್ ಮಾಡಬಹುದು. ಕ್ಲಾಸ್ ಡೆಕೊರೇಟರ್‌ಗಳು ಸಾಮಾನ್ಯವಾಗಿ ಕ್ಲಾಸ್‌ನ ನಡವಳಿಕೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಥವಾ ವಿಸ್ತರಿಸಲು ಬಳಸಲಾಗುತ್ತದೆ.

ಉದಾಹರಣೆಗೆ, ಒಂದು ಕ್ಲಾಸ್‌ಗೆ ಹೆಚ್ಚುವರಿ ಅಟ್ರಿಬ್ಯೂಟ್ ಸೇರಿಸುವ ಡೆಕೊರೇಟರ್:

def add_version(version):
    def class_decorator(cls):
        @functools.wraps(cls)
        def wrapper(*args, **kwargs):
            instance = cls(*args, **kwargs)
            instance.version = version
            return instance
        return wrapper
    return class_decorator

@add_version("1.0.2")
class MyAPI:
    def __init__(self, name):
        self.name = name

api_instance = MyAPI("My Awesome API")
print(f"API ಹೆಸರು: {api_instance.name}")
print(f"API ಆವೃತ್ತಿ: {api_instance.version}")
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, @add_version ಡೆಕೊರೇಟರ್ MyAPI ಕ್ಲಾಸ್‌ಗೆ version ಎಂಬ ಹೊಸ ಅಟ್ರಿಬ್ಯೂಟ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ.

ಡೆಕೊರೇಟರ್‌ಗಳು ಲಾಗಿಂಗ್, ಟೈಮಿಂಗ್, ದೃಢೀಕರಣ (authentication) ಮತ್ತು ಕ್ಯಾಶಿಂಗ್ (caching) ನಂತಹ ಕ್ರಾಸ್-ಕಟಿಂಗ್ ಕನ್ಸರ್ನ್‌ಗಳನ್ನು (cross-cutting concerns) ನಿರ್ವಹಿಸಲು ಅತ್ಯಂತ ಉಪಯುಕ್ತವಾಗಿವೆ.