2009-05-20 30 views
6

मैं अजगर कार्यों मैं कोड के प्रदर्शन को मापने के लिए सक्षम होने की तरह है, इसलिए बहुत बार मैं इस के समान कुछ करना ...समारोह डेकोरेटर

import time 

def some_function(arg1, arg2, ..., argN, verbose = True) : 
    t = time.clock() # works best in Windows 
    # t = time.time() # apparently works better in Linux 

    # Function code goes here 

    t = time.clock() - t 
    if verbose : 
     print "some_function executed in",t,"sec." 

    return return_val 

हाँ, मुझे पता है तुम timeit साथ प्रदर्शन को मापने के अपेक्षा की जाती है , लेकिन यह मेरी ज़रूरतों के लिए ठीक काम करता है, और मुझे इस जानकारी को बहुत आसानी से डिबगिंग के लिए चालू और बंद करने की अनुमति देता है।

ज़ाहिर है कि कोड इससे पहले कि मैं समारोह सज्जाकार बारे में पता था से था ... मैं अब उनके बारे में ज्यादा पता है, लेकिन मुझे लगता है कि मैं एक डेकोरेटर कि निम्नलिखित किया लिखने ** kwds शब्दकोश का उपयोग कर सकता है ऐसा नहीं है कि:

some_function(arg1, arg2, ..., argN) # Does not time function 
some_function(arg1, arg2, ..., argN, verbose = True) # Times function 

मैं फिर भी, मेरे कार्यों की पूर्व काम कर नकल करने ताकि काम कर रहे कुछ अधिक की तरह होगा चाहते हैं:

some_function(arg1, arg2, ..., argN) # Does not time function 
some_function(arg1, arg2, ..., argN, False) # Does not time function 
some_function(arg1, arg2, ..., argN, True) # Times function 

मुझे लगता है कि इस तर्क की संख्या गिनने के लिए डेकोरेटर की आवश्यकता होगी, पता मूल कार्य कितना लेगा, स्ट्राइक पी अतिरिक्त में, कार्य करने के लिए उनमें से सही संख्या पास करें ... मैं अनिश्चित हूं हालांकि यह करने के लिए पाइथन को कैसे बताना है ... क्या यह संभव है? क्या इसे हासिल करने का एक बेहतर तरीका है?

उत्तर

9

हालांकि inspect आप रास्ते पर एक सा मिल सकता है, आप क्या चाहते हैं सामान्य रूप में नहीं संभव है:

def f(*args): 
    pass 

f अब कितने तर्क ले करता है? चूंकि *args और **kwargs तर्कों की मनमानी संख्या की अनुमति देते हैं, इसलिए किसी फ़ंक्शन की आवश्यक तर्कों की संख्या निर्धारित करने का कोई तरीका नहीं है। असल में ऐसे मामले हैं जहां समारोह वास्तव में बहुत से हैंडल करता है!


संपादित करें: यदि आप एक विशेष कीवर्ड तर्क के रूप में verbose साथ प्रस्तुत करने को तैयार हैं, तो आप ऐसा कर सकते हैं:

import time 

def timed(f): 
    def dec(*args, **kwargs): 
     verbose = kwargs.pop('verbose', False) 
     t = time.clock() 

     ret = f(*args, **kwargs) 

     if verbose: 
      print("%s executed in %ds" % (f.__name__, time.clock() - t)) 

     return ret 

    return dec 

@timed 
def add(a, b): 
    return a + b 

print(add(2, 2, verbose=True)) 

(! kwargs.pop टिप के लिए धन्यवाद Alex Martelli)

+0

लेकिन क्या "some_function (ARG1, ARG2, ..., argN, यह सच है)" भी चलाना चाहिए है? –

+0

ठीक है, इसके लिए एक और प्रकार की सजावट की आवश्यकता होगी। वह जो निरीक्षण का उपयोग करता है या एक अतिरिक्त संख्यात्मक मान लेता है जो सजाए गए फ़ंक्शन को निर्धारित तर्कों की निश्चित संख्या दर्शाता है। – Stephan202

+0

मेरे लिए स्टीफन लिखने के लिए धन्यवाद! मैं काम से घर के रास्ते पर इस बारे में सोच रहा था, और मैं इस निष्कर्ष पर आया हूं कि इसके लिए कीवर्ड तर्क का उपयोग करना एक बेहतर तरीका है, क्योंकि इससे मुझे अन्य पैरामीटर शामिल करने की अनुमति मिल जाएगी, जैसे फ़ंक्शन कितनी बार , और क्या प्रिंटआउट औसत समय, न्यूनतम समय, या अधिक विस्तृत आंकड़े प्रतिबिंबित करना चाहिए ... – Jaime

8

स्टीफन 202 के उत्तर पर +1, हालांकि (इसे अलग जवाब में डालने के बाद से टिप्पणियां कोड को प्रारूपित नहीं करती हैं!), उस उत्तर में कोड का निम्नलिखित बिट:

verbose = False 
if 'verbose' in kwargs: 
    verbose = True 
    del kwargs['verbose'] 

व्यक्त किया जा सकता है और अधिक स्पष्ट रूप से और संक्षेप के रूप में:

verbose = kwargs.pop('verbose', False) 
+0

+1। मुझे लगता है कि पहले कभी एक dict पर पॉप() इस्तेमाल नहीं किया। – Stephan202

0

यह मुश्किल हो सकता है, लेकिन आप इन पंक्तियों पर कुछ कर सकते हैं। नीचे दिया गया कोड किसी भी अतिरिक्त तर्क को हटाने की कोशिश करता है और उन्हें प्रिंट करता है।

def mydeco(func): 
    def wrap(*args, **kwargs): 
     """ 
     we want to eat any extra argument, so just count args and kwargs 
     and if more(>func.func_code.co_argcount) first take it out from kwargs 
     based on func.func_code.co_varnames, else last one from args 
     """ 
     extraArgs = [] 

     newKwargs = {} 
     for name, value in kwargs.iteritems(): 
      if name in func.func_code.co_varnames: 
       newKwargs[name] = value 
      else: 
       extraArgs.append(kwargs[name]) 

     diff = len(args) + len(newKwargs) - func.func_code.co_argcount 
     if diff: 
      extraArgs.extend(args[-diff:]) 
      args = args[:-diff] 

     func(*args, **newKwargs) 
     print "%s has extra args=%s"%(func.func_name, extraArgs) 

    return wrap 

@mydeco 
def func1(a, b, c=3): 
    pass 

func1(1,b=2,c=3, d="x") 
func1(1,2,3,"y") 

उत्पादन

func1 has extra args=['x'] 
func1 has extra args=['y'] 
संबंधित मुद्दे