2012-05-23 14 views
15

क्या सजावटी को सशर्त रूप से कार्य करना संभव है। उदाहरण के लिए, मैं टाइमर फ़ंक्शन (timeit) के साथ फ़ंक्शन foo() को सजाना चाहता हूं केवल do_performance_analysis True (नीचे psuedo-code देखें)।पायथन 2.6 में एक सशर्त सजावट कैसे करें 2.6

if doing_performance_analysis: 
    @timeit 
    def foo(): 
    """ 
    do something, timeit function will return the time it takes 
    """ 
    time.sleep(2) 
else: 
    def foo(): 
    time.sleep(2) 

उत्तर

20

डेकोरेटर बस callables कि एक प्रतिस्थापन, वैकल्पिक रूप से एक ही समारोह, एक आवरण है, या कुछ पूरी तरह से अलग लौट आते हैं।

class conditional_decorator(object): 
    def __init__(self, dec, condition): 
     self.decorator = dec 
     self.condition = condition 

    def __call__(self, func): 
     if not self.condition: 
      # Return the function unchanged, not decorated. 
      return func 
     return self.decorator(func) 

अब आप इसे इस तरह उपयोग कर सकते हैं: इस तरह के रूप में, आप एक सशर्त डेकोरेटर बना सकते हैं

@conditional_decorator(timeit, doing_performance_analysis) 
def foo(): 
    time.sleep(2) 
+0

धन्यवाद! टिप्पणी अनुभाग प्रारूपित नहीं है, इसलिए मैंने आपके मूल उत्तर में नमूना कोड जोड़ा। क्या आप समझा सकते हैं कि टाइम फ़ंक्शन क्यों नहीं कहा जाता है? – cfpete

+0

सजावटी आयात समय पर लागू होता है, इसलिए उस समय आवृत्ति चर से परामर्श नहीं किया जा रहा है। इसके लिए आपको एक अलग सजावट लिखनी होगी, जो स्वयं को बुलाए जाने पर स्वयं का निरीक्षण करता है। इस क्यू और टिप्पणी प्रारूप के लिए दायरे से बाहर। :-) –

+0

यदि मैं क्लास आधारित विधियों, यानी Django क्लास आधारित विचारों पर इसका उपयोग करना चाहता हूं तो मैं इसका उपयोग कैसे करूं। वहां पर हमें 'method_decorator' का उपयोग करना होगा। इस कोड को इसके साथ संगत कैसे बनाएं? – PythonEnthusiast

4

कैसे के बारे में:

def foo(): 
    ... 

if doing_performance_analysis: 
    foo = timeit(foo) 

मैं कल्पना आप भी एक डेकोरेटर कि एक बूलियन ध्वज और एक अन्य डेकोरेटर ले जाएगा में इस लपेट सकता है, और केवल बाद लागू होगा झंडा True पर सेट है :

def cond_decorator(flag, dec): 
    def decorate(fn): 
     return dec(fn) if flag else fn 
    return decorate 

@cond_decorator(doing_performance_analysis, timeit) 
def foo(): 
    ... 
9

एक सजावट बस एक अन्य समारोह पर लागू एक समारोह है। आप इसे मैन्युअल रूप से लागू कर सकते हैं:

def foo(): 
    # whatever 
    time.sleep(2) 

if doing_performance_analysis: 
    foo = timeit(foo) 
0

Blckknght के जवाब महान अगर आप हर बार जब आप फ़ंक्शन को कॉल की जांच करना चाहते हैं, लेकिन अगर आपके पास एक सेटिंग है जिसे आप एक बार पढ़ सकते हैं और कभी नहीं बदल सकते हैं तो आप सजाए गए फ़ंक्शन को हर बार सेटिंग की जांच नहीं करना चाहेंगे। काम पर हमारे कुछ उच्च प्रदर्शन डिमन्स में मैंने एक सजावट लिखा है जो एक बार एक फाइल को जांचता है जब पाइथन फ़ाइल पहली बार लोड होती है और निर्णय लेती है कि उसे लपेटना चाहिए या नहीं।

यहां नमूने

def timed(f): 
    def wrapper(*args, **kwargs): 
     start = datetime.datetime.utcnow() 
     return_value = f(*args, **kwargs) 
     end = datetime.datetime.utcnow() 
     duration = end - start 

     log_function_call(module=f.__module__, function=f.__name__, start=__start__, end=__end__, duration=duration.total_seconds()) 
    if config.get('RUN_TIMED_FUNCTIONS'): 
     return wrapper 
    return f 

कि log_function_call मान लिया जाये कि एक डेटाबेस, लॉगफ़ाइल, या जो कुछ भी और उस config.get करने के लिए अपने कॉल लॉग है ('RUN_TIMED_FUNCTIONS') अपने वैश्विक विन्यास की जाँच करता है, तो @timed डेकोरेटर जोड़ने एक फ़ंक्शन में यह देखने के लिए लोड पर एक बार जांच होगी कि क्या आप इस सर्वर, पर्यावरण इत्यादि पर समय दे रहे हैं और यदि नहीं, तो यह उत्पादन या अन्य वातावरण पर फ़ंक्शन के निष्पादन को नहीं बदलेगा जहां आप प्रदर्शन की परवाह करते हैं।

0
use_decorator = False 

class myDecorator(object): 
    def __init__(self, f): 
      self.f = f 

    def __call__(self): 
      print "Decorated running..." 
      print "Entering", self.f.__name__ 
      self.f() 
      print "Exited", self.f.__name__ 


def null(a): 
    return a 


if use_decorator == False : 
    myDecorator = null 


@myDecorator 
def CoreFunction(): 
    print "Core Function running" 

CoreFunction() 
संबंधित मुद्दे