Modern Python 3.12+ చాప్టర్ 24 / 25 Phase 05: OOP & Advanced 2026 Edition

24. అడ్వాన్స్‌డ్ పైథాన్ — డెకరేటర్లు, జెనరేటర్లు & డండర్ మెథడ్స్

📌 Covered in this chapter: Closures & Metaprogramming • Function Decorators & functools.wraps • Decorators with Arguments • Generators, yield & Lazy Evaluation • yield from Sub-generators • Python Data Model & Dunder Methods • Context Managers (__enter__/__exit__) • Streaming Log Pipeline Capstone
పైథాన్‌ను ప్రపంచంలోనే అత్యంత శక్తివంతమైన మరియు సుందరమైన భాషగా మార్చిన రహస్యం దాని "అడ్వాన్స్‌డ్ మెటాప్రోగ్రామింగ్" ఫీచర్లు. సాధారణ డెవలపర్‌కు మరియు సీనియర్ పైథాన్ ఆర్కిటెక్ట్‌కు మధ్య వ్యత్యాసాన్ని చూపేవి సరిగ్గా ఈ అంశాలే: ఫంక్షన్ల ప్రవర్తనను మార్చకుండా అదనపు ఫీచర్లను చేర్చే డెకరేటర్లు (Decorators), గిగాబైట్ల కొద్దీ డేటాను కొన్ని మెగాబైట్ల ర్యామ్‌తోనే ప్రాసెస్ చేయగల జెనరేటర్లు & లేజీ ఎవాల్యుయేషన్ (Generators & yield), మరియు పైథాన్ భాషలోని బిల్ట్-ఇన్ ఆపరేటర్లను మన క్లాసులకు అనుసంధానించే మ్యాజిక్ లేదా డండర్ మెథడ్స్ (Python Data Model). ఈ అధ్యాయంలో ఈ మూడు మాస్టర్ టూల్స్‌ను లోతైన అంతర్గత రన్‌టైమ్ మెకానిక్స్ మరియు లైవ్ ప్రొడక్షన్ ప్రాజెక్ట్‌తో వివరంగా నేర్చుకుందాం.

1 ఫస్ట్-క్లాస్ ఫంక్షన్స్ (First-Class Functions) & క్లోజర్స్ (Closures)

పైథాన్‌లో డెకరేటర్లను అర్థం చేసుకోవాలంటే, మొదట ఫంక్షన్లను పైథాన్ ఎలా చూస్తుందో అర్థం చేసుకోవాలి. పైథాన్‌లో ఫంక్షన్లు First-Class Citizens:

క్లోజర్ (Closure) మెకానిక్స్ & Free Variables:

ఒక ఔటర్ ఫంక్షన్ ఎగ్జిక్యూషన్ ముగిసిపోయి, దాని లోకల్ స్కోప్ మెమరీ నుండి తుడిచిపెట్టుకుపోయిన తర్వాత కూడా — దాని లోపల ఉన్న ఇన్నర్ ఫంక్షన్ ఆ ఔటర్ స్కోప్ యొక్క వేరియబుల్స్‌ను (Free Variables) గుర్తుంచుకునే అద్భుతమైన సామర్థ్యాన్ని క్లోజర్ అంటారు.

పైథాన్ అంతర్గతంగా ప్రతి ఇన్నర్ ఫంక్షన్ ఆబ్జెక్ట్‌కు __closure__ అనే ట్యూపుల్‌ను జతచేస్తుంది. ఇందులో సెల్ ఆబ్జెక్టుల (Cell Objects) రూపంలో ఔటర్ వేరియబుల్స్ భద్రంగా నిల్వ ఉంటాయి. డెకరేటర్లు పనిచేయడానికి సరిగ్గా ఈ క్లోజర్ మెకానిజమే అత్యంత కీలకమైన పునాది!

2 ఫంక్షన్ డెకరేటర్ల నిర్మాణం (Decorators Anatomy & @ Syntax)

ఒక ఫంక్షన్ యొక్క అసలు సోర్స్ కోడ్‌ను ఎటువంటి మార్పు చేయకుండా, దాని ముందు లేదా వెనుక అదనపు ఫంక్షనాలిటీని (ఉదా: Logging, Timing, Authentication) చేర్చే హైయర్-ఆర్డర్ ఫంక్షన్‌ను డెకరేటర్ (Decorator) అంటారు:

@ సింటాక్స్ వెనుక అసలు నిజం (Syntactic Sugar):
మీరు ఒక ఫంక్షన్ పైన @my_decorator అని రాసినప్పుడు, పైథాన్ ఇంటర్‌ప్రీటర్ కోడ్ లోడ్ అయ్యే సమయంలోనే ఆటోమేటిక్‌గా original_func = my_decorator(original_func) గా రీరైట్ చేస్తుంది! అంటే డెకరేటర్ అనేది అసలు ఫంక్షన్‌ను ఇన్‌పుట్‌గా తీసుకుని, అదనపు రక్షణ లేదా లాజిక్ జోడించిన ఒక కొత్త "ర్యాపర్ ఫంక్షన్" ను రిటర్న్ చేస్తుంది.

3 functools.wraps ప్రాముఖ్యత (Metadata Preservation)

ఒక ఫంక్షన్‌ను ర్యాప్ చేసినప్పుడు, దాని పేరు (__name__) మరియు డాక్యుమెంటేషన్ (__doc__) ర్యాపర్ ఫంక్షన్ పేరుతో రీప్లేస్ అయిపోతాయి. దీనివల్ల డీబగ్గింగ్, డాక్యుమెంటేషన్ జనరేటర్లు (Sphinx), మరియు వెబ్ ఫ్రేమ్‌వర్కులు (Flask/FastAPI) తీవ్రంగా గందరగోళానికి గురవుతాయి:

4 పారామీటర్లతో కూడిన డెకరేటర్లు & క్లాస్ బేస్డ్ డెకరేటర్లు (__call__)

డెకరేటర్‌కు ఆర్గ్యుమెంట్లను పాస్ చేయాలంటే (ఉదా: @repeat(num_times=3) లేదా @role_required("ADMIN")), మనం 3 స్థాయిల నెస్టెడ్ ఫంక్షన్లను (Triple-nested functions: Decorator Factory ➔ Decorator ➔ Wrapper) ఉపయోగించాలి:

క్లాస్ బేస్డ్ డెకరేటర్లు (Stateful Decorators) & Enterprise Patterns:

డెకరేటర్‌ను ఫంక్షన్‌గా మాత్రమే కాకుండా ఒక పూర్తి క్లాస్‌గా కూడా రూపొందించవచ్చు. ఒక క్లాస్ ఆబ్జెక్ట్‌ను ఫంక్షన్ లాగా కాల్ చేయడానికి (Callable Object) పైథాన్‌లో __call__ డండర్ మెథడ్‌ను వాడుతాము.

ఒక ఫంక్షన్ ఎన్నిసార్లు పిలవబడిందో లెక్కించడానికి (Call Counter), లేదా ఫలితాలను క్యాష్ చేయడానికి (Memoization) క్లాస్ అట్రిబ్యూట్లు చాలా శక్తివంతమైన సాధనాలు. __init__ లో అసలు ఫంక్షన్‌ను దాచిపెట్టి, __call__ లో ప్రతి కాల్‌ను ట్రాక్ చేస్తాము.

రియల్-వరల్డ్ వెబ్ డెవలప్‌మెంట్‌లో పాపులర్ డెకరేటర్ల సూట్:
  • @login_required (Authentication): వెబ్ అభ్యర్థనను యూజర్ పంపినప్పుడు సెషన్ టోకెన్ లేదా కుకీని చెక్ చేసి, యూజర్ లాగిన్ అయి ఉంటేనే అసలు వ్యూ ఫంక్షన్‌ను పిలవడం.
  • @rate_limit(requests=60, window_sec=60) (API Throttling): ఒక ఐపీ అడ్రస్ నుండి నిమిషానికి 60 రిక్వెస్టుల కంటే ఎక్కువ వస్తే 429 Too Many Requests తో బ్లాక్ చేయడం.
  • @cache_response(ttl_seconds=300) (Caching): పదే పదే మారే అవకాశం లేని డేటాబేస్ ఫలితాలను Redis లో క్యాష్ చేసి రెస్పాన్స్ సమయాన్ని 200ms నుండి 2ms కి తగ్గించడం!

5 ఇటరేటర్ ప్రోటోకాల్ (The Python Iterator Protocol)

పైథాన్‌లో for item in collection: లూప్ తెరవెనుక ఎలా పనిచేస్తుంది? దీని వెనుక పైథాన్ యొక్క అధికారిక Iterator Protocol ఉంది:

6 జెనరేటర్లు (Generators) & yield స్టేట్‌మెంట్ — Lazy Evaluation

జెనరేటర్లు సాధారణ ఫంక్షన్ల లాంటివే, కానీ అవి విలువను return చేసి చనిపోవు; బదులుగా yield స్టేట్‌మెంట్ ద్వారా విలువను అందించి, తమ ఎగ్జిక్యూషన్ స్టేట్‌ను (Local Variables, Instruction Pointer) స్తంభింపజేస్తాయి (Pause). మళ్లీ next() పిలిచినప్పుడు సరిగ్గా ఎక్కడైతే ఆగిపోయాయో అక్కడి నుంచే తమ పనిని కొనసాగిస్తాయి:

ఫీచర్ సాధారణ లిస్ట్ (Eager Evaluation) జెనరేటర్ (Lazy Evaluation)
మెమరీ వినియోగం (1 కోటి సంఖ్యలకు) ~800 MegaBytes (భారీగా RAM ఆక్రమిస్తుంది) కేవలం 104 Bytes మాత్రమే! (ఒక్కొక్కటిగా ఉత్పత్తి అవుతుంది)
ప్రారంభ వేగం మొత్తం లిస్ట్ తయారయ్యే వరకు వేచి ఉండాలి (High Latency). తక్షణమే మొదటి ఫలితం లభిస్తుంది (Zero Startup Latency).
డేటా పరిమాణ పరిమితి సిస్టమ్ RAM సైజుకు పరిమితం (RAM అయిపోతే క్రాష్). అనంతమైన డేటా స్ట్రీమ్‌లు (Infinite Streams) ను కూడా నిరంతరం ప్రాసెస్ చేయగలదు.
🔬 అండర్ ది హుడ్: పైథాన్ రన్‌టైమ్‌లో జెనరేటర్ ఫ్రేమ్ సస్పెన్షన్:
సాధారణ ఫంక్షన్ రన్ అయినప్పుడు దాని స్టాక్ ఫ్రేమ్ (Stack Frame) క్రియేట్ అవుతుంది, మరియు return కాగానే ఆ ఫ్రేమ్ మెమరీ నుండి నాశనమవుతుంది. కానీ ఒక ఫంక్షన్‌లో yield ఉన్నప్పుడు, పైథాన్ కంపైలర్ దానిని PyGenObject గా గుర్తిస్తుంది.
yield స్టేట్‌మెంట్ వచ్చినప్పుడు, పైథాన్ ఆ ఫంక్షన్ యొక్క లోకల్ వేరియబుల్స్ మరియు బైట్‌కోడ్ ఇన్‌స్ట్రక్షన్ పాయింటర్ (f_lasti) ను హీప్ (Heap) మెమరీలోనే స్తంభింపజేసి భద్రపరుస్తుంది. కాలర్ మళ్లీ next() పిలిచినప్పుడు, ఖచ్చితంగా ఆగిపోయిన f_lasti అడ్రస్ నుండే ఎగ్జిక్యూషన్ పునఃప్రారంభమవుతుంది! ఈ ఆర్కిటెక్చరే ఆధునిక అసెంక్రోనస్ ప్రోగ్రామింగ్ (Async/Await) కు మూలస్తంభం.

7 yield from & బై-డైరెక్షనల్ జెనరేటర్లు (send() Coroutines)

పైథాన్ 3.3 లో ప్రవేశపెట్టబడిన yield from నెస్టెడ్ జెనరేటర్లను మరియు ఇటరబుల్స్‌ను డీలిగేట్ చేయడానికి అత్యంత సులభతరమైన సింటాక్స్. ఇది లోపలి సబ్-జెనరేటర్ నుండి వచ్చే అన్ని విలువలను నేరుగా కాలర్‌కు పాస్ చేస్తుంది.

బై-డైరెక్షనల్ కమ్యూనికేషన్: generator.send(value)

జెనరేటర్లు కేవలం బయటకు డేటాను పంపడం (Produce) మాత్రమే కాదు; బయటి కాలర్ నుండి డేటాను లోపలికి స్వీకరించగలవు కూడా! val = yield output అని రాసినప్పుడు, కాలర్ gen.send(new_val) ద్వారా జెనరేటర్‌లోకి కొత్త డేటాను ఇంజెక్ట్ చేయవచ్చు. ఆధునిక పైథాన్‌లో asyncio మరియు కోరూటీన్లు (Coroutines) అభివృద్ధి చెందడానికి సరిగ్గా ఈ yield మరియు send() ప్రోటోకాలే మాతృకగా నిలిచింది!

8 పైథాన్ డేటా మోడల్ & మ్యాజిక్ / డండర్ మెథడ్స్ (Python Data Model)

పైథాన్‌లో క్లాసులు సాధారణ యూజర్-డిఫైన్డ్ టైప్స్ లాగా మాత్రమే కాకుండా, పైథాన్ యొక్క కోర్ సింటాక్స్‌తో సహజంగా అనుసంధానం కావడానికి Dunder (Double Underscore) మెథడ్స్ తోడ్పడతాయి:

ఆపరేషన్ / సింటాక్స్ అంతర్గతంగా పిలవబడే డండర్ మెథడ్ వివరణ & ఉపయోగం
str(obj) / print(obj) __str__(self) యూజర్లకు చదవడానికి అనువైన అందమైన టెక్స్ట్ రిప్రజెంటేషన్.
repr(obj) / Debugger __repr__(self) డెవలపర్లకు డీబగ్గింగ్ కోసం ఖచ్చితమైన సాంకేతిక సమాచారం.
len(obj) __len__(self) కస్టమ్ కంటైనర్ల పొడవును లెక్కించడం.
obj1 + obj2 __add__(self, other) కూడిక ఆపరేటర్ ఓవర్‌లోడింగ్.
obj1 == obj2 __eq__(self, other) సమానత్వ పోలిక ఆపరేటర్ ఓవర్‌లోడింగ్.
with obj: __enter__(self), __exit__(self) కాంటెక్స్ట్ మేనేజర్ రిసోర్స్ అలోకేషన్ & సేఫ్ క్లీనప్.

9 కోడ్ డెమో 1: ఆపరేటర్ ఓవర్‌లోడింగ్ with Currency & Dunder Suite

పైథాన్ ఆపరేటర్లను (+, *, ==, <) మన యూజర్-డిఫైన్డ్ ఆబ్జెక్టులపై పనిచేసేలా ఓవర్‌లోడ్ చేసే పూర్తి కోడ్ ఉదాహరణను పరిశీలిద్దాం:

01_money_operator_overloading.py
# ఆపరేటర్ ఓవర్‌లోడింగ్ మరియు పైథాన్ డేటా మోడల్
class Money:
    def __init__(self, amount: float, currency: str = "INR"):
        self.amount = round(float(amount), 2)
        self.currency = currency

    # 1. యూజర్ ఫ్రెండ్లీ స్ట్రింగ్
    def __str__(self):
        symbol = "₹" if self.currency == "INR" else self.currency
        return f"{symbol}{self.amount:,.2f}"

    # 2. డెవలపర్ డీబగ్గింగ్ రిప్రజెంటేషన్
    def __repr__(self):
        return f"Money(amount={self.amount}, currency='{self.currency}')"

    # 3. కూడిక ఆపరేటర్ (+) ఓవర్‌లోడింగ్
    def __add__(self, other):
        if not isinstance(other, Money) or self.currency != other.currency:
            raise TypeError("విభిన్న కరెన్సీలను లేదా నాన్-మనీ ఆబ్జెక్టులను కూడలేము!")
        return Money(self.amount + other.amount, self.currency)

    # 4. గుణకారం ఆపరేటర్ (*) ఓవర్‌లోడింగ్ (స్కేలార్ నంబర్‌తో)
    def __mul__(self, factor: float):
        return Money(self.amount * factor, self.currency)

    # 5. సమానత్వ ఆపరేటర్ (==)
    def __eq__(self, other):
        return isinstance(other, Money) and self.amount == other.amount and self.currency == other.currency

    # 6. తక్కువ/ఎక్కువ ఆపరేటర్ (<) సార్టింగ్ కోసం
    def __lt__(self, other):
        if not isinstance(other, Money) or self.currency != other.currency:
            raise TypeError("పోలిక ఒకే కరెన్సీ మధ్య మాత్రమే సాధ్యం!")
        return self.amount < other.amount

# టెస్టింగ్
m1 = Money(1500, "INR")
m2 = Money(3250.50, "INR")
m3 = m1 + m2
print("m1:", m1)                  # __str__ -> ₹1,500.00
print("repr(m1):", repr(m1))      # __repr__ -> Money(amount=1500.0, currency='INR')
print("మొత్తం (m1 + m2):", m3)    # ₹4,750.50
print("GST తో (m1 * 1.18):", m1 * 1.18)
print("సార్టింగ్ ఫలితం:", sorted([m2, m1]))

10 కాంటెక్స్ట్ మేనేజర్స్ (Context Managers): __enter__ & contextlib

రిసోర్స్ మేనేజ్‌మెంట్ కోసం (ఫైళ్లు మూసివేయడం, నెట్‌వర్క్ సాకెట్ క్లోజ్ చేయడం, డేటాబేస్ లావాదేవీలను కమిట్/రోల్‌బ్యాక్ చేయడం) with స్టేట్‌మెంట్‌ను ఉపయోగిస్తాము:

11 కోడ్ డెమో 2: ప్రొడక్షన్ లెవల్ డెకరేటర్లు (@retry & @audit)

నెట్‌వర్క్ కాల్స్ విఫలమైనప్పుడు ఆటోమేటిక్‌గా 3 సార్లు రీట్రై చేసే మరియు ఆడిట్ లాగ్ చేసే ప్రొడక్షన్-గ్రేడ్ డెకరేటర్‌ను చూద్దాం:

02_production_retry_decorator.py
import functools
import time

def retry_operation(max_attempts=3, delay_sec=1.0):
    """విఫలమైన ఫంక్షన్లను ఆటోమేటిక్‌గా రీట్రై చేసే డెకరేటర్."""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            attempts = 0
            while attempts < max_attempts:
                try:
                    attempts += 1
                    return func(*args, **kwargs)
                except Exception as err:
                    print(f"⚠️ [ప్రయత్నం {attempts}/{max_attempts}] విఫలమైంది: {err}")
                    if attempts >= max_attempts:
                        print("❌ గరిష్ట రీట్రై పరిమితి ముగిసింది! ఎర్రర్ విసురుతున్నాము.")
                        raise
                    time.sleep(delay_sec)
        return wrapper
    return decorator

# సిమ్యులేషన్: 2 సార్లు ఫెయిల్ అయి 3వ సారి సక్సెస్ అయ్యే API కాల్
call_count = 0

@retry_operation(max_attempts=3, delay_sec=0.5)
def fetch_payment_status(txn_id: str):
    global call_count
    call_count += 1
    if call_count < 3:
        raise ConnectionResetError("గేట్‌వే సర్వర్ స్పందించడం లేదు (504 Gateway Timeout)")
    return f"SUCCESS: లావాదేవీ {txn_id} విజయవంతంగా పూర్తయింది!"

print("📡 పేమెంట్ సర్వీస్ కాల్ మొదలైంది...")
result = fetch_payment_status("TXN-90218")
print("🎉 రిజల్ట్:", result)

12 కామన్ బిగినర్స్ మిస్టేక్స్ & ప్రొడక్షన్ బెస్ట్ ప్రాక్టీసెస్

13 రియల్-వరల్డ్ ప్రాజెక్ట్: "Gigabyte-Scale Streaming Server Log Audit Pipeline"

ఈ అధ్యాయంలో నేర్చుకున్న అన్ని అంశాలను (జెనరేటర్లు, yield from, కస్టమ్ డెకరేటర్లు, డండర్ మెథడ్స్‌తో కూడిన డేటా మోడల్, కాంటెక్స్ట్ మేనేజర్) సమగ్రంగా ఏకీకృతం చేస్తూ — భారీ గిగాబైట్ల సర్వర్ లాగ్ ఫైల్స్‌ను కేవలం కొన్ని కిలోబైట్ల మెమరీతోనే లైవ్ స్ట్రీమింగ్ చేస్తూ సెక్యూరిటీ బెదిరింపులను గుర్తించే పూర్తి స్థాయి Gigabyte-Scale Streaming Log Audit Pipeline ను నిర్మిద్దాం!

03_streaming_log_audit_pipeline.py
# =====================================================================
# చాప్టర్ 24 ప్రాజెక్ట్: Gigabyte-Scale Streaming Server Log Audit Pipeline
# కాన్సెప్ట్స్: Custom Context Manager, Generators, yield from,
#              Dunder Methods (__iter__, __len__, __repr__), @timer Decorator
# =====================================================================
import time
import functools

# 1. పెర్ఫార్మెన్స్ బెంచ్‌మార్క్ డెకరేటర్
def benchmark_pipeline(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        t0 = time.perf_counter()
        res = func(*args, **kwargs)
        t1 = time.perf_counter()
        print(f"
⚡ పైప్‌లైన్ ఆడిట్ పూర్తయిన సమయం: {(t1 - t0)*1000:.3f} ms")
        return res
    return wrapper

# 2. లాగ్ రికార్డ్ క్లాస్ (Python Data Model with Dunder Methods)
class LogRecord:
    def __init__(self, ip: str, method: str, path: str, status_code: int, response_ms: float):
        self.ip = ip
        self.method = method
        self.path = path
        self.status_code = status_code
        self.response_ms = response_ms

    def __repr__(self):
        return f"LogRecord({self.ip} | {self.method} {self.path} -> {self.status_code})"

    def is_security_threat(self) -> bool:
        # 401/403/500 ఎర్రర్లు లేదా అనుమానాస్పద పాత్‌లను గుర్తించడం
        suspicious_paths = ["/admin", "/wp-login.php", "/.env", "/config.json"]
        return self.status_code in (401, 403, 500) or any(sp in self.path for sp in suspicious_paths)

# 3. కాంటెక్స్ట్ మేనేజర్: సేఫ్ లాగ్ స్ట్రీమ్ సెషన్
class LogStreamAuditSession:
    def __init__(self, session_name: str):
        self.session_name = session_name

    def __enter__(self):
        print(f"🔒 [AUDIT SESSION: {self.session_name}] సెషన్ ప్రారంభమైంది. లాగ్ స్ట్రీమ్ లాక్ చేయబడింది.")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print(f"🚨 [AUDIT ALERT] సెషన్‌లో ఊహించని ఎర్రర్: {exc_val}")
        print(f"🔓 [AUDIT SESSION: {self.session_name}] సెషన్ సురక్షితంగా క్లోజ్ అయింది.
")
        return False

# 4. జెనరేటర్: భారీ లాగ్ ఫైల్ సిమ్యులేషన్ (మెమరీలో కేవలం 1 లైన్ మాత్రమే ఉంటుంది)
def generate_raw_server_logs():
    raw_sample_data = [
        "192.168.1.10 GET /api/v1/products 200 45.2",
        "10.0.0.5 POST /api/v1/checkout 200 320.1",
        "45.33.32.156 GET /admin 403 12.0",
        "185.220.101.5 GET /wp-login.php 404 8.5",
        "192.168.1.12 GET /api/v1/user/profile 200 65.4",
        "45.33.32.156 POST /api/v1/login 401 25.0",
        "10.0.0.8 GET /config.json 500 110.0",
        "192.168.1.15 GET /index.html 200 18.2"
    ]
    for line in raw_sample_data:
        yield line

# 5. జెనరేటర్ పైప్‌లైన్: రా స్ట్రింగ్‌ను LogRecord ఆబ్జెక్ట్‌గా మార్చడం (Lazy Parsing)
def parse_log_stream(raw_stream):
    for line in raw_stream:
        parts = line.strip().split()
        if len(parts) == 5:
            ip, method, path, status_code, resp_ms = parts
            yield LogRecord(ip, method, path, int(status_code), float(resp_ms))

# 6. జెనరేటర్ ఫిల్టర్: కేవలం సెక్యూరిటీ బెదిరింపులను మాత్రమే ఫిల్టర్ చేయడం
def filter_security_threats(record_stream):
    for record in record_stream:
        if record.is_security_threat():
            yield record

# 7. మొత్తం పైప్‌లైన్ ఎగ్జిక్యూషన్
@benchmark_pipeline
def run_security_audit():
    with LogStreamAuditSession("SOC_HYDERABAD_GATEWAY"):
        raw_stream = generate_raw_server_logs()
        parsed_stream = parse_log_stream(raw_stream)
        threat_stream = filter_security_threats(parsed_stream)

        print("🔍 గుర్తించబడిన భద్రతా బెదిరింపులు (Security Threat Events):")
        threat_count = 0
        for threat in threat_stream:
            threat_count += 1
            print(f"  [హెచ్చరిక #{threat_count}] {threat}")

        print(f"
📊 మొత్తం విశ్లేషించబడిన బెదిరింపుల సంఖ్య: {threat_count}")

# పైప్‌లైన్ రన్ చేద్దాం
run_security_audit()

? మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes)

1. ఫంక్షన్ డెకరేటర్లలో @functools.wraps(func) ఎందుకు తప్పనిసరిగా వాడాలి?
సమాధానం: డెకరేటర్ వాడినప్పుడు అసలు ఫంక్షన్ స్థానంలో ర్యాపర్ ఫంక్షన్ వస్తుంది. @functools.wraps వాడకపోతే అసలు ఫంక్షన్ యొక్క పేరు (__name__) మరియు డాక్యుమెంటేషన్ (__doc__) కోల్పోతాము. wraps ఆ మెటాడేటాను సురక్షితంగా కాపాడుతుంది.
2. return మరియు yield స్టేట్‌మెంట్ల మధ్య ముఖ్యమైన తేడా ఏమిటి?
సమాధానం: return ఫంక్షన్ నుండి విలువను ఇచ్చి ఆ ఫంక్షన్‌ను పూర్తిగా ముగించివేస్తుంది (Terminate). కానీ yield విలువను అందించి, ఫంక్షన్ యొక్క స్థితిని (State & Local variables) స్తంభింపజేస్తుంది (Pause). తర్వాత next() పిలిచినప్పుడు అక్కడి నుండే కొనసాగుతుంది.
3. భారీ డేటాసెట్ల కోసం లిస్టుల కంటే జెనరేటర్లు ఎందుకు సమర్థవంతమైనవి?
సమాధానం: లిస్ట్ మొత్తం డేటాను ఒకేసారి ర్యామ్ (RAM) లో నిల్వ చేస్తుంది (గిగాబైట్ల మెమరీ అవసరం). జెనరేటర్ లేజీ ఎవాల్యుయేషన్ (Lazy Evaluation) విధానంలో అడిగినప్పుడు ఒక్కో ఎలిమెంట్‌ను మాత్రమే ఉత్పత్తి చేస్తుంది; దీనివల్ల మెమరీ వినియోగం కొన్ని బైట్లలోనే ఉంటుంది.
4. __str__ మరియు __repr__ మధ్య తేడా ఏమిటి?
సమాధానం: __str__ సాధారణ వినియోగదారులకు చదవడానికి సులభంగా ఉండే ఫార్మాట్‌లో టెక్స్ట్‌ను అందిస్తుంది (User-friendly). __repr__ డెవలపర్లకు డీబగ్గింగ్ కోసం ఆబ్జెక్ట్ యొక్క ఖచ్చితమైన సాంకేతిక రూపాన్ని అందిస్తుంది (Unambiguous / Developer-focused).
5. కాంటెక్స్ట్ మేనేజర్‌లో __exit__ మెథడ్ False ను ఎందుకు రిటర్న్ చేస్తుంది?
సమాధానం: __exit__ లో False (లేదా None) రిటర్న్ చేస్తే, with బ్లాక్‌లో వచ్చిన ఏదైనా ఎక్సెప్షన్ అణచివేయబడకుండా (Not suppressed), బయటి ప్రోగ్రామ్‌కు ప్రయాణించి హ్యాండిల్ చేయబడుతుంది. ఒకవేళ True రిటర్న్ చేస్తే ఎక్సెప్షన్ పూర్తిగా అణచివేయబడుతుంది.
← మునుపటి అధ్యాయం: 23. OOP పిల్లర్స్ తర్వాతి అధ్యాయం: 25. గ్రాండ్ ఫినాలే క్యాప్‌స్టోన్ ప్రాజెక్ట్ →

ఈ Streaming Log Audit Engine ని లైవ్‌గా మన కంపైలర్‌లో రన్ చేయండి!

ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్‌లోనే Modern Python 3 కంపైలర్‌లో ఈ డెకరేటర్లు మరియు జెనరేటర్ల కోడ్‌ను ఎగ్జిక్యూట్ చేసి అవుట్‌పుట్ తనిఖీ చేయండి.