Python Decorator dan Context Manager: Encapsulasi Logic dengan Elegan

Lhuqita Fazry
Python Programming Python Design Patterns
Python Decorator dan Context Manager: Encapsulasi Logic dengan Elegan

Decorator adalah pola desain yang memungkinkan kita memodifikasi perilaku function tanpa mengubah source code aslinya. Context manager menyediakan mekanisme untuk mengelola resource seperti file atau koneksi database dengan pattern setup dan teardown yang terjamin. Kedua fitur ini membantu kita menulis code yang lebih bersih, reusable, dan mudah dimaintain. Mereka merepresentasikan first-class functions dan duck typing philosophy yang membuat Python expressive dan powerful.

Decorator Adalah Function Wrapper

Decorator pada dasarnya adalah function yang menerima function lain sebagai argument dan mengembalikan function baru. Syntax @ di Python menyediakan cara elegan untuk menerapkan decorator.

pythonpython
def uppercase_decorator(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

@uppercase_decorator
def say_hello():
    return "hello world"

print(say_hello())

Output:

text
HELLO WORLD

Function uppercase_decorator menerima say_hello sebagai argument. wrapper function mengeksekusi function asli dan memodifikasi return value sebelum dikembalikan. Syntax @ secara otomatis melewati function yang didekorasi ke decorator. Hasilnya adalah function baru dengan perilaku yang diperluas tanpa modifikasi definisi asli. Kita juga dapat menumpuk multiple decorator pada satu function dengan menuliskannya secara berurutan dari atas ke bawah.

Membuat Decorator untuk Mengukur Execution Time

Salah satu use case paling umum untuk decorator adalah profiling performance. Kita dapat membungkus function dengan timing logic yang reusable.

pythonpython
import time
from functools import wraps

def timer_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__} executed in {end - start:.4f}s")
        return result
    return wrapper

@timer_decorator
def slow_function():
    time.sleep(0.5)
    return "done"

@timer_decorator
def compute_sum(n):
    return sum(range(n))

slow_function()
compute_sum(1000000)

Output:

text
slow_function executed in 0.5001s
compute_sum executed in 0.0203s

Decorator timer_decorator menggunakan @wraps dari functools untuk mempertahankan metadata function asli. Tanpa @wraps, attribute seperti __name__ dan __doc__ akan tertimpa oleh wrapper. Decorator ini menerima args dan *kwargs sehingga kompatibel dengan function apa pun. Hasil timing dicetak ke console dan function tetap mengembalikan nilai aslinya. Pattern ini sering kita temui di web framework dan data pipeline untuk monitoring bottleneck.

Implementasi Retry Logic dengan Decorator

Decorator juga efektif untuk mengimplementasikan cross-cutting concerns seperti retry mechanism. Pattern ini berguna saat kita berinteraksi dengan service eksternal yang tidak stabil.

pythonpython
import time
from functools import wraps

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(1, max_attempts + 1):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    print(f"Attempt {attempt} failed: {e}")
                    if attempt == max_attempts:
                        raise
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

@retry(max_attempts=3, delay=0.5)
def unstable_function():
    import random
    if random.random() < 0.7:
        raise RuntimeError("Service unavailable")
    return "success"

result = unstable_function()
print(result)

Output:

text
Attempt 1 failed: Service unavailable
Attempt 2 failed: Service unavailable
success

Decorator retry menerima parameter sehingga kita dapat mengkonfigurasi max_attempts dan delay. Pattern ini disebut decorator factory. Function wrapper menangkap exception dan mencoba eksekusi ulang hingga batas attempt tercapai. Jika semua attempt gagal, exception terakhir akan di-raise kembali ke caller. Pattern ini sangat berguna untuk HTTP requests, database connections, atau API calls yang mengalami transient failures.

Data Science with Python
Data Science • Beginner

Data Science with Python

Master the art of data analysis, visualization, and predictive modeling.

Daftar

Context Manager Mengelola Resource Secara Aman

Context manager memastikan resource dibuka dan ditutup dengan benar. Statement with di Python menjamin cleanup code dijalankan meskipun terjadi exception di tengah proses.

pythonpython
class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connected = False

    def __enter__(self):
        print(f"Connecting to {self.db_name}...")
        self.connected = True
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing connection to {self.db_name}...")
        self.connected = False
        return False

    def query(self, sql):
        if not self.connected:
            raise RuntimeError("Not connected")
        return f"Result for: {sql}"

with DatabaseConnection("production_db") as db:
    result = db.query("SELECT * FROM users")
    print(result)

print(f"Connected after with block: {db.connected}")

Output:

text
Connecting to production_db...
Result for: SELECT * FROM users
Closing connection to production_db...
Connected after with block: False

Method __enter__ dijalankan saat konteks dimulai. Method __exit__ dijalankan saat blok with selesai. Parameter exc_type, exc_val, dan exc_tb menyimpan informasi exception jika terjadi error. Return value False dari __exit__ membiarkan exception propagate ke caller. Return value True akan men-swallow exception. Protocol ini dikenal sebagai context management protocol dan menjadi dasar dari statement with di Python.

Menyederhanakan Context Manager dengan contextlib

Modul contextlib menyediakan decorator contextmanager yang mengubah generator function menjadi context manager. Pendekatan ini menghasilkan code yang lebih ringkas dibandingkan class-based approach.

pythonpython
from contextlib import contextmanager

@contextmanager
def managed_file(filename, mode):
    file = open(filename, mode)
    try:
        yield file
    finally:
        file.close()

with managed_file("output.txt", "w") as f:
    f.write("Hello from context manager")

with managed_file("output.txt", "r") as f:
    content = f.read()
    print(content)

Output:

text
Hello from context manager

Decorator @contextmanager menghasilkan context manager dari generator function. Statement yield memisahkan setup code dan teardown code. Code sebelum yield adalah setup, code setelah yield (biasanya dalam blok finally) adalah teardown. Pattern ini ideal untuk resource management yang sederhana dan menghindari boilerplate class. Mayoritas context manager di codebase modern menggunakan pendekatan ini karena lebih readable.

Context Manager Bawaan yang Sering Digunakan

Python menyediakan beberapa context manager bawaan yang powerful. Modul contextlib memiliki utilitas tambahan selain @contextmanager.

pythonpython
from contextlib import suppress, redirect_stdout
import io

# suppress: ignore specific exception
with suppress(FileNotFoundError):
    with open("nonexistent.txt", "r") as f:
        content = f.read()

# redirect_stdout: capture print output
buffer = io.StringIO()
with redirect_stdout(buffer):
    print("This goes to buffer")
    print("Not to console")

print("Captured:", buffer.getvalue())

Output:

text
Captured: This goes to buffer
Not to console

suppress secara elegan mengabaikan exception tertentu tanpa blok try-except yang verbose. redirect_stdout berguna untuk testing function yang mencetak output ke console. Kedua utilitas ini menunjukkan bagaimana context manager dapat menyederhanakan code yang biasanya memerlukan boilerplate ekstensif.

Menggabungkan Decorator dan Context Manager dalam Satu Workflow

Kedua pola ini sering digunakan bersama dalam codebase production. Decorator meng-encapsulasi behavior yang reusable, sedangkan context manager menangani lifecycle resource.

pythonpython
from contextlib import contextmanager
from functools import wraps
import time

def log_execution(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Starting {func.__name__}...")
        result = func(*args, **kwargs)
        print(f"Finished {func.__name__}")
        return result
    return wrapper

@contextmanager
def timed_context(label):
    start = time.perf_counter()
    yield
    elapsed = time.perf_counter() - start
    print(f"{label} took {elapsed:.4f}s")

@log_execution
def process_data():
    with timed_context("data processing"):
        time.sleep(0.3)
        print("Processing complete")

process_data()

Output:

text
Starting process_data...
Processing complete
data processing took 0.3001s
Finished process_data

Decorator log_execution membungkus function dengan log messages. Context manager timed_context mengukur waktu eksekusi blok spesifik. Kombinasi ini menghasilkan code yang modular dan mudah ditrace tanpa menambah complexity ke business logic utama. Kita dapat menambah atau menghapus concern tanpa mengubah implementasi function inti. Separation of concerns menjadi lebih jelas dan maintenance lebih mudah dilakukan.

Kapan Menggunakan Decorator atau Context Manager

Gunakan decorator ketika kita perlu menambahkan behavior secara transversal ke multiple functions. Timing, logging, caching, dan autentikasi adalah contoh kasus yang ideal untuk decorator. Decorator memungkinkan kita mengaplikasikan concern yang sama ke banyak function dengan satu baris syntax. Mereka mendukung separation of concerns dengan cara yang Pythonic.

Gunakan context manager ketika kita perlu mengelola state dan resource dengan jaminan cleanup. File I/O, database transactions, dan lock acquisition adalah scenario yang cocok untuk pattern ini. Context manager memastikan resource tidak leak meskipun terjadi exception. Cleanup code selalu dijalankan sehingga program tetap stabil.

Kedua fitur ini merupakan fundamental Python yang sering muncul di framework populer seperti Flask, Django, dan SQLAlchemy. Memahami cara kerja internal decorator dan context manager membantu kita membaca dan menulis library Python dengan lebih percaya diri. Investasi waktu untuk memahami kedua pattern ini akan mempercepat workflow development secara signifikan.

Mau menguasai pattern Python seperti decorator dan context manager secara praktis? Bergabunglah dengan Python Bootcamp di Rumah Coding. Kurikulum berbasis project dengan bimbingan mentor profesional.

Course Terkait

E-commerce Sales Dashboard
Premium Course Data Science

Data Science with Python

Master the art of data analysis, visualization, and predictive modeling.

Capstone Project

E-commerce Sales Dashboard

  • Data Cleaning Pipeline
  • Interactive Charts
  • Sales Forecasting Model
7 Weeks Beginner
Lihat Detail Course
GreenGuard: Intelligent Plant Disease Diagnosis Web App
Premium Course Machine Learning

Deep Learning Bootcamp

A beginner-friendly, highly interactive bootcamp designed to take you from foundational concepts to deploying real-world Artificial Intelligence applications. Through a completely project-based approach, you will master the core of Deep Learning, Artificial Neural Networks, and Computer Vision using Python and TensorFlow, ultimately building a professional-grade AI web application for your portfolio.

Capstone Project

GreenGuard: Intelligent Plant Disease Diagnosis Web App

  • Interactive Image Upload UI: A clean, user-friendly interface built with Streamlit that supports drag-and-drop image uploads directly from a computer or mobile phone.
  • Real-Time AI Inference: Utilizes a lightweight, optimized CNN model (like MobileNetV2) to process the image and return a diagnosis in seconds without heavy server load.
  • Confidence Scoring Dashboard: Visually displays the model's prediction probability (e.g., "95% confident this is Tomato Late Blight") using interactive progress bars or charts.
7 Weeks Intermediate
Lihat Detail Course
Domain-Specific AI Knowledge Assistant
Premium Course Machine Learning

LLM Bootcamp

This project-based bootcamp is designed for beginners to dive practically into the world of Large Language Models (LLMs). Through hands-on building, you will learn how to interact with top-tier AI APIs, master prompt engineering, orchestrate complex workflows using LangChain, and implement Retrieval-Augmented Generation (RAG) to query your own documents. By the end of this course, you will have the skills to build, test, and deploy a fully functional, custom AI web application.

Capstone Project

Domain-Specific AI Knowledge Assistant

  • Dynamic Document Processing: A sidebar interface allowing users to upload new PDF or TXT files, which the app automatically chunks, embeds, and stores in the vector database.
  • Context-Aware Chat UI: A modern chat interface built with Streamlit that maintains conversation history, allowing users to ask follow-up questions naturally.
  • Strict Guardrails (Anti-Hallucination): System instructions designed so the AI politely declines to answer questions that fall outside the context of the uploaded documents.
7 Weeks Beginner
Lihat Detail Course

Artikel Terkait