🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Python functools Complete Guide 2026: lru_cache, আংশিক এবং হ্রাস

⏱️4 min read  ·  774 words

Python এর functools মডিউল হল সবচেয়ে কম ব্যবহৃত কিন্তু শক্তিশালী স্ট্যান্ডার্ড লাইব্রেরি মডিউলগুলির মধ্যে একটি। 2026 সালে, ফাংক্টুলগুলি উচ্চ-ক্রম ফাংশন, মেমোাইজেশন, আংশিক প্রয়োগ এবং ফাংশন রচনার জন্য সরঞ্জাম সরবরাহ করে যা বয়লারপ্লেট দূর করে এবং কোডকে আরও অভিব্যক্তিপূর্ণ করে। এই সম্পূর্ণ নির্দেশিকা ব্যবহারিক উদাহরণ সহ প্রতিটি ফাংশন ফাংশন কভার করে।

functools.lru_cache এবং ক্যাশে

from functools import lru_cache, cache
import time

# Simple memoization — cache indefinitely
@cache  # Python 3.9+, same as lru_cache(maxsize=None)
def fibonacci(n: int) -> int:
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# LRU cache — keep only most recent N results
@lru_cache(maxsize=128)
def expensive_api_call(user_id: int) -> dict:
    time.sleep(0.5)  # simulate slow API
    return {"id": user_id, "name": "User"}

# Cache info and management
print(fibonacci.cache_info())  # CacheInfo(hits=X, misses=Y, maxsize=None, currsize=N)
fibonacci.cache_clear()

# Method-level cache (instance-level, not shared across instances)
class DataService:
    @lru_cache(maxsize=256)
    def get_user(self, user_id: int) -> dict:
        return fetch_from_db(user_id)

functools.partial — আংশিক অ্যাপ্লিকেশন

from functools import partial
import operator

# Create a new function with some args pre-filled
def power(base: float, exponent: float) -> float:
    return base ** exponent

square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5))  # 25.0
print(cube(3))    # 27.0

# Useful with map/filter
double = partial(operator.mul, 2)
numbers = [1, 2, 3, 4, 5]
doubled = list(map(double, numbers))  # [2, 4, 6, 8, 10]

# Partial with keyword args
import requests
get_from_api = partial(requests.get, headers={"Authorization": "Bearer token123"})
response = get_from_api("https://api.example.com/users")

# In configuration/dependency injection
from functools import partial

def create_user(db, email: str, role: str = "user") -> dict:
    return db.insert("users", {"email": email, "role": role})

create_admin = partial(create_user, db=prod_db, role="admin")
admin = create_admin("admin@example.com")

functools.reduce

from functools import reduce
import operator

# Sum a list (use sum() instead in practice)
total = reduce(operator.add, [1, 2, 3, 4, 5])  # 15

# Product of list (no built-in)
product = reduce(operator.mul, [1, 2, 3, 4, 5])  # 120

# Flatten nested list
nested = [[1, 2], [3, 4], [5, 6]]
flat = reduce(operator.add, nested)  # [1, 2, 3, 4, 5, 6]

# Compose functions (right to left)
def compose(*functions):
    return reduce(lambda f, g: lambda x: f(g(x)), functions)

pipeline = compose(str.upper, str.strip, str.lower)
print(pipeline("  Hello World  "))  # "HELLO WORLD"

# Deep dictionary merge
dicts = [{"a": 1}, {"b": 2, "c": 3}, {"d": 4}]
merged = reduce(lambda acc, d: {**acc, **d}, dicts)  # {"a":1,"b":2,"c":3,"d":4}

functools.wraps

from functools import wraps
import time, logging

logger = logging.getLogger(__name__)

def log_calls(func):
    @wraps(func)  # preserves __name__, __doc__, __wrapped__, __annotations__
    def wrapper(*args, **kwargs):
        logger.info(f"Calling {func.__name__}")
        result = func(*args, **kwargs)
        logger.info(f"Done {func.__name__}")
        return result
    return wrapper

def measure(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__}: {elapsed*1000:.2f}ms")
        return result
    return wrapper

@log_calls
@measure
def process_data(data: list) -> list:
    return sorted(data)

# Without @wraps, process_data.__name__ would be "wrapper"
print(process_data.__name__)  # "process_data" (correct!)

functools.total_ordering

from functools import total_ordering

@total_ordering  # generates __le__, __lt__, __ge__, __gt__ from __eq__ and one comparison
class Version:
    def __init__(self, major: int, minor: int, patch: int = 0):
        self.major = major
        self.minor = minor
        self.patch = patch

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Version):
            return NotImplemented
        return (self.major, self.minor, self.patch) == (other.major, other.minor, other.patch)

    def __lt__(self, other: "Version") -> bool:
        return (self.major, self.minor, self.patch) < (other.major, other.minor, other.patch)

    def __repr__(self) -> str:
        return f"Version({self.major}.{self.minor}.{self.patch})"

versions = [Version(2, 0), Version(1, 9, 5), Version(3, 0), Version(1, 9, 4)]
print(sorted(versions))  # [1.9.4, 1.9.5, 2.0, 3.0]
print(Version(1, 9) < Version(2, 0))  # True
print(Version(3, 0) >= Version(2, 1))  # True (generated!)

functools.singledispatch — পদ্ধতি ওভারলোডিং

from functools import singledispatch

@singledispatch
def process(obj):
    raise TypeError(f"Cannot process {type(obj)}")

@process.register(int)
def _(obj: int) -> str:
    return f"Integer: {obj}"

@process.register(str)
def _(obj: str) -> str:
    return f"String: '{obj}'"

@process.register(list)
def _(obj: list) -> str:
    return f"List with {len(obj)} items"

@process.register(dict)
def _(obj: dict) -> str:
    return f"Dict with {len(obj)} keys: {list(obj.keys())}"

print(process(42))           # "Integer: 42"
print(process("hello"))      # "String: 'hello'"
print(process([1, 2, 3]))    # "List with 3 items"

# Useful for serialization/display of varied types without isinstance chains

functools.cached_property

from functools import cached_property
import statistics

class Dataset:
    def __init__(self, data: list[float]):
        self._data = data

    @cached_property
    def mean(self) -> float:
        print("Computing mean...")
        return statistics.mean(self._data)

    @cached_property
    def stdev(self) -> float:
        print("Computing stdev...")
        return statistics.stdev(self._data)

    @cached_property
    def sorted_data(self) -> list[float]:
        print("Sorting...")
        return sorted(self._data)

ds = Dataset([3, 1, 4, 1, 5, 9, 2, 6])
print(ds.mean)       # "Computing mean..." then value
print(ds.mean)       # value directly (cached)
print(ds.stdev)      # "Computing stdev..." then value

পরিষ্কার, দক্ষ কোডের জন্য 2026 সালে Python functools অপরিহার্য। মেমোাইজেশনের জন্য @cache ব্যবহার করুন, কনফিগারেশন ইনজেকশনের জন্য আংশিক(), ডেকোরেটর ট্রান্সপারেন্সির জন্য @wraps, তুলনা ক্লাসের জন্য @total_ordering, টাইপ-ভিত্তিক প্রেরণের জন্য @singledispatch এবং অলস কম্পিউটেড অ্যাট্রিবিউটের জন্য ক্যাশেড_প্রপার্টি ব্যবহার করুন। এই সরঞ্জামগুলি বয়লারপ্লেট প্রতিস্থাপন করে এবং অভিপ্রায় স্পষ্ট করে।

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা