2009-07-17 10 views
11

मैंने कुछ कोड लिखा है जो किसी ऑब्जेक्ट के गुणों का उपयोग करता है:पायथन @property बनाम विधि प्रदर्शन - किस का उपयोग करने के लिए?

class Foo: 
    def __init__(self): 
     self.bar = "baz" 
myFoo = Foo() 
print (myFoo.bar) 

अब मैं bar को वापस करने के लिए कुछ फैंसी गणना करना चाहता हूं। मैं @property का उपयोग कर सकता हूं ताकि विधियों को bar गुण के रूप में कार्य किया जा सके, या मैं myFoo.bar() का उपयोग करने के लिए अपने कोड को दोबारा कर सकता हूं।

क्या मुझे वापस जाना चाहिए और मेरे सभी bar एक्सेसों में माता-पिता जोड़ना चाहिए या @property का उपयोग करना चाहिए? मान लें कि मेरा कोड बेस अब छोटा है लेकिन एंट्रॉपी के कारण यह बढ़ेगा।

उत्तर

21

यदि यह तर्कसंगत रूप से वस्तु की संपत्ति/विशेषता है, तो मैं इसे एक संपत्ति के रूप में रखूंगा। यदि यह पैरामीराइज्ड बनने की संभावना है, जिसके द्वारा मेरा मतलब है कि आप myFoo.bar(someArgs) का आह्वान करना चाहते हैं तो बुलेट को काट लें और इसे एक विधि बनाएं।

अधिकांश परिस्थितियों में, प्रदर्शन एक मुद्दा होने की संभावना नहीं है।

7

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

एक विधि है और एक @property का उपयोग कर के बीच चुनने के लिए के रूप में, यह स्वाद की बात है, लेकिन जब से गुण सरल विशेषताओं के रूप में खुद को भेस, विस्तृत कुछ भी नहीं चल रहा होना चाहिए। एक विधि इंगित करती है कि यह एक महंगा ऑपरेशन हो सकता है, और आपके कोड का उपयोग करने वाले डेवलपर्स इसे बार-बार लाने के बजाय मूल्य को कैश करने पर विचार करेंगे।

तो फिर, प्रदर्शन पर न जाएं, हमेशा बनाए रखने योग्यता बनाम प्रदर्शन पर विचार करें। समय बीतने के साथ कंप्यूटर तेजी से और तेज़ हो जाते हैं। कोड की पठनीयता के लिए यह खड़ा नहीं है।

संक्षेप में, यदि आप एक साधारण गणना मूल्य प्राप्त करना चाहते हैं, @property एक उत्कृष्ट विकल्प है; यदि आप एक विस्तृत मूल्य की गणना करना चाहते हैं, तो एक विधि इंगित करती है कि बेहतर।

1

यह वही है जो @property के लिए है।

3

मैं रिफैक्टरिंग के लिए जाऊंगा, लेकिन केवल स्टाइल के मामले के लिए - यह मुझे स्पष्ट लगता है कि "फैंसी गणना" एक विधि कॉल के साथ चल रही है, जबकि मैं एक संपत्ति को लगभग नो-ऑप होने की उम्मीद करता हूं , लेकिन यह स्वाद का मामला है।

सजावट के प्रदर्शन के बारे में चिंता न करें ... यदि आपको लगता है कि यह एक समस्या हो सकती है, तो दोनों मामलों में प्रदर्शन को मापें और देखें कि यह कितना जोड़ता है (मेरा अनुमान है कि तुलना में यह पूरी तरह से नगण्य होगा अपनी फैंसी गणना के लिए)।

17

प्रदर्शन के बारे में सोच रहे हैं कि अनावश्यक है जब यह मापने के लिए बहुत आसान है:

$ python -mtimeit -s'class X(object): 
> @property 
> def y(self): return 23 
> x=X()' 'x.y' 
1000000 loops, best of 3: 0.685 usec per loop 
$ python -mtimeit -s'class X(object): 

    def y(self): return 23 
x=X()' 'x.y()' 
1000000 loops, best of 3: 0.447 usec per loop 
$ 

(मेरी धीमी गति से लैपटॉप पर - अगर आप क्यों 2 मामले माध्यमिक खोल संकेतों का भी नहीं है, क्योंकि मैं बनाया है यह पहली बार बैश में एक अप-तीर के साथ है, और यह लाइनबैक संरचना को दोहराता है लेकिन संकेत नहीं देता! -)।

तो जब तक कि आप ऐसे मामले में न हों जहां आप 200+ नैनोसेकंड जानते हों या इससे कोई फर्क नहीं पड़ता (एक तंग आंतरिक लूप जिसे आप अत्यंत अनुकूलित करने की कोशिश कर रहे हैं), आप संपत्ति दृष्टिकोण का उपयोग कर सकते हैं; यदि आप मूल्य प्राप्त करने के लिए कुछ गणना करते हैं, तो 200+ नैनोसेकंड निश्चित रूप से लिया गया कुल समय का एक छोटा अंश बन जाएगा।

मैं अन्य उत्तरों से सहमत हूं कि यदि गणना बहुत भारी हो जाती है, या आप कभी भी पैरामीटर चाहते हैं, तो एक विधि बेहतर है - इसी तरह, यदि आप कभी भी कॉल करने योग्य को कहीं भी छीनने की ज़रूरत है, तो मैं जोड़ूंगा लेकिन इसे बाद में कॉल करें, और अन्य फैंसी कार्यात्मक प्रोग्रामिंग चालें; लेकिन मैं प्रदर्शन बिंदु को मात्रात्मक रूप से बनाना चाहता था, क्योंकि timeit इस तरह के माप को इतना आसान बनाता है! -)

+0

और यदि आप 'x' इंस्टेंस सृजन की गणना नहीं करते हैं, तो परिणाम भी करीब (प्रतिशत-वार) होते हैं, (मैंने iPython में '% timeit' जादू फ़ंक्शन का उपयोग किया): ' x = X();% timeit x.y' -> 1000000 लूप, 3: 211 एनएस प्रति लूप का सर्वश्रेष्ठ; 'एक्स = एक्स(); % timeit x.y() '-> 10000000 लूप, 3: 16 9 एनएस प्रति लूप का सर्वोत्तम –

2

मैं यहां से अधिकतर लोगों के साथ सहमत हूं, मैंने कुछ साल पहले पाइथन में हाइड्रोलोजिक मॉडल बनाने के दौरान बहुत अधिक माप किया था और पाया कि @property का उपयोग करने से गति पूरी तरह से गणना द्वारा छायांकित थी।

उदाहरण के लिए, विधि स्थानीय चर बनाने ("डॉट कारक" मेरी गणना में दूर करने @property को हटाने (इन परिणामों एक मध्य पैमाने आवेदन के औसत से कर रहे हैं) की तुलना में अधिक परिमाण के लगभग एक आदेश द्वारा प्रदर्शन में वृद्धि हुई।

मैं ऑप्टिमाइज़ेशन के लिए कहीं और देखता हूं, जब आवश्यक हो, और शुरुआत में अच्छा, रखरखाव योग्य कोड प्राप्त करने पर ध्यान केंद्रित करें। इस बिंदु पर, यदि @property आपके मामले में अंतर्ज्ञानी है, तो इसका उपयोग करें। यदि नहीं, तो एक विधि बनाएं।

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