2012-03-12 11 views
6

कभी-कभी मैं किसी ऑब्जेक्ट के लिए गेटर विशेषताओं को लिखना पसंद करता हूं जैसे कि पहली बार उन्हें बुलाया जाता है, भारी भारोत्तोलन एक बार किया जाता है, और वह मूल्य सहेजा जाता है और भविष्य की कॉल पर वापस आ जाता है। उद्देश्य-सी में मैं इस मान को पकड़ने के लिए एक ivar या स्थिर चर का उपयोग करूंगा। कुछ ऐसा:आलसी गेटर्स को लागू करने के लिए पायथन में उचित पैटर्न क्या है?

- (id)foo 
{ 
    if (_foo == nil) 
    { 
     _foo = // hard work to figure out foo 
    } 
    return _foo 
} 

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

def foo(self): 
    if not hasattr(self, "mFoo": 
     self.mFoo = # heavy lifting to compute foo 
    return self.mFoo 

उत्तर

1

आप पाइथन में बिल्कुल उसी पैटर्न का उपयोग कर सकते हैं। आप चिंतित हैं कि my_object.get_foo() करना हर समय पाइथोनिक है या नहीं। शुक्र है, अजगर आप properties के रूप में यहाँ के साथ काम करने के लिए एक अच्छा उपकरण देता है:

class my_class(object): 

    @property 
    def foo(self): 
     # calculate if needed 
     return self._foo 

यह आपको कुछ है जो एक विशेषता के रूप में इस्तेमाल है, भले ही वह एक समारोह के रूप कार्यान्वित किया जाता है की सुविधा देता है। यानी, उपयोगकर्ता my_object.foo करेंगे, और इस बात की परवाह नहीं है कि यह दृश्यों के पीछे एक फ़ंक्शन चला रहा है।

दूसरी बात ध्यान में रखना है कि पायथन सम्मेलन का कहना है कि mFoo के बजाय निजी विशेषताओं को _foo लिखा गया है।

+0

धन्यवाद, @property उस वर्ग पर नहीं जाता है, हालांकि यह करता है? –

+0

@ डैरेन वास्तव में ऐसा नहीं करता है, यही मुझे मध्यरात्रि के गलत पक्ष पर पोस्ट करने के लिए मिलता है। :) मैंने इसे अभी तय कर लिया है। – lvc

1

मैं इस तरह कुछ करना चाहते हैं:

@property 
def foo(self): 
    return self._foo_value if hasattr(self, '_foo_value') else calculate_foo() 

def calculate_foo(self): 
    self._foo_value = # heavy foo calculation 
    return self._foo_value 

अब आप "foo" का उपयोग कर सकते मौसम यह पहले से ही गणना की गई थी या नहीं, का उपयोग करते हुए:

object.foo 
3

के बजाय एक स्पष्ट "hasattr कर "हर बार परीक्षण करें, पाइथन रनटाइम आपके लिए ऐसा करते हैं। अपनी कक्षा में __getattr__ परिभाषित करें, जिसे केवल तब निर्दिष्ट किया जाता है जब एक अपरिभाषित विशेषता का संदर्भ दिया जाता है।

class Sth(object): 
    @property 
    def a(self): 
     print "property a" 
     return self._a 

    def _a_compute(self): 
     # put expensive computation code here 
     print "_a_compute" 
     return 1000 

    def __getattr__(self, attr): 
     print "__getattr__" 
     if attr == '_a': 
      self._a = self._a_compute() 
      return self._a 


ss = Sth() 
print "first time" 
print ss.a 
print 
print "second time" 
print ss.a 

प्रिंट करता है निम्नलिखित:

first time 
property a 
__getattr__ 
_a_compute 
1000 

second time 
property a 
1000 

आप संपत्ति छोड़ देते हैं और 'एक' सीधे है, लेकिन फिर आप दृश्यता के लिए 'एक' विशेषता के रूप में नहीं होगा के लिए __getattr__ परीक्षण हो सकता था आत्मनिरीक्षण या आईडीई स्वत: पूर्ण जैसी चीजों के लिए dir में।

+0

धन्यवाद, मैं पहले __getattr__ और __getattribute__ के बीच उलझन में था। हालांकि यह समझ में आता है। –