2015-01-12 4 views
7

मैं एक ऐसा फ़ंक्शन बनाने का प्रयास कर रहा हूं जो इसे कॉल किए जाने वाले समय की गिनती रखता है, और मैं चाहता हूं कि जानकारी फ़ंक्शन के अंदर ही रहें। मैं बहुत की तरह एक आवरण बनाने की कोशिश की:अपने शरीर के अंदर एक फ़ंक्शन की विशेषता बदलें?

def keep_count(f): 
    f.count = 0 
    @functools.wraps(f) 
    def wrapped_f(*args, **kwargs): 
     f(*args, **kwargs) 
     f.count += 1 
    return wrapped_f 

@keep_count 
def test_f(*args, **kwargs): 
    print(args, kwargs) 

मैंने सोचा था कि यह काम करते हैं, लेकिन मैं एक AttributeError'function' object has no attribute 'count' कह मिला है।

मैं पहले से ही समस्या लगा: यह क्योंकि डेकोरेटर सेट है मेरी test_fwrapped_f (keep_count डेकोरेटर के अंदर परिभाषित) को बराबर करने के लिए, और मैं मूल f की गिनती, जो अब के बाद से test_f संदर्भित करता है प्रयोग किया जाता है में वृद्धि कर रहा हूँ नए समारोह में।

क्या हैकिंग के बिना ऐसा करने का कोई तरीका है?

+2

कक्षा का उपयोग क्यों नहीं करें? इस तरह की एक वर्ग है - –

+0

@AdamSmith में कार्यों को चलाने के लिए एक राज्यव्यापी संदर्भ बनाना, चूंकि अजगर कार्य वस्तुएं हैं, क्या वे राज्य को भी बनाए रख सकते हैं? – wegry

+0

@wegry यकीन है कि वे कर सकते हैं। आप दो बोर्डों को एक साथ नाखून करने के लिए प्लेयर्स की एक जोड़ी का भी उपयोग कर सकते हैं :) –

उत्तर

9

बस f के बजाय wrapped_f पर विशेषता सेट करें। यह आपको समारोह को परिभाषित करने के बाद प्रारंभिक count स्थापित करने के लिए आवश्यकता है, लेकिन है कि कोई बड़ी बात नहीं है:

def keep_count(f): 
    @functools.wraps(f) 
    def wrapped_f(*args, **kwargs): 
     f(*args, **kwargs) 
     wrapped_f.count += 1 
    wrapped_f.count = 0 
    return wrapped_f 
फिर अपने सजाया समारोह के साथ

:

>>> test_f() 
() {} 
>>> test_f.count 
1 
>>> test_f() 
() {} 
>>> test_f.count 
2 

यह काम करता है क्योंकि wrapped_f एक स्थानीय चर keep_count के अंदर है। चूंकि wrapped_f के शरीर में wrapped_f का संदर्भ शामिल है, इसलिए इसे बंद करने के लिए wrapped_f को बंद करने की अनुमति मिलती है।

+0

वाह, मैंने हमेशा सोचा है कि आप अपने अंदर एक फ़ंक्शन का उपयोग नहीं कर सकते ... फिर फिर, जब तक मुझे याद है, मैं रिकर्सिव फ़ंक्शंस का उपयोग कर रहा हूं, यह नहीं देख सकता कि मैं यह क्यों नहीं कर सकता बस किसी तरह की गलत धारणा है। खैर, उत्तर के लिए धन्यवाद, मुझे लगता है कि आप हर दिन पुरानी चीजें में कुछ नया सीखते हैं! :) –

+2

@ मार्कसमेस्कन: आप कम या ज्यादा कर सकते हैं, लेकिन आपको इसके बारे में सावधान रहना होगा, क्योंकि नाम लुकअप अलग-अलग समय पर होता है। – BrenBarn

+0

आह हाँ, धन्यवाद ... :) मैं इसमें खुदाई रखूंगा, जितनी जल्दी हो सके स्वीकार करूँगा। –

संबंधित मुद्दे